Merge branch 'testing' of git@gitorious.org:statusnet/mainline into 0.9.x

This commit is contained in:
Brion Vibber 2010-04-06 15:22:23 -07:00
commit 5dc169260d
27 changed files with 6427 additions and 74 deletions

View File

@ -168,4 +168,11 @@ class BlockAction extends ProfileFormAction
return; return;
} }
} }
function showScripts()
{
parent::showScripts();
$this->autofocus('form_action-yes');
}
} }

View File

@ -214,5 +214,12 @@ class GroupblockAction extends Action
303); 303);
} }
} }
function showScripts()
{
parent::showScripts();
$this->autofocus('form_action-yes');
}
} }

View File

@ -212,6 +212,7 @@ class GroupMemberListItem extends ProfileListItem
} }
} }
function showGroupBlockForm() function showGroupBlockForm()
{ {
$user = common_current_user(); $user = common_current_user();
@ -224,7 +225,24 @@ class GroupMemberListItem extends ProfileListItem
$bf->show(); $bf->show();
$this->out->elementEnd('li'); $this->out->elementEnd('li');
} }
}
function linkAttributes()
{
$aAttrs = parent::linkAttributes();
if (common_config('nofollow', 'members')) {
$aAttrs['rel'] .= ' nofollow';
}
return $aAttrs;
}
function homepageAttributes()
{
if (common_config('nofollow', 'members')) {
$aAttrs['rel'] = 'nofollow';
}
} }
} }

View File

@ -32,8 +32,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1); exit(1);
} }
require_once INSTALLDIR.'/lib/profilelist.php';
/** /**
* This class outputs a paginated list of profiles self-tagged with a given tag * This class outputs a paginated list of profiles self-tagged with a given tag
* *
@ -124,8 +122,8 @@ class PeopletagAction extends Action
$profile->query(sprintf($qry, $this->tag, $lim)); $profile->query(sprintf($qry, $this->tag, $lim));
$pl = new ProfileList($profile, $this); $ptl = new PeopleTagList($profile, $this); // pass the ammunition
$cnt = $pl->show(); $cnt = $ptl->show();
$this->pagination($this->page > 1, $this->pagination($this->page > 1,
$cnt > PROFILES_PER_PAGE, $cnt > PROFILES_PER_PAGE,
@ -146,3 +144,33 @@ class PeopletagAction extends Action
} }
} }
class PeopleTagList extends ProfileList
{
function newListItem($profile)
{
return new PeopleTagListItem($profile, $this->action);
}
}
class PeopleTagListItem extends ProfileListItem
{
function linkAttributes()
{
$aAttrs = parent::linkAttributes();
if (common_config('nofollow', 'peopletag')) {
$aAttrs['rel'] .= ' nofollow';
}
return $aAttrs;
}
function homepageAttributes()
{
if (common_config('nofollow', 'peopletag')) {
$aAttrs['rel'] = 'nofollow';
}
}
}

View File

@ -388,18 +388,23 @@ class ShowgroupAction extends GroupDesignAction
$this->elementStart('div', array('id' => 'entity_members', $this->elementStart('div', array('id' => 'entity_members',
'class' => 'section')); 'class' => 'section'));
$this->element('h2', null, _('Members')); if (Event::handle('StartShowGroupMembersMiniList', array($this))) {
$pml = new ProfileMiniList($member, $this); $this->element('h2', null, _('Members'));
$cnt = $pml->show();
if ($cnt == 0) {
$this->element('p', null, _('(None)'));
}
if ($cnt > MEMBERS_PER_SECTION) { $gmml = new GroupMembersMiniList($member, $this);
$this->element('a', array('href' => common_local_url('groupmembers', $cnt = $gmml->show();
array('nickname' => $this->group->nickname))), if ($cnt == 0) {
_('All members')); $this->element('p', null, _('(None)'));
}
if ($cnt > MEMBERS_PER_SECTION) {
$this->element('a', array('href' => common_local_url('groupmembers',
array('nickname' => $this->group->nickname))),
_('All members'));
}
Event::handle('EndShowGroupMembersMiniList', array($this));
} }
$this->elementEnd('div'); $this->elementEnd('div');
@ -502,3 +507,26 @@ class GroupAdminSection extends ProfileSection
return null; return null;
} }
} }
class GroupMembersMiniList extends ProfileMiniList
{
function newListItem($profile)
{
return new GroupMembersMiniListItem($profile, $this->action);
}
}
class GroupMembersMiniListItem extends ProfileMiniListItem
{
function linkAttributes()
{
$aAttrs = parent::linkAttributes();
if (common_config('nofollow', 'members')) {
$aAttrs['rel'] .= ' nofollow';
}
return $aAttrs;
}
}

View File

@ -163,4 +163,22 @@ class SubscribersListItem extends SubscriptionListItem
$bf->show(); $bf->show();
} }
} }
function linkAttributes()
{
$aAttrs = parent::linkAttributes();
if (common_config('nofollow', 'subscribers')) {
$aAttrs['rel'] .= ' nofollow';
}
return $aAttrs;
}
function homepageAttributes()
{
if (common_config('nofollow', 'subscribers')) {
$aAttrs['rel'] = 'nofollow';
}
}
} }

View File

@ -299,4 +299,8 @@ $default =
), ),
'api' => 'api' =>
array('realm' => null), array('realm' => null),
'nofollow' =>
array('subscribers' => true,
'members' => true,
'peopletag' => true),
); );

View File

@ -139,25 +139,30 @@ class ProfileAction extends OwnerDesignAction
$this->elementStart('div', array('id' => 'entity_subscribers', $this->elementStart('div', array('id' => 'entity_subscribers',
'class' => 'section')); 'class' => 'section'));
$this->element('h2', null, _('Subscribers')); if (Event::handle('StartShowSubscribersMiniList', array($this))) {
$cnt = 0; $this->element('h2', null, _('Subscribers'));
if (!empty($profile)) { $cnt = 0;
$pml = new ProfileMiniList($profile, $this);
$cnt = $pml->show(); if (!empty($profile)) {
if ($cnt == 0) { $sml = new SubscribersMiniList($profile, $this);
$this->element('p', null, _('(None)')); $cnt = $sml->show();
if ($cnt == 0) {
$this->element('p', null, _('(None)'));
}
} }
}
if ($cnt > PROFILES_PER_MINILIST) { if ($cnt > PROFILES_PER_MINILIST) {
$this->elementStart('p'); $this->elementStart('p');
$this->element('a', array('href' => common_local_url('subscribers', $this->element('a', array('href' => common_local_url('subscribers',
array('nickname' => $this->profile->nickname)), array('nickname' => $this->profile->nickname)),
'class' => 'more'), 'class' => 'more'),
_('All subscribers')); _('All subscribers'));
$this->elementEnd('p'); $this->elementEnd('p');
}
Event::handle('EndShowSubscribersMiniList', array($this));
} }
$this->elementEnd('div'); $this->elementEnd('div');
@ -266,3 +271,23 @@ class ProfileAction extends OwnerDesignAction
} }
} }
class SubscribersMiniList extends ProfileMiniList
{
function newListItem($profile)
{
return new SubscribersMiniListItem($profile, $this->action);
}
}
class SubscribersMiniListItem extends ProfileMiniListItem
{
function linkAttributes()
{
$aAttrs = parent::linkAttributes();
if (common_config('nofollow', 'subscribers')) {
$aAttrs['rel'] .= ' nofollow';
}
return $aAttrs;
}
}

View File

@ -181,9 +181,8 @@ class ProfileListItem extends Widget
function showAvatar() function showAvatar()
{ {
$avatar = $this->profile->getAvatar(AVATAR_STREAM_SIZE); $avatar = $this->profile->getAvatar(AVATAR_STREAM_SIZE);
$this->out->elementStart('a', array('href' => $this->profile->profileurl, $aAttrs = $this->linkAttributes();
'class' => 'url entry-title', $this->out->elementStart('a', $aAttrs);
'rel' => 'contact'));
$this->out->element('img', array('src' => ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE), $this->out->element('img', array('src' => ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE),
'class' => 'photo avatar', 'class' => 'photo avatar',
'width' => AVATAR_STREAM_SIZE, 'width' => AVATAR_STREAM_SIZE,
@ -223,8 +222,8 @@ class ProfileListItem extends Widget
{ {
if (!empty($this->profile->homepage)) { if (!empty($this->profile->homepage)) {
$this->out->text(' '); $this->out->text(' ');
$this->out->elementStart('a', array('href' => $this->profile->homepage, $aAttrs = $this->homepageAttributes();
'class' => 'url')); $this->out->elementStart('a', $aAttrs);
$this->out->raw($this->highlight($this->profile->homepage)); $this->out->raw($this->highlight($this->profile->homepage));
$this->out->elementEnd('a'); $this->out->elementEnd('a');
} }
@ -299,4 +298,17 @@ class ProfileListItem extends Widget
{ {
return htmlspecialchars($text); return htmlspecialchars($text);
} }
function linkAttributes()
{
return array('href' => $this->profile->profileurl,
'class' => 'url entry-title',
'rel' => 'contact');
}
function homepageAttributes()
{
return array('href' => $this->profile->homepage,
'class' => 'url');
}
} }

View File

@ -81,20 +81,36 @@ class ProfileMiniListItem extends ProfileListItem
function show() function show()
{ {
$this->out->elementStart('li', 'vcard'); $this->out->elementStart('li', 'vcard');
$this->out->elementStart('a', array('title' => $this->profile->getBestName(), if (Event::handle('StartProfileListItemProfileElements', array($this))) {
'href' => $this->profile->profileurl, if (Event::handle('StartProfileListItemAvatar', array($this))) {
'rel' => 'contact member', $aAttrs = $this->linkAttributes();
'class' => 'url')); $this->out->elementStart('a', $aAttrs);
$avatar = $this->profile->getAvatar(AVATAR_MINI_SIZE); $avatar = $this->profile->getAvatar(AVATAR_MINI_SIZE);
$this->out->element('img', array('src' => (($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_MINI_SIZE)), $this->out->element('img', array('src' => (($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_MINI_SIZE)),
'width' => AVATAR_MINI_SIZE, 'width' => AVATAR_MINI_SIZE,
'height' => AVATAR_MINI_SIZE, 'height' => AVATAR_MINI_SIZE,
'class' => 'avatar photo', 'class' => 'avatar photo',
'alt' => ($this->profile->fullname) ? 'alt' => ($this->profile->fullname) ?
$this->profile->fullname : $this->profile->fullname :
$this->profile->nickname)); $this->profile->nickname));
$this->out->element('span', 'fn nickname', $this->profile->nickname); $this->out->element('span', 'fn nickname', $this->profile->nickname);
$this->out->elementEnd('a'); $this->out->elementEnd('a');
$this->out->elementEnd('li'); Event::handle('EndProfileListItemAvatar', array($this));
}
$this->out->elementEnd('li');
}
}
// default; overridden for nofollow lists
function linkAttributes()
{
$aAttrs = parent::linkAttributes();
$aAttrs['title'] = $this->profile->getBestName();
$aAttrs['rel'] = 'contact member'; // @todo: member? always?
$aAttrs['class'] = 'url';
return $aAttrs;
} }
} }

View File

@ -1,9 +1,56 @@
Localizations for StatusNet are being maintained through TranslateWiki: Localizations for StatusNet are being maintained through TranslateWiki:
http://translatewiki.net/wiki/Translating:StatusNet http://translatewiki.net/wiki/Translating:StatusNet
Note if you are working with a direct git checkout, you will need to build Ongoing translation work should be done there to ensure updates are
the binary .mo files from the .po source files for translations to work integrated into future versions of StatusNet.
in the web app.
If gettext and GNU make are installed, you can simply run 'make' in this
directory to build them. == Building runtime translations ==
If you are working with a direct git checkout or have customized any
message files, you will need to build binary .mo files from the .po
source files for translations to work in the web app.
If gettext and GNU make are installed, you can simply run 'make' in the
main StatusNet directory, and all core and plugin localizations will be
recompiled.
== Customization ==
User interface texts in any language can be customized by editing the
texts in the .po source files, then rebuilding the binary .mo files
used at runtime.
The default/US English texts can be overridden by adding "translations"
to en/LC_MESSAGES/statusnet.po.
Note that texts you change in one language will not affect other
languages, which are selected based on visitors' browser preferences.
If you customizations include important information or links,
you may wish to disable languages that you haven't customized so that
visitors always get your text.
To disable all non-English languages add this to your config.php (you
will need to edit both the en and en_GB files):
$config['site']['languages'] = array(
'en-us' => array('q' => 1, 'lang' => 'en', 'name' => 'English (US)', 'direction' => 'ltr'),
'en-gb' => array('q' => 1, 'lang' => 'en_GB', 'name' => 'English (British)', 'direction' => 'ltr'),
'en' => array('q' => 1, 'lang' => 'en', 'name' => 'English (US)', 'direction' => 'ltr'),
);
To disable everything including British English variant:
$config['site']['languages'] = array(
'en' => array('q' => 1, 'lang' => 'en', 'name' => 'English', 'direction' => 'ltr'),
);
== Plugins ==
This locale directory contains translations for the core StatusNet
software only. Plugins may have their own locale subdirectories and
their own .po and .mo files as well, so if customizing you may need
to poke at those as well.

File diff suppressed because it is too large Load Diff

View File

@ -55,9 +55,13 @@ class GeonamesPlugin extends Plugin
public $username = null; public $username = null;
public $token = null; public $token = null;
public $expiry = 7776000; // 90-day expiry public $expiry = 7776000; // 90-day expiry
public $timeout = 2; // Web service timeout in seconds.
public $timeoutWindow = 60; // Further lookups in this process will be disabled for N seconds after a timeout.
public $cachePrefix = null; // Optional shared memcache prefix override public $cachePrefix = null; // Optional shared memcache prefix override
// to share lookups between local instances. // to share lookups between local instances.
protected $lastTimeout = null; // timestamp of last web service timeout
/** /**
* convert a name into a Location object * convert a name into a Location object
* *
@ -437,9 +441,21 @@ class GeonamesPlugin extends Plugin
function getGeonames($method, $params) function getGeonames($method, $params)
{ {
$client = HTTPClient::start(); if ($this->lastTimeout && (time() - $this->lastTimeout < $this->timeoutWindow)) {
throw new Exception("skipping due to recent web service timeout");
}
$result = $client->get($this->wsUrl($method, $params)); $client = HTTPClient::start();
$client->setConfig('connect_timeout', $this->timeout);
$client->setConfig('timeout', $this->timeout);
try {
$result = $client->get($this->wsUrl($method, $params));
} catch (Exception $e) {
common_log(LOG_ERR, __METHOD__ . ": " . $e->getMessage());
$this->lastTimeout = time();
throw $e;
}
if (!$result->isOk()) { if (!$result->isOk()) {
throw new Exception("HTTP error code " . $result->code); throw new Exception("HTTP error code " . $result->code);

View File

@ -65,6 +65,26 @@ class MeteorPlugin extends RealtimePlugin
parent::__construct(); parent::__construct();
} }
/**
* Pull settings from config file/database if set.
*/
function initialize()
{
$settings = array('webserver',
'webport',
'controlport',
'controlserver',
'channelbase');
foreach ($settings as $name) {
$val = common_config('meteor', $name);
if ($val !== false) {
$this->$name = $val;
}
}
return parent::initialize();
}
function _getScripts() function _getScripts()
{ {
$scripts = parent::_getScripts(); $scripts = parent::_getScripts();

View File

@ -73,9 +73,11 @@ class MobileProfilePlugin extends WAP20Plugin
$this->serveMobile = true; $this->serveMobile = true;
} else { } else {
// If they like the WAP 2.0 mimetype, serve them MP // If they like the WAP 2.0 mimetype, serve them MP
if (strstr('application/vnd.wap.xhtml+xml', $type) !== false) { // @fixme $type is undefined, making this if case useless and spewing errors.
$this->serveMobile = true; // What's the intent?
} else { //if (strstr('application/vnd.wap.xhtml+xml', $type) !== false) {
// $this->serveMobile = true;
//} else {
// If they are a mobile device that supports WAP 2.0, // If they are a mobile device that supports WAP 2.0,
// serve them MP // serve them MP
@ -139,8 +141,19 @@ class MobileProfilePlugin extends WAP20Plugin
'windows ce' 'windows ce'
); );
$blacklist = array(
'ipad', // Larger screen handles the full theme fairly well.
);
$httpuseragent = strtolower($_SERVER['HTTP_USER_AGENT']); $httpuseragent = strtolower($_SERVER['HTTP_USER_AGENT']);
foreach ($blacklist as $md) {
if (strstr($httpuseragent, $md) !== false) {
$this->serveMobile = false;
return true;
}
}
foreach ($this->mobiledevices as $md) { foreach ($this->mobiledevices as $md) {
if (strstr($httpuseragent, $md) !== false) { if (strstr($httpuseragent, $md) !== false) {
$this->setMobileFeatures($httpuseragent); $this->setMobileFeatures($httpuseragent);
@ -149,7 +162,7 @@ class MobileProfilePlugin extends WAP20Plugin
break; break;
} }
} }
} //}
// If they are okay with MP, and the site has a mobile server, // If they are okay with MP, and the site has a mobile server,
// redirect there // redirect there
@ -167,7 +180,9 @@ class MobileProfilePlugin extends WAP20Plugin
return true; return true;
} }
if (!$type) { // @fixme $type is undefined, making this if case useless and spewing errors.
// What's the intent?
//if (!$type) {
$httpaccept = isset($_SERVER['HTTP_ACCEPT']) ? $httpaccept = isset($_SERVER['HTTP_ACCEPT']) ?
$_SERVER['HTTP_ACCEPT'] : null; $_SERVER['HTTP_ACCEPT'] : null;
@ -180,7 +195,7 @@ class MobileProfilePlugin extends WAP20Plugin
throw new ClientException(_('This page is not available in a '. throw new ClientException(_('This page is not available in a '.
'media type you accept'), 406); 'media type you accept'), 406);
} }
} //}
header('Content-Type: '.$type); header('Content-Type: '.$type);
@ -221,9 +236,12 @@ class MobileProfilePlugin extends WAP20Plugin
function onStartShowHeadElements($action) function onStartShowHeadElements($action)
{ {
if (!$action->serveMobile) { // @fixme nothing appears to set a serveMobile on any action,
return true; // so this is useless and spews errors. Is this supposed to be
} // checking $this?
//if (!$action->serveMobile) {
// return true;
//}
$action->showTitle(); $action->showTitle();
$action->showShortcutIcon(); $action->showShortcutIcon();

View File

@ -50,20 +50,47 @@ $encGroup = str_replace($marker, '%', $encGroup);
$sql = "SELECT * FROM ostatus_profile WHERE uri LIKE '%s' OR uri LIKE '%s'"; $sql = "SELECT * FROM ostatus_profile WHERE uri LIKE '%s' OR uri LIKE '%s'";
$oprofile->query(sprintf($sql, $encProfile, $encGroup)); $oprofile->query(sprintf($sql, $encProfile, $encGroup));
echo "Found $oprofile->N bogus ostatus_profile entries for local users and groups:\n"; $count = $oprofile->N;
echo "Found $count bogus ostatus_profile entries shadowing local users and groups:\n";
while ($oprofile->fetch()) { while ($oprofile->fetch()) {
echo "$oprofile->uri"; $uri = $oprofile->uri;
if (preg_match('!/group/(\d+)/id!', $oprofile->uri, $matches)) {
if ($dry) { $id = intval($matches[1]);
echo " (unchanged)\n"; $group = Local_group::staticGet('group_id', $id);
if ($group) {
$nick = $group->nickname;
} else {
$nick = '<deleted>';
}
echo "group $id ($nick) hidden by $uri";
} else if (preg_match('!/user/(\d+)!', $uri, $matches)) {
$id = intval($matches[1]);
$user = User::staticGet('id', $id);
if ($user) {
$nick = $user->nickname;
} else {
$nick = '<deleted>';
}
echo "user $id ($nick) hidden by $uri";
} else { } else {
echo " removing bogus ostatus_profile entry..."; echo "$uri matched query, but we don't recognize it.\n";
continue;
}
if ($dry) {
echo " - skipping\n";
} else {
echo " - removing bogus ostatus_profile entry...";
$evil = clone($oprofile); $evil = clone($oprofile);
$evil->delete(); $evil->delete();
echo " ok\n"; echo " ok\n";
} }
} }
echo "done.\n"; if ($count && $dry) {
echo "NO CHANGES MADE -- To delete the bogus entries, run again without --dry-run option.\n";
} else {
echo "done.\n";
}

View File

@ -34,7 +34,7 @@ function update_core($dir, $domain)
xgettext \ xgettext \
--from-code=UTF-8 \ --from-code=UTF-8 \
--default-domain=$domain \ --default-domain=$domain \
--output=locale/$domain.po \ --output=locale/$domain.pot \
--language=PHP \ --language=PHP \
--add-comments=TRANS \ --add-comments=TRANS \
--keyword="_m:1,1t" \ --keyword="_m:1,1t" \
@ -64,7 +64,7 @@ function do_update_plugin($dir, $domain)
xgettext \ xgettext \
--from-code=UTF-8 \ --from-code=UTF-8 \
--default-domain=$domain \ --default-domain=$domain \
--output=locale/$domain.po \ --output=locale/$domain.pot \
--language=PHP \ --language=PHP \
--add-comments=TRANS \ --add-comments=TRANS \
--keyword='' \ --keyword='' \