diff --git a/actions/all.php b/actions/all.php index 2826319c0d..74a0059346 100644 --- a/actions/all.php +++ b/actions/all.php @@ -55,17 +55,17 @@ class AllAction extends ProfileAction function prepare($args) { parent::prepare($args); - $cur = common_current_user(); - if (!empty($cur) && $cur->id == $this->user->id) { - $this->notice = $this->user->noticeInboxThreaded(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); - } else { - $this->notice = $this->user->noticesWithFriendsThreaded(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); - } + $stream = new InboxNoticeStream($this->user); + + $this->notice = $stream->getNotices(($this->page-1)*NOTICES_PER_PAGE, + NOTICES_PER_PAGE + 1, + null, + null); if ($this->page > 1 && $this->notice->N == 0) { // TRANS: Server error when page not found (404). - $this->serverError(_('No such page.'), $code = 404); + $this->serverError(_('No such page.'), 404); } return true; diff --git a/actions/allrss.php b/actions/allrss.php index 573bb4eb2f..6d82e551e7 100644 --- a/actions/allrss.php +++ b/actions/allrss.php @@ -83,16 +83,9 @@ class AllrssAction extends Rss10Action */ function getNotices($limit=0) { - $cur = common_current_user(); - $user = $this->user; + $stream = new InboxNoticeStream($this->user); + $notice = $stream->getNotices(0, $limit, null, null); - if (!empty($cur) && $cur->id == $user->id) { - $notice = $this->user->noticeInbox(0, $limit); - } else { - $notice = $this->user->noticesWithFriends(0, $limit); - } - - $notice = $user->noticesWithFriends(0, $limit); $notices = array(); while ($notice->fetch()) { diff --git a/actions/apitimelinefriends.php b/actions/apitimelinefriends.php index 00eb4de502..279265a30e 100644 --- a/actions/apitimelinefriends.php +++ b/actions/apitimelinefriends.php @@ -289,15 +289,12 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction { $notices = array(); - if (!empty($this->auth_user) && $this->auth_user->id == $this->user->id) { - $notice = $this->user->ownFriendsTimeline(($this->page-1) * $this->count, - $this->count, $this->since_id, - $this->max_id); - } else { - $notice = $this->user->friendsTimeline(($this->page-1) * $this->count, - $this->count, $this->since_id, - $this->max_id); - } + $stream = new InboxNoticeStream($this->user); + + $notice = $stream->getNotices(($this->page-1) * $this->count, + $this->count, + $this->since_id, + $this->max_id); while ($notice->fetch()) { $notices[] = clone($notice); diff --git a/actions/apitimelinehome.php b/actions/apitimelinehome.php index 96642cbfab..3c18a5b0bf 100644 --- a/actions/apitimelinehome.php +++ b/actions/apitimelinehome.php @@ -192,19 +192,12 @@ class ApiTimelineHomeAction extends ApiBareAuthAction { $notices = array(); - if (!empty($this->auth_user) && $this->auth_user->id == $this->user->id) { - $notice = $this->user->noticeInbox( - ($this->page-1) * $this->count, - $this->count, $this->since_id, - $this->max_id - ); - } else { - $notice = $this->user->noticesWithFriends( - ($this->page-1) * $this->count, - $this->count, $this->since_id, - $this->max_id - ); - } + $stream = new InboxNoticeStream($this->user); + + $notice = $stream->getNotices(($this->page-1) * $this->count, + $this->count, + $this->since_id, + $this->max_id); while ($notice->fetch()) { $notices[] = clone($notice); diff --git a/classes/Inbox.php b/classes/Inbox.php index feaead249b..336bba048c 100644 --- a/classes/Inbox.php +++ b/classes/Inbox.php @@ -157,168 +157,11 @@ class Inbox extends Memcached_DataObject } } - function stream($user_id, $offset, $limit, $since_id, $max_id, $own=false) - { - $inbox = Inbox::staticGet('user_id', $user_id); - - if (empty($inbox)) { - $inbox = Inbox::fromNoticeInbox($user_id); - if (empty($inbox)) { - return array(); - } else { - $inbox->encache(); - } - } - - $ids = $inbox->unpack(); - - if (!empty($since_id)) { - $newids = array(); - foreach ($ids as $id) { - if ($id > $since_id) { - $newids[] = $id; - } - } - $ids = $newids; - } - - if (!empty($max_id)) { - $newids = array(); - foreach ($ids as $id) { - if ($id <= $max_id) { - $newids[] = $id; - } - } - $ids = $newids; - } - - $ids = array_slice($ids, $offset, $limit); - - return $ids; - } - - /** - * Wrapper for Inbox::stream() and Notice::getStreamByIds() returning - * additional items up to the limit if we were short due to deleted - * notices still being listed in the inbox. - * - * This is meant to assist threaded views, and optimizes paging for - * threadness. Not ideal for very late pages, as we have to bump about - * through all previous items. - * - * Should avoid duplicates in paging, though. - * - * @param int $user_id - * @param int $offset skip past the most recent N notices (after since_id checks) - * @param int $limit - * @param mixed $since_id return only notices after but not including this id - * @param mixed $max_id return only notices up to and including this id - * @param mixed $own ignored? - * @return array of Notice objects - * - * @todo consider repacking the inbox when this happens? - * @fixme reimplement $own if we need it? - */ - function streamNoticesThreaded($user_id, $offset, $limit, $since_id, $max_id, $own=false) - { - // So what we want is: - // * slurp in the beginning of the notice list - // * filter out deleted notices - // * replace any reply notices with their conversation roots - // * filter out any duplicate conversations - // * return $limit notices after skipping $offset from the most recent - - $ids = self::stream($user_id, 0, self::MAX_NOTICES, $since_id, $max_id, $own); - - // Do a bulk lookup for the first $limit items - // Fast path when nothing's deleted. - $firstChunk = array_slice($ids, 0, $offset + $limit); - $notices = NoticeStream::getStreamByIds($firstChunk); - - assert($notices instanceof ArrayWrapper); - $items = $notices->_items; - - // Extract the latest non-deleted item in each convo - $noticeByConvo = array(); - foreach ($items as $notice) { - if (empty($noticeByConvo[$notice->conversation])) { - $noticeByConvo[$notice->conversation] = $notice; - } - } - - $wanted = count($firstChunk); // raw entry count in the inbox up to our $limit - // There were deleted notices, we'll need to look for more. - $remainder = array_slice($ids, $limit); - - for ($i = $offset + $limit; count($noticeByConvo) < $wanted && $i < count($ids); $i++) { - $notice = Notice::staticGet($ids[$i]); - if ($notice && empty($noticeByConvo[$notice->conversation])) { - $noticeByConvo[$notice->conversation] = $notice; - } - } - - $slice = array_slice($noticeByConvo, $offset, $limit, false); - return new ArrayWrapper($slice); - } - - /** - * Wrapper for Inbox::stream() and Notice::getStreamByIds() returning - * additional items up to the limit if we were short due to deleted - * notices still being listed in the inbox. - * - * The fast path (when no items are deleted) should be just as fast; the - * offset parameter is applied *before* lookups for maximum efficiency. - * - * This means offset-based paging may show duplicates, but similar behavior - * already exists when new notices are posted between page views, so we - * think people will be ok with this until id-based paging is introduced - * to the user interface. - * - * @param int $user_id - * @param int $offset skip past the most recent N notices (after since_id checks) - * @param int $limit - * @param mixed $since_id return only notices after but not including this id - * @param mixed $max_id return only notices up to and including this id - * @param mixed $own ignored? - * @return array of Notice objects - * - * @todo consider repacking the inbox when this happens? - * @fixme reimplement $own if we need it? - */ - function streamNotices($user_id, $offset, $limit, $since_id, $max_id, $own=false) - { - $ids = self::stream($user_id, $offset, self::MAX_NOTICES, $since_id, $max_id, $own); - - // Do a bulk lookup for the first $limit items - // Fast path when nothing's deleted. - $firstChunk = array_slice($ids, 0, $limit); - $notices = NoticeStream::getStreamByIds($firstChunk); - - $wanted = count($firstChunk); // raw entry count in the inbox up to our $limit - if ($notices->N >= $wanted) { - return $notices; - } - - // There were deleted notices, we'll need to look for more. - assert($notices instanceof ArrayWrapper); - $items = $notices->_items; - $remainder = array_slice($ids, $limit); - - while (count($items) < $wanted && count($remainder) > 0) { - $notice = Notice::staticGet(array_shift($remainder)); - if ($notice) { - $items[] = $notice; - } else { - } - } - return new ArrayWrapper($items); - } - /** * Saves a list of integer notice_ids into a packed blob in this object. * @param array $ids list of integer notice_ids */ - protected function pack(array $ids) + function pack(array $ids) { $this->notice_ids = call_user_func_array('pack', array_merge(array('N*'), $ids)); } @@ -326,7 +169,7 @@ class Inbox extends Memcached_DataObject /** * @return array of integer notice_ids */ - protected function unpack() + function unpack() { return unpack('N*', $this->notice_ids); } diff --git a/classes/Notice.php b/classes/Notice.php index df2ab96d05..cfc00b0871 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -2297,6 +2297,21 @@ class Notice extends Memcached_DataObject * @return boolean whether the profile is in the notice's scope */ function inScope($profile) + { + $keypart = sprintf('notice:in-scope-for:%d:%d', $this->id, $profile->id); + + $result = self::cacheGet($keypart); + + if ($result === false) { + $bResult = $this->_inScope($profile); + $result = ($bResult) ? 1 : 0; + self::cacheSet($keypart, $result, 0, 300); + } + + return ($result == 1) ? true : false; + } + + protected function _inScope($profile) { // If there's no scope, anyone (even anon) is in scope. diff --git a/classes/User.php b/classes/User.php index c229d70929..2f3ce4430a 100644 --- a/classes/User.php +++ b/classes/User.php @@ -478,34 +478,45 @@ class User extends Memcached_DataObject return Fave::stream($this->id, $offset, $limit, $own, $since_id, $max_id); } + function noticeInbox($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0) + { + $stream = new InboxNoticeStream($this); + return $stream->getNotices($offset, $limit, $since_id, $before_id); + } + + // DEPRECATED, use noticeInbox() + function noticesWithFriends($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0) { - return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, false); + return $this->noticeInbox($offset, $limit, $since_id, $before_id); } + // DEPRECATED, use noticeInbox() + function noticesWithFriendsThreaded($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0) { - return Inbox::streamNoticesThreaded($this->id, $offset, $limit, $since_id, $before_id, false); + return $this->noticeInbox($offset, $limit, $since_id, $before_id); } - function noticeInbox($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0) - { - return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, true); - } + // DEPRECATED, use noticeInbox() function noticeInboxThreaded($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0) { - return Inbox::streamNoticesThreaded($this->id, $offset, $limit, $since_id, $before_id, true); + return $this->noticeInbox($offset, $limit, $since_id, $before_id); } + // DEPRECATED, use noticeInbox() + function friendsTimeline($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0) { - return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, false); + return $this->noticeInbox($offset, $limit, $since_id, $before_id); } + // DEPRECATED, use noticeInbox() + function ownFriendsTimeline($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0) { - return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, true); + $this->noticeInbox($offset, $limit, $since_id, $before_id); } function blowFavesCache() diff --git a/lib/inboxnoticestream.php b/lib/inboxnoticestream.php new file mode 100644 index 0000000000..09c3edb281 --- /dev/null +++ b/lib/inboxnoticestream.php @@ -0,0 +1,135 @@ +. + * + * @category Cache + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + // This check helps protect against security problems; + // your code file can't be executed directly from the web. + exit(1); +} + +/** + * Stream of notices for the user's inbox + * + * @category General + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ +class InboxNoticeStream extends ScopingNoticeStream +{ + /** + * Constructor + * + * @param User $user User to get a stream for + */ + function __construct($user, $profile = null) + { + // Note: we don't use CachingNoticeStream since RawInboxNoticeStream + // uses Inbox::staticGet(), which is cached. + parent::__construct(new RawInboxNoticeStream($user), $profile); + } +} + +/** + * Raw stream of notices for the user's inbox + * + * @category General + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ +class RawInboxNoticeStream extends NoticeStream +{ + protected $user = null; + protected $inbox = null; + + /** + * Constructor + * + * @param User $user User to get a stream for + */ + function __construct($user) + { + $this->user = $user; + $this->inbox = Inbox::staticGet('user_id', $user->id); + } + + /** + * Get IDs in a range + * + * @param int $offset Offset from start + * @param int $limit Limit of number to get + * @param int $since_id Since this notice + * @param int $max_id Before this notice + * + * @return Array IDs found + */ + function getNoticeIds($offset, $limit, $since_id, $max_id) + { + if (empty($this->inbox)) { + $this->inbox = Inbox::fromNoticeInbox($user_id); + if (empty($this->inbox)) { + return array(); + } else { + $this->inbox->encache(); + } + } + + $ids = $this->inbox->unpack(); + + if (!empty($since_id)) { + $newids = array(); + foreach ($ids as $id) { + if ($id > $since_id) { + $newids[] = $id; + } + } + $ids = $newids; + } + + if (!empty($max_id)) { + $newids = array(); + foreach ($ids as $id) { + if ($id <= $max_id) { + $newids[] = $id; + } + } + $ids = $newids; + } + + $ids = array_slice($ids, $offset, $limit); + + return $ids; + } +} diff --git a/lib/oembedhelper.php b/lib/oembedhelper.php index 4aae815918..6d8064e660 100644 --- a/lib/oembedhelper.php +++ b/lib/oembedhelper.php @@ -131,6 +131,7 @@ class oEmbedHelper } if (empty($api)) { + // TRANS: Server exception thrown in oEmbed action if no API endpoint is available. throw new ServerException(_('No oEmbed API endpoint available.')); } diff --git a/plugins/Echo/EchoPlugin.php b/plugins/Echo/EchoPlugin.php index cd8d8c0e73..a6f87bc38d 100644 --- a/plugins/Echo/EchoPlugin.php +++ b/plugins/Echo/EchoPlugin.php @@ -108,6 +108,7 @@ class EchoPlugin extends Plugin 'author' => 'Zach Copley', 'homepage' => 'http://status.net/wiki/Plugin:Echo', 'rawdescription' => + // TRANS: Plugin description. _m('Use Echo'. ' to add commenting to notice pages.')); return true; diff --git a/plugins/EmailAuthentication/EmailAuthenticationPlugin.php b/plugins/EmailAuthentication/EmailAuthenticationPlugin.php index 689d6231d1..e55614ea43 100644 --- a/plugins/EmailAuthentication/EmailAuthenticationPlugin.php +++ b/plugins/EmailAuthentication/EmailAuthenticationPlugin.php @@ -57,6 +57,7 @@ class EmailAuthenticationPlugin extends Plugin 'author' => 'Craig Andrews', 'homepage' => 'http://status.net/wiki/Plugin:EmailAuthentication', 'rawdescription' => + // TRANS: Plugin description. _m('The Email Authentication plugin allows users to login using their email address.')); return true; } diff --git a/plugins/EmailAuthentication/README b/plugins/EmailAuthentication/README index 3208156896..3fc40794be 100644 --- a/plugins/EmailAuthentication/README +++ b/plugins/EmailAuthentication/README @@ -1,7 +1,8 @@ The Email Authentication plugin allows users to login using their email address. -The provided email address is used to lookup the user's nickname, then that nickname and the provided password is checked. +The provided email address is used to lookup the user's nickname, then that +nickname and the provided password is checked. Installation ============ -add "addPlugin('emailAuthentication');" to the bottom of your config.php +add "addPlugin('emailAuthentication');" to the bottom of your config.php. diff --git a/plugins/EmailSummary/EmailSummaryPlugin.php b/plugins/EmailSummary/EmailSummaryPlugin.php index 66c1214106..36aec6c96c 100644 --- a/plugins/EmailSummary/EmailSummaryPlugin.php +++ b/plugins/EmailSummary/EmailSummaryPlugin.php @@ -43,7 +43,6 @@ if (!defined('STATUSNET')) { * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 * @link http://status.net/ */ - class EmailSummaryPlugin extends Plugin { /** @@ -51,13 +50,11 @@ class EmailSummaryPlugin extends Plugin * * @return boolean hook value */ - function onCheckSchema() { $schema = Schema::get(); // For storing user-submitted flags on profiles - $schema->ensureTable('email_summary_status', array(new ColumnDef('user_id', 'integer', null, false, 'PRI'), @@ -80,9 +77,8 @@ class EmailSummaryPlugin extends Plugin * @param string $cls Name of the class to be loaded * * @return boolean hook value; true means continue processing, false means stop. - * + * */ - function onAutoload($cls) { $dir = dirname(__FILE__); @@ -107,9 +103,7 @@ class EmailSummaryPlugin extends Plugin * @param array &$versions array of version data * * @return boolean hook value; true means continue processing, false means stop. - * */ - function onPluginVersion(&$versions) { $versions[] = array('name' => 'EmailSummary', @@ -117,86 +111,84 @@ class EmailSummaryPlugin extends Plugin 'author' => 'Evan Prodromou', 'homepage' => 'http://status.net/wiki/Plugin:EmailSummary', 'rawdescription' => + // TRANS: Plugin description. _m('Send an email summary of the inbox to users.')); return true; } /** * Register our queue handlers - * + * * @param QueueManager $qm Current queue manager - * + * * @return boolean hook value */ - function onEndInitializeQueueManager($qm) { $qm->connect('sitesum', 'SiteEmailSummaryHandler'); $qm->connect('usersum', 'UserEmailSummaryHandler'); return true; } - + /** * Add a checkbox to turn off email summaries - * + * * @param Action $action Action being executed (emailsettings) - * + * * @return boolean hook value */ - function onEndEmailFormData($action) { $user = common_current_user(); - + $action->elementStart('li'); $action->checkbox('emailsummary', // TRANS: Checkbox label in e-mail preferences form. - _m('Send me a periodic summary of updates from my network.'), + _m('Send me a periodic summary of updates from my network'), Email_summary_status::getSendSummary($user->id)); $action->elementEnd('li'); return true; } - + /** * Add a checkbox to turn off email summaries - * + * * @param Action $action Action being executed (emailsettings) - * + * * @return boolean hook value */ - function onEndEmailSaveForm($action) { $sendSummary = $action->boolean('emailsummary'); - + $user = common_current_user(); - + if (!empty($user)) { - + $ess = Email_summary_status::staticGet('user_id', $user->id); - + if (empty($ess)) { - + $ess = new Email_summary_status(); $ess->user_id = $user->id; $ess->send_summary = $sendSummary; $ess->created = common_sql_now(); $ess->modified = common_sql_now(); - + $ess->insert(); - + } else { - + $orig = clone($ess); - + $ess->send_summary = $sendSummary; $ess->modified = common_sql_now(); - + $ess->update($orig); } } - + return true; } } diff --git a/plugins/EmailSummary/Email_summary_status.php b/plugins/EmailSummary/Email_summary_status.php index 7072370faf..0c9e880f18 100644 --- a/plugins/EmailSummary/Email_summary_status.php +++ b/plugins/EmailSummary/Email_summary_status.php @@ -35,7 +35,7 @@ require_once INSTALLDIR . '/classes/Memcached_DataObject.php'; /** * Data class for email summaries - * + * * Email summary information for users * * @category Action @@ -46,7 +46,6 @@ require_once INSTALLDIR . '/classes/Memcached_DataObject.php'; * * @see DB_DataObject */ - class Email_summary_status extends Memcached_DataObject { public $__table = 'email_summary_status'; // table name @@ -78,7 +77,6 @@ class Email_summary_status extends Memcached_DataObject * * @return array array of column definitions */ - function table() { return array('user_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL, @@ -93,7 +91,6 @@ class Email_summary_status extends Memcached_DataObject * * @return array list of key field names */ - function keys() { return array_keys($this->keyTypes()); @@ -121,7 +118,6 @@ class Email_summary_status extends Memcached_DataObject * * @return array magic three-false array that stops auto-incrementing. */ - function sequenceKey() { return array(false, false, false); @@ -134,7 +130,6 @@ class Email_summary_status extends Memcached_DataObject * * @return int flag for whether to send this user a summary email */ - static function getSendSummary($user_id) { $ess = Email_summary_status::staticGet('user_id', $user_id); @@ -153,11 +148,10 @@ class Email_summary_status extends Memcached_DataObject * * @return Email_summary_status instance for this user, with count already incremented. */ - static function getLastSummaryID($user_id) { $ess = Email_summary_status::staticGet('user_id', $user_id); - + if (!empty($ess)) { return $ess->last_summary_id; } else { diff --git a/plugins/EmailSummary/siteemailsummaryhandler.php b/plugins/EmailSummary/siteemailsummaryhandler.php index 1c0d4997de..3369a5a703 100644 --- a/plugins/EmailSummary/siteemailsummaryhandler.php +++ b/plugins/EmailSummary/siteemailsummaryhandler.php @@ -1,7 +1,7 @@ find(); - + while ($user->fetch()) { try { $qm->enqueue($user->id, 'usersum'); @@ -89,8 +86,7 @@ class SiteEmailSummaryHandler extends QueueHandler } catch (Exception $e) { common_log(LOG_WARNING, $e->getMessage()); } - + return true; } } - diff --git a/plugins/EmailSummary/useremailsummaryhandler.php b/plugins/EmailSummary/useremailsummaryhandler.php index 5e10af40eb..2c8c0d9039 100644 --- a/plugins/EmailSummary/useremailsummaryhandler.php +++ b/plugins/EmailSummary/useremailsummaryhandler.php @@ -1,7 +1,7 @@ send_summary) { common_log(LOG_INFO, sprintf('Not sending email summary for user %s by request.', $user_id)); return true; } $since_id = null; - + if (!empty($ess)) { $since_id = $ess->last_summary_id; } - + $user = User::staticGet('id', $user_id); if (empty($user)) { common_log(LOG_INFO, sprintf('Not sending email summary for user %s; no such user.', $user_id)); return true; } - + if (empty($user->email)) { common_log(LOG_INFO, sprintf('Not sending email summary for user %s; no email address.', $user_id)); return true; } - + $profile = $user->getProfile(); - + if (empty($profile)) { common_log(LOG_WARNING, sprintf('Not sending email summary for user %s; no profile.', $user_id)); return true; } - + $notice = $user->ownFriendsTimeline(0, self::MAX_NOTICES, $since_id); if (empty($notice) || $notice->N == 0) { @@ -117,18 +113,20 @@ class UserEmailSummaryHandler extends QueueHandler // figuring out a better way. -ESP $new_top = null; - + if ($notice instanceof ArrayWrapper) { $new_top = $notice->_items[0]->id; } - + $out = new XMLStringer(); $out->elementStart('div', array('width' => '100%', 'style' => 'background-color: #ffffff; border: 4px solid #4c609a; padding: 10px;')); $out->elementStart('div', array('style' => 'color: #ffffff; background-color: #4c609a; font-weight: bold; margin-bottom: 10px; padding: 4px;')); - $out->raw(sprintf(_m('Recent updates from %1s for %2s:'), + // TRANS: Text in e-mail summary. + // TRANS: %1$s is the StatusNet sitename, %2$s is the recipient's profile name. + $out->raw(sprintf(_m('Recent updates from %1$s for %2s:'), common_config('site', 'name'), $profile->getBestName())); $out->elementEnd('div'); @@ -137,13 +135,12 @@ class UserEmailSummaryHandler extends QueueHandler 'style' => 'border: none; border-collapse: collapse;', 'cellpadding' => '6')); while ($notice->fetch()) { - $profile = Profile::staticGet('id', $notice->profile_id); - + if (empty($profile)) { continue; } - + $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE); $out->elementStart('tr'); @@ -191,7 +188,7 @@ class UserEmailSummaryHandler extends QueueHandler $out->elementEnd('td'); $out->elementEnd('tr'); } - + $out->elementEnd('table'); $out->raw(sprintf(_m('

change your email settings for %2s

'), @@ -199,35 +196,32 @@ class UserEmailSummaryHandler extends QueueHandler common_config('site', 'name'))); $out->elementEnd('div'); - + $body = $out->getString(); - + // FIXME: do something for people who don't like HTML email - + mail_to_user($user, _m('Updates from your network'), $body, array('Content-Type' => 'text/html; charset=UTF-8')); if (empty($ess)) { - $ess = new Email_summary_status(); - + $ess->user_id = $user_id; $ess->created = common_sql_now(); $ess->last_summary_id = $new_top; $ess->modified = common_sql_now(); $ess->insert(); - } else { - $orig = clone($ess); - + $ess->last_summary_id = $new_top; $ess->modified = common_sql_now(); $ess->update($orig); } - + return true; } } diff --git a/plugins/Enjit/enjitqueuehandler.php b/plugins/Enjit/enjitqueuehandler.php index 4a68f4f6b6..284f29477c 100644 --- a/plugins/Enjit/enjitqueuehandler.php +++ b/plugins/Enjit/enjitqueuehandler.php @@ -23,7 +23,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { /** * Queue handler for watching new notices and posting to enjit. - * @fixme is this actually being used/functional atm? + * @todo FIXME: Is this actually being used/functional atm? */ class EnjitQueueHandler extends QueueHandler { diff --git a/plugins/Event/EventPlugin.php b/plugins/Event/EventPlugin.php index 528c855bda..63d92e63c7 100644 --- a/plugins/Event/EventPlugin.php +++ b/plugins/Event/EventPlugin.php @@ -105,7 +105,6 @@ class EventPlugin extends MicroappPlugin * * @return boolean hook value; true means continue processing, false means stop. */ - function onRouterInitialized($m) { $m->connect('main/event/new', @@ -130,12 +129,14 @@ class EventPlugin extends MicroappPlugin 'author' => 'Evan Prodromou', 'homepage' => 'http://status.net/wiki/Plugin:Event', 'description' => + // TRANS: Plugin description. _m('Event invitations and RSVPs.')); return true; } function appTitle() { - return _m('Event'); + // TRANS: Title for event application. + return _m('TITLE','Event'); } function tag() { @@ -162,12 +163,13 @@ class EventPlugin extends MicroappPlugin function saveNoticeFromActivity($activity, $actor, $options=array()) { if (count($activity->objects) != 1) { - throw new Exception('Too many activity objects.'); + throw new Exception(_('Too many activity objects.')); } $happeningObj = $activity->objects[0]; if ($happeningObj->type != Happening::OBJECT_TYPE) { + // TRANS: Exception thrown when event plugin comes across a non-event type object. throw new Exception(_m('Wrong type for object.')); } @@ -175,8 +177,8 @@ class EventPlugin extends MicroappPlugin switch ($activity->verb) { case ActivityVerb::POST: - $notice = Happening::saveNew($actor, - $start_time, + $notice = Happening::saveNew($actor, + $start_time, $end_time, $happeningObj->title, null, @@ -189,12 +191,14 @@ class EventPlugin extends MicroappPlugin $happening = Happening::staticGet('uri', $happeningObj->id); if (empty($happening)) { // FIXME: save the event + // TRANS: Exception thrown when trying to RSVP for an unknown event. throw new Exception(_m('RSVP for unknown event.')); } $notice = RSVP::saveNew($actor, $happening, $activity->verb, $options); break; default: - throw new Exception(_m('Unknown verb for events')); + // TRANS: Exception thrown when event plugin comes across a undefined verb. + throw new Exception(_m('Unknown verb for events.')); } return $notice; @@ -207,7 +211,6 @@ class EventPlugin extends MicroappPlugin * * @return ActivityObject */ - function activityObjectFromNotice($notice) { $happening = null; @@ -225,12 +228,14 @@ class EventPlugin extends MicroappPlugin } if (empty($happening)) { + // TRANS: Exception thrown when event plugin comes across a unknown object type. throw new Exception(_m('Unknown object type.')); } $notice = $happening->getNotice(); if (empty($notice)) { + // TRANS: Exception thrown when referring to a notice that is not an event an in event context. throw new Exception(_m('Unknown event notice.')); } @@ -264,7 +269,6 @@ class EventPlugin extends MicroappPlugin * * @return ActivityObject */ - function onEndNoticeAsActivity($notice, &$act) { switch ($notice->object_type) { case RSVP::POSITIVE: @@ -282,7 +286,6 @@ class EventPlugin extends MicroappPlugin * @param Notice $notice * @param HTMLOutputter $out */ - function showNotice($notice, $out) { switch ($notice->object_type) { @@ -365,6 +368,7 @@ class EventPlugin extends MicroappPlugin $out->elementStart('div', 'event-times'); // VEVENT/EVENT-TIMES IN + // TRANS: Field label for event description. $out->element('strong', null, _m('Time:')); $out->element('abbr', array('class' => 'dtstart', @@ -385,6 +389,7 @@ class EventPlugin extends MicroappPlugin if (!empty($event->location)) { $out->elementStart('div', 'event-location'); + // TRANS: Field label for event description. $out->element('strong', null, _m('Location:')); $out->element('span', 'location', $event->location); $out->elementEnd('div'); @@ -392,6 +397,7 @@ class EventPlugin extends MicroappPlugin if (!empty($event->description)) { $out->elementStart('div', 'event-description'); + // TRANS: Field label for event description. $out->element('strong', null, _m('Description:')); $out->element('span', 'description', $event->description); $out->elementEnd('div'); @@ -400,6 +406,7 @@ class EventPlugin extends MicroappPlugin $rsvps = $event->getRSVPs(); $out->elementStart('div', 'event-rsvps'); + // TRANS: Field label for event description. $out->element('strong', null, _m('Attending:')); $out->element('span', 'event-rsvps', // TRANS: RSVP counts. @@ -433,7 +440,6 @@ class EventPlugin extends MicroappPlugin * @param HTMLOutputter $out * @return Widget */ - function entryForm($out) { return new EventForm($out); @@ -444,7 +450,6 @@ class EventPlugin extends MicroappPlugin * * @param Notice $notice */ - function deleteRelated($notice) { switch ($notice->object_type) { diff --git a/plugins/Event/Happening.php b/plugins/Event/Happening.php index ec3e12595d..a2811252c0 100644 --- a/plugins/Event/Happening.php +++ b/plugins/Event/Happening.php @@ -47,7 +47,6 @@ if (!defined('STATUSNET')) { * * @see Managed_DataObject */ - class Happening extends Managed_DataObject { const OBJECT_TYPE = 'http://activitystrea.ms/schema/1.0/event'; @@ -122,6 +121,7 @@ class Happening extends Managed_DataObject if (array_key_exists('uri', $options)) { $other = Happening::staticGet('uri', $options['uri']); if (!empty($other)) { + // TRANS: Client exception thrown when trying to create an event that already exists. throw new ClientException(_m('Event already exists.')); } } @@ -163,6 +163,9 @@ class Happening extends Managed_DataObject $location, $description); + // TRANS: Rendered event description. %1$s is a title, %2$s is start time, %3$s is start time, + // TRANS: %4$s is end time, %5$s is end time, %6$s is location, %7$s is description. + // TRANS: Class names should not be translated. $rendered = sprintf(_m(''. '%1$s '. '%3$s - '. diff --git a/plugins/Event/RSVP.php b/plugins/Event/RSVP.php index 85862d375d..1f47958e9a 100644 --- a/plugins/Event/RSVP.php +++ b/plugins/Event/RSVP.php @@ -42,7 +42,6 @@ if (!defined('STATUSNET')) { * * @see Managed_DataObject */ - class RSVP extends Managed_DataObject { const POSITIVE = 'http://activitystrea.ms/schema/1.0/rsvp-yes'; @@ -64,7 +63,6 @@ class RSVP extends Managed_DataObject * @param mixed $v Value to lookup * * @return RSVP object found, or null for no hits - * */ function staticGet($k, $v=null) { @@ -77,7 +75,6 @@ class RSVP extends Managed_DataObject * @param array $kv array of key-value mappings * * @return Bookmark object found, or null for no hits - * */ function pkeyGet($kv) @@ -141,6 +138,7 @@ class RSVP extends Managed_DataObject if (array_key_exists('uri', $options)) { $other = RSVP::staticGet('uri', $options['uri']); if (!empty($other)) { + // TRANS: Client exception thrown when trying to save an already existing RSVP ("please respond"). throw new ClientException(_m('RSVP already exists.')); } } @@ -149,6 +147,7 @@ class RSVP extends Managed_DataObject 'event_id' => $event->id)); if (!empty($other)) { + // TRANS: Client exception thrown when trying to save an already existing RSVP ("please respond"). throw new ClientException(_m('RSVP already exists.')); } @@ -179,7 +178,7 @@ class RSVP extends Managed_DataObject // XXX: come up with something sexier $content = $rsvp->asString(); - + $rendered = $rsvp->asHTML(); $options = array_merge(array('object_type' => $verb), @@ -217,7 +216,8 @@ class RSVP extends Managed_DataObject return '?'; break; default: - throw new Exception(sprintf(_m('Unknown verb "%s"'),$verb)); + // TRANS: Exception thrown when requesting an undefined verb for RSVP. + throw new Exception(sprintf(_m('Unknown verb "%s".'),$verb)); } } @@ -234,6 +234,7 @@ class RSVP extends Managed_DataObject return RSVP::POSSIBLE; break; default: + // TRANS: Exception thrown when requesting an undefined code for RSVP. throw new Exception(sprintf(_m('Unknown code "%s".'),$code)); } } @@ -242,6 +243,8 @@ class RSVP extends Managed_DataObject { $notice = Notice::staticGet('uri', $this->uri); if (empty($notice)) { + // TRANS: Server exception thrown when requesting a non-exsting notice for an RSVP ("please respond"). + // TRANS: %s is the RSVP with the missing notice. throw new ServerException(sprintf(_m('RSVP %s does not correspond to a notice in the database.'),$this->id)); } return $notice; @@ -297,6 +300,8 @@ class RSVP extends Managed_DataObject { $profile = Profile::staticGet('id', $this->profile_id); if (empty($profile)) { + // TRANS: Exception thrown when requesting a non-existing profile. + // TRANS: %s is the ID of the non-existing profile. throw new Exception(sprintf(_m('No profile with ID %s.'),$this->profile_id)); } return $profile; @@ -306,6 +311,8 @@ class RSVP extends Managed_DataObject { $event = Happening::staticGet('id', $this->event_id); if (empty($event)) { + // TRANS: Exception thrown when requesting a non-existing event. + // TRANS: %s is the ID of the non-existing event. throw new Exception(sprintf(_m('No event with ID %s.'),$this->event_id)); } return $event; @@ -335,21 +342,34 @@ class RSVP extends Managed_DataObject switch ($response) { case 'Y': + // TRANS: HTML version of an RSVP ("please respond") status for a user. + // TRANS: %1$s is a profile URL, %2$s a profile name, + // TRANS: %3$s is an event URL, %4$s an event title. $fmt = _m("%2\$s is attending %4\$s."); break; case 'N': + // TRANS: HTML version of an RSVP ("please respond") status for a user. + // TRANS: %1$s is a profile URL, %2$s a profile name, + // TRANS: %3$s is an event URL, %4$s an event title. $fmt = _m("%2\$s is not attending %4\$s."); break; case '?': + // TRANS: HTML version of an RSVP ("please respond") status for a user. + // TRANS: %1$s is a profile URL, %2$s a profile name, + // TRANS: %3$s is an event URL, %4$s an event title. $fmt = _m("%2\$s might attend %4\$s."); break; default: + // TRANS: Exception thrown when requesting a user's RSVP status for a non-existing response code. + // TRANS: %s is the non-existing response code. throw new Exception(sprintf(_m('Unknown response code %s.'),$response)); break; } if (empty($event)) { $eventUrl = '#'; + // TRANS: Used as event title when not event title is available. + // TRANS: Used as: Username [is [not ] attending|might attend] an unknown event. $eventTitle = _m('an unknown event'); } else { $notice = $event->getNotice(); @@ -370,20 +390,30 @@ class RSVP extends Managed_DataObject switch ($response) { case 'Y': + // TRANS: Plain text version of an RSVP ("please respond") status for a user. + // TRANS: %1$s is a profile name, %2$s is an event title. $fmt = _m('%1$s is attending %2$s.'); break; case 'N': + // TRANS: Plain text version of an RSVP ("please respond") status for a user. + // TRANS: %1$s is a profile name, %2$s is an event title. $fmt = _m('%1$s is not attending %2$s.'); break; case '?': + // TRANS: Plain text version of an RSVP ("please respond") status for a user. + // TRANS: %1$s is a profile name, %2$s is an event title. $fmt = _m('%1$s might attend %2$s.'); break; default: + // TRANS: Exception thrown when requesting a user's RSVP status for a non-existing response code. + // TRANS: %s is the non-existing response code. throw new Exception(sprintf(_m('Unknown response code %s.'),$response)); break; } if (empty($event)) { + // TRANS: Used as event title when not event title is available. + // TRANS: Used as: Username [is [not ] attending|might attend] an unknown event. $eventTitle = _m('an unknown event'); } else { $notice = $event->getNotice(); diff --git a/plugins/Event/cancelrsvp.php b/plugins/Event/cancelrsvp.php index 94f78bfca6..6b0ddb2287 100644 --- a/plugins/Event/cancelrsvp.php +++ b/plugins/Event/cancelrsvp.php @@ -4,7 +4,7 @@ * Copyright (C) 2011, StatusNet, Inc. * * Cancel the RSVP for an event - * + * * PHP version 5 * * This program is free software: you can redistribute it and/or modify @@ -27,6 +27,7 @@ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 * @link http://status.net/ */ + if (!defined('STATUSNET')) { // This check helps protect against security problems; // your code file can't be executed directly from the web. @@ -43,7 +44,6 @@ if (!defined('STATUSNET')) { * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 * @link http://status.net/ */ - class CancelrsvpAction extends Action { protected $user = null; @@ -55,10 +55,10 @@ class CancelrsvpAction extends Action * * @return string Action title */ - function title() { - return _m('Cancel RSVP'); + // TRANS: Title for RSVP ("please respond") action. + return _m('TITLE','Cancel RSVP'); } /** @@ -68,7 +68,6 @@ class CancelrsvpAction extends Action * * @return boolean true */ - function prepare($argarray) { parent::prepare($argarray); @@ -79,24 +78,28 @@ class CancelrsvpAction extends Action $rsvpId = $this->trimmed('rsvp'); if (empty($rsvpId)) { + // TRANS: Client exception thrown when referring to a non-existing RSVP ("please respond") item. throw new ClientException(_m('No such RSVP.')); } $this->rsvp = RSVP::staticGet('id', $rsvpId); if (empty($this->rsvp)) { + // TRANS: Client exception thrown when referring to a non-existing RSVP ("please respond") item. throw new ClientException(_m('No such RSVP.')); } $this->event = Happening::staticGet('id', $this->rsvp->event_id); if (empty($this->event)) { + // TRANS: Client exception thrown when referring to a non-existing event. throw new ClientException(_m('No such event.')); } $this->user = common_current_user(); if (empty($this->user)) { + // TRANS: Client exception thrown when trying tp RSVP ("please respond") while not logged in. throw new ClientException(_m('You must be logged in to RSVP for an event.')); } @@ -110,7 +113,6 @@ class CancelrsvpAction extends Action * * @return void */ - function handle($argarray=null) { parent::handle($argarray); @@ -129,7 +131,6 @@ class CancelrsvpAction extends Action * * @return void */ - function cancelRSVP() { try { @@ -171,7 +172,6 @@ class CancelrsvpAction extends Action * * @return void */ - function showContent() { if (!empty($this->error)) { @@ -194,7 +194,6 @@ class CancelrsvpAction extends Action * * @return boolean is read only action? */ - function isReadOnly($args) { if ($_SERVER['REQUEST_METHOD'] == 'GET' || diff --git a/plugins/Event/cancelrsvpform.php b/plugins/Event/cancelrsvpform.php index 14161d1897..107351135a 100644 --- a/plugins/Event/cancelrsvpform.php +++ b/plugins/Event/cancelrsvpform.php @@ -4,7 +4,7 @@ * Copyright (C) 2011, StatusNet, Inc. * * Form to RSVP for an event - * + * * PHP version 5 * * This program is free software: you can redistribute it and/or modify @@ -44,7 +44,6 @@ if (!defined('STATUSNET')) { * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 * @link http://status.net/ */ - class CancelRSVPForm extends Form { protected $rsvp = null; @@ -60,7 +59,6 @@ class CancelRSVPForm extends Form * * @return int ID of the form */ - function id() { return 'form_event_rsvp'; @@ -71,7 +69,6 @@ class CancelRSVPForm extends Form * * @return string class of the form */ - function formClass() { return 'ajax'; @@ -82,7 +79,6 @@ class CancelRSVPForm extends Form * * @return string URL of the action */ - function action() { return common_local_url('cancelrsvp'); @@ -93,7 +89,6 @@ class CancelRSVPForm extends Form * * @return void */ - function formData() { $this->out->elementStart('fieldset', array('id' => 'new_rsvp_data')); @@ -102,12 +97,15 @@ class CancelRSVPForm extends Form switch (RSVP::verbFor($this->rsvp->response)) { case RSVP::POSITIVE: + // TRANS: Possible status for RSVP ("please respond") item. $this->out->text(_m('You will attend this event.')); break; case RSVP::NEGATIVE: + // TRANS: Possible status for RSVP ("please respond") item. $this->out->text(_m('You will not attend this event.')); break; case RSVP::POSSIBLE: + // TRANS: Possible status for RSVP ("please respond") item. $this->out->text(_m('You might attend this event.')); break; } @@ -120,9 +118,9 @@ class CancelRSVPForm extends Form * * @return void */ - function formActions() { + // TRANS: Button text to cancel responding to an RSVP ("please respond") item. $this->out->submit('cancel', _m('BUTTON', 'Cancel')); } } diff --git a/plugins/Event/event.css b/plugins/Event/event.css index a922bb5791..8c9cbbb082 100644 --- a/plugins/Event/event.css +++ b/plugins/Event/event.css @@ -6,4 +6,3 @@ .event-title { margin-left: 0px; } #content .event .entry-title { margin-left: 0px; } #content .event .entry-content { margin-left: 0px; } - diff --git a/plugins/Event/eventform.php b/plugins/Event/eventform.php index 9c9a86229b..832604a31d 100644 --- a/plugins/Event/eventform.php +++ b/plugins/Event/eventform.php @@ -4,7 +4,7 @@ * Copyright (C) 2011, StatusNet, Inc. * * Form for entering an event - * + * * PHP version 5 * * This program is free software: you can redistribute it and/or modify @@ -44,7 +44,6 @@ if (!defined('STATUSNET')) { * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 * @link http://status.net/ */ - class EventForm extends Form { /** @@ -52,7 +51,6 @@ class EventForm extends Form * * @return int ID of the form */ - function id() { return 'form_new_event'; @@ -63,7 +61,6 @@ class EventForm extends Form * * @return string class of the form */ - function formClass() { return 'form_settings ajax-notice'; @@ -74,7 +71,6 @@ class EventForm extends Form * * @return string URL of the action */ - function action() { return common_local_url('newevent'); @@ -85,7 +81,6 @@ class EventForm extends Form * * @return void */ - function formData() { $this->out->elementStart('fieldset', array('id' => 'new_bookmark_data')); @@ -93,57 +88,73 @@ class EventForm extends Form $this->li(); $this->out->input('title', + // TRANS: Field label on event form. _m('LABEL','Title'), null, + // TRANS: Field title on event form. _m('Title of the event.')); $this->unli(); $this->li(); $this->out->input('startdate', + // TRANS: Field label on event form. _m('LABEL','Start date'), null, + // TRANS: Field title on event form. _m('Date the event starts.')); $this->unli(); $this->li(); $this->out->input('starttime', + // TRANS: Field label on event form. _m('LABEL','Start time'), null, + // TRANS: Field title on event form. _m('Time the event starts.')); $this->unli(); $this->li(); $this->out->input('enddate', + // TRANS: Field label on event form. _m('LABEL','End date'), - null, + null, + // TRANS: Field title on event form. _m('Date the event ends.')); $this->unli(); $this->li(); $this->out->input('endtime', + // TRANS: Field label on event form. _m('LABEL','End time'), null, + // TRANS: Field title on event form. _m('Time the event ends.')); $this->unli(); $this->li(); $this->out->input('location', + // TRANS: Field label on event form. _m('LABEL','Location'), null, + // TRANS: Field title on event form. _m('Event location.')); $this->unli(); $this->li(); $this->out->input('url', + // TRANS: Field label on event form. _m('LABEL','URL'), null, + // TRANS: Field title on event form. _m('URL for more information.')); $this->unli(); $this->li(); $this->out->input('description', + // TRANS: Field label on event form. _m('LABEL','Description'), null, + // TRANS: Field title on event form. _m('Description of the event.')); $this->unli(); @@ -162,9 +173,9 @@ class EventForm extends Form * * @return void */ - function formActions() { + // TRANS: Button text to save an event.. $this->out->submit('submit', _m('BUTTON', 'Save')); } } diff --git a/plugins/Event/newevent.php b/plugins/Event/newevent.php index 93baa37b6b..cadf0e1433 100644 --- a/plugins/Event/newevent.php +++ b/plugins/Event/newevent.php @@ -4,7 +4,7 @@ * Copyright (C) 2011, StatusNet, Inc. * * Add a new event - * + * * PHP version 5 * * This program is free software: you can redistribute it and/or modify @@ -27,6 +27,7 @@ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 * @link http://status.net/ */ + if (!defined('STATUSNET')) { // This check helps protect against security problems; // your code file can't be executed directly from the web. @@ -43,7 +44,6 @@ if (!defined('STATUSNET')) { * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 * @link http://status.net/ */ - class NeweventAction extends Action { protected $user = null; @@ -60,10 +60,10 @@ class NeweventAction extends Action * * @return string Action title */ - function title() { - return _m('New event'); + // TRANS: Title for new event form. + return _m('TITLE','New event'); } /** @@ -73,7 +73,6 @@ class NeweventAction extends Action * * @return boolean true */ - function prepare($argarray) { parent::prepare($argarray); @@ -81,6 +80,7 @@ class NeweventAction extends Action $this->user = common_current_user(); if (empty($this->user)) { + // TRANS: Client exception thrown when trying to post an event while not logged in. throw new ClientException(_m('Must be logged in to post a event.'), 403); } @@ -92,6 +92,7 @@ class NeweventAction extends Action $this->title = $this->trimmed('title'); if (empty($this->title)) { + // TRANS: Client exception thrown when trying to post an event without providing a title. throw new ClientException(_m('Title required.')); } @@ -102,6 +103,7 @@ class NeweventAction extends Action $startDate = $this->trimmed('startdate'); if (empty($startDate)) { + // TRANS: Client exception thrown when trying to post an event without providing a start date. throw new ClientException(_m('Start date required.')); } @@ -114,6 +116,7 @@ class NeweventAction extends Action $endDate = $this->trimmed('enddate'); if (empty($endDate)) { + // TRANS: Client exception thrown when trying to post an event without providing an end date. throw new ClientException(_m('End date required.')); } @@ -135,12 +138,16 @@ class NeweventAction extends Action $this->endTime = strtotime($end); if ($this->startTime == 0) { + // TRANS: Client exception thrown when trying to post an event with a date that cannot be processed. + // TRANS: %s is the data that could not be processed. throw new Exception(sprintf(_m('Could not parse date "%s".'), $start)); } if ($this->endTime == 0) { + // TRANS: Client exception thrown when trying to post an event with a date that cannot be processed. + // TRANS: %s is the data that could not be processed. throw new Exception(sprintf(_m('Could not parse date "%s".'), $end)); } @@ -155,7 +162,6 @@ class NeweventAction extends Action * * @return void */ - function handle($argarray=null) { parent::handle($argarray); @@ -174,19 +180,21 @@ class NeweventAction extends Action * * @return void */ - function newEvent() { try { if (empty($this->title)) { + // TRANS: Client exception thrown when trying to post an event without providing a title. throw new ClientException(_m('Event must have a title.')); } if (empty($this->startTime)) { + // TRANS: Client exception thrown when trying to post an event without providing a start time. throw new ClientException(_m('Event must have a start time.')); } if (empty($this->endTime)) { + // TRANS: Client exception thrown when trying to post an event without providing an end time. throw new ClientException(_m('Event must have an end time.')); } @@ -195,7 +203,7 @@ class NeweventAction extends Action // Does the heavy-lifting for getting "To:" information ToSelector::fillOptions($this, $options); - + $profile = $this->user->getProfile(); $saved = Happening::saveNew($profile, @@ -239,7 +247,6 @@ class NeweventAction extends Action * * @return void */ - function showContent() { if (!empty($this->error)) { @@ -262,7 +269,6 @@ class NeweventAction extends Action * * @return boolean is read only action? */ - function isReadOnly($args) { if ($_SERVER['REQUEST_METHOD'] == 'GET' || diff --git a/plugins/Event/newrsvp.php b/plugins/Event/newrsvp.php index cb7f72d49c..b000767340 100644 --- a/plugins/Event/newrsvp.php +++ b/plugins/Event/newrsvp.php @@ -4,7 +4,7 @@ * Copyright (C) 2011, StatusNet, Inc. * * RSVP for an event - * + * * PHP version 5 * * This program is free software: you can redistribute it and/or modify @@ -27,6 +27,7 @@ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 * @link http://status.net/ */ + if (!defined('STATUSNET')) { // This check helps protect against security problems; // your code file can't be executed directly from the web. @@ -43,7 +44,6 @@ if (!defined('STATUSNET')) { * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 * @link http://status.net/ */ - class NewrsvpAction extends Action { protected $user = null; @@ -55,10 +55,10 @@ class NewrsvpAction extends Action * * @return string Action title */ - function title() { - return _m('New RSVP'); + // TRANS: Title for RSVP ("please respond") action. + return _m('TITLE','New RSVP'); } /** @@ -68,7 +68,6 @@ class NewrsvpAction extends Action * * @return boolean true */ - function prepare($argarray) { parent::prepare($argarray); @@ -79,18 +78,21 @@ class NewrsvpAction extends Action $eventId = $this->trimmed('event'); if (empty($eventId)) { + // TRANS: Client exception thrown when requesting a non-exsting event. throw new ClientException(_m('No such event.')); } $this->event = Happening::staticGet('id', $eventId); if (empty($this->event)) { + // TRANS: Client exception thrown when requesting a non-exsting event. throw new ClientException(_m('No such event.')); } $this->user = common_current_user(); if (empty($this->user)) { + // TRANS: Client exception thrown when trying to RSVP ("please respond") while not logged in. throw new ClientException(_m('You must be logged in to RSVP for an event.')); } @@ -107,7 +109,8 @@ class NewrsvpAction extends Action $this->verb = RSVP::POSSIBLE; break; default: - throw new ClientException('Unknown submit value.'); + // TRANS: Client exception thrown when using an invalud value for RSVP ("please respond"). + throw new ClientException(_('Unknown submit value.')); } return true; @@ -120,7 +123,6 @@ class NewrsvpAction extends Action * * @return void */ - function handle($argarray=null) { parent::handle($argarray); @@ -139,7 +141,6 @@ class NewrsvpAction extends Action * * @return void */ - function newRSVP() { try { @@ -158,7 +159,7 @@ class NewrsvpAction extends Action $this->xw->startDocument('1.0', 'UTF-8'); $this->elementStart('html'); $this->elementStart('head'); - // TRANS: Page title after sending a notice. + // TRANS: Page title after creating an event. $this->element('title', null, _m('Event saved')); $this->elementEnd('head'); $this->elementStart('body'); @@ -178,7 +179,6 @@ class NewrsvpAction extends Action * * @return void */ - function showContent() { if (!empty($this->error)) { @@ -201,7 +201,6 @@ class NewrsvpAction extends Action * * @return boolean is read only action? */ - function isReadOnly($args) { if ($_SERVER['REQUEST_METHOD'] == 'GET' || diff --git a/plugins/Event/rsvpform.php b/plugins/Event/rsvpform.php index 494e64929f..6f86004f94 100644 --- a/plugins/Event/rsvpform.php +++ b/plugins/Event/rsvpform.php @@ -4,7 +4,7 @@ * Copyright (C) 2011, StatusNet, Inc. * * Form to RSVP for an event - * + * * PHP version 5 * * This program is free software: you can redistribute it and/or modify @@ -44,7 +44,6 @@ if (!defined('STATUSNET')) { * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 * @link http://status.net/ */ - class RSVPForm extends Form { protected $event = null; @@ -60,7 +59,6 @@ class RSVPForm extends Form * * @return int ID of the form */ - function id() { return 'form_event_rsvp'; @@ -71,7 +69,6 @@ class RSVPForm extends Form * * @return string class of the form */ - function formClass() { return 'ajax'; @@ -82,7 +79,6 @@ class RSVPForm extends Form * * @return string URL of the action */ - function action() { return common_local_url('newrsvp'); @@ -93,11 +89,11 @@ class RSVPForm extends Form * * @return void */ - function formData() { $this->out->elementStart('fieldset', array('id' => 'new_rsvp_data')); + // TRANS: Field label on form to RSVP ("please respond") for an event. $this->out->text(_m('RSVP:')); $this->out->hidden('event', $this->event->id); @@ -111,14 +107,16 @@ class RSVPForm extends Form * * @return void */ - function formActions() { + // TRANS: Button text for RSVP ("please respond") reply to confirm attendence. $this->submitButton('yes', _m('BUTTON', 'Yes')); + // TRANS: Button text for RSVP ("please respond") reply to deny attendence. $this->submitButton('no', _m('BUTTON', 'No')); + // TRANS: Button text for RSVP ("please respond") reply to indicate one might attend. $this->submitButton('maybe', _m('BUTTON', 'Maybe')); } - + function submitButton($id, $label) { $this->out->element('input', array('type' => 'submit', diff --git a/plugins/Event/showevent.php b/plugins/Event/showevent.php index e5afd47d00..52e17f860a 100644 --- a/plugins/Event/showevent.php +++ b/plugins/Event/showevent.php @@ -4,7 +4,7 @@ * Copyright (C) 2011, StatusNet, Inc. * * Show a single event - * + * * PHP version 5 * * This program is free software: you can redistribute it and/or modify diff --git a/plugins/Event/showrsvp.php b/plugins/Event/showrsvp.php index 7b129177e1..da80448af8 100644 --- a/plugins/Event/showrsvp.php +++ b/plugins/Event/showrsvp.php @@ -4,7 +4,7 @@ * Copyright (C) 2010, StatusNet, Inc. * * Show a single RSVP - * + * * PHP version 5 * * This program is free software: you can redistribute it and/or modify diff --git a/plugins/ExtendedProfile/ExtendedProfilePlugin.php b/plugins/ExtendedProfile/ExtendedProfilePlugin.php index ce1593dad5..51584e9f91 100644 --- a/plugins/ExtendedProfile/ExtendedProfilePlugin.php +++ b/plugins/ExtendedProfile/ExtendedProfilePlugin.php @@ -29,7 +29,6 @@ if (!defined('STATUSNET')) { */ class ExtendedProfilePlugin extends Plugin { - function onPluginVersion(&$versions) { $versions[] = array( @@ -37,8 +36,8 @@ class ExtendedProfilePlugin extends Plugin 'version' => STATUSNET_VERSION, 'author' => 'Brion Vibber, Samantha Doherty, Zach Copley', 'homepage' => 'http://status.net/wiki/Plugin:ExtendedProfile', - 'rawdescription' => _m( - 'UI extensions for additional profile fields.') + // TRANS: Plugin description. + 'rawdescription' => _m('UI extensions for additional profile fields.') ); return true; @@ -120,9 +119,9 @@ class ExtendedProfilePlugin extends Plugin $user = User::staticGet('id', $profile->id); if ($user) { $url = common_local_url('profiledetail', array('nickname' => $user->nickname)); + // TRANS: Link text on user profile page leading to extended profile page. $out->element('a', array('href' => $url, 'class' => 'profiledetail'), _m('More details...')); } return true; } - } diff --git a/plugins/ExtendedProfile/classes/Profile_detail.php b/plugins/ExtendedProfile/classes/Profile_detail.php index 96869b0e63..94e52c396c 100644 --- a/plugins/ExtendedProfile/classes/Profile_detail.php +++ b/plugins/ExtendedProfile/classes/Profile_detail.php @@ -80,7 +80,6 @@ class Profile_detail extends Managed_DataObject * @return User_greeting_count object found, or null for no hits * */ - function staticGet($k, $v=null) { return Memcached_DataObject::staticGet('Profile_detail', $k, $v); @@ -98,7 +97,6 @@ class Profile_detail extends Managed_DataObject * @return Bookmark object found, or null for no hits * */ - function pkeyGet($kv) { return Memcached_DataObject::pkeyGet('Profile_detail', $kv); @@ -107,6 +105,7 @@ class Profile_detail extends Managed_DataObject static function schemaDef() { return array( + // No need for i18n. Table properties. 'description' => 'Additional profile details for the ExtendedProfile plugin', 'fields' => array( @@ -138,5 +137,4 @@ class Profile_detail extends Managed_DataObject ) ); } - } diff --git a/plugins/ExtendedProfile/lib/extendedprofile.php b/plugins/ExtendedProfile/lib/extendedprofile.php index fa632e5073..d73170b235 100644 --- a/plugins/ExtendedProfile/lib/extendedprofile.php +++ b/plugins/ExtendedProfile/lib/extendedprofile.php @@ -116,6 +116,7 @@ class ExtendedProfile if (empty($phones)) { $pArrays[] = array( + // TRANS: Field label for extended profile properties. 'label' => _m('Phone'), 'index' => 0, 'type' => 'phone', @@ -126,6 +127,7 @@ class ExtendedProfile } else { for ($i = 0; $i < sizeof($phones); $i++) { $pa = array( + // TRANS: Field label for extended profile properties. 'label' => _m('Phone'), 'type' => 'phone', 'index' => intval($phones[$i]->value_index), @@ -147,12 +149,14 @@ class ExtendedProfile if (empty($ims)) { $iArrays[] = array( + // TRANS: Field label for extended profile properties (Instant Messaging). 'label' => _m('IM'), 'type' => 'im' ); } else { for ($i = 0; $i < sizeof($ims); $i++) { $ia = array( + // TRANS: Field label for extended profile properties (Instant Messaging). 'label' => _m('IM'), 'type' => 'im', 'index' => intval($ims[$i]->value_index), @@ -173,12 +177,14 @@ class ExtendedProfile if (empty($sites)) { $wArrays[] = array( + // TRANS: Field label for extended profile properties. 'label' => _m('Website'), 'type' => 'website' ); } else { for ($i = 0; $i < sizeof($sites); $i++) { $wa = array( + // TRANS: Field label for extended profile properties. 'label' => _m('Website'), 'type' => 'website', 'index' => intval($sites[$i]->value_index), @@ -202,6 +208,7 @@ class ExtendedProfile if (empty($companies)) { $eArrays[] = array( + // TRANS: Field label for extended profile properties. 'label' => _m('Employer'), 'type' => 'experience', 'company' => null, @@ -213,6 +220,7 @@ class ExtendedProfile } else { for ($i = 0; $i < sizeof($companies); $i++) { $ea = array( + // TRANS: Field label for extended profile properties. 'label' => _m('Employer'), 'type' => 'experience', 'company' => $companies[$i]->field_value, @@ -239,6 +247,7 @@ class ExtendedProfile if (empty($schools)) { $iArrays[] = array( 'type' => 'education', + // TRANS: Field label for extended profile properties. 'label' => _m('Institution'), 'school' => null, 'degree' => null, @@ -251,6 +260,7 @@ class ExtendedProfile for ($i = 0; $i < sizeof($schools); $i++) { $ia = array( 'type' => 'education', + // TRANS: Field label for extended profile properties. 'label' => _m('Institution'), 'school' => $schools[$i]->field_value, 'degree' => isset($degrees[$i]->field_value) ? $degrees[$i]->field_value : null, @@ -275,32 +285,39 @@ class ExtendedProfile { return array( 'basic' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Personal'), 'fields' => array( 'fullname' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Full name'), 'profile' => 'fullname', 'vcard' => 'fn', ), 'title' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Title'), 'vcard' => 'title', ), 'manager' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Manager'), 'type' => 'person', 'vcard' => 'x-manager', ), 'location' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Location'), 'profile' => 'location' ), 'bio' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Bio'), 'type' => 'textarea', 'profile' => 'bio', ), 'tags' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Tags'), 'type' => 'tags', 'profile' => 'tags', @@ -308,6 +325,7 @@ class ExtendedProfile ), ), 'contact' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Contact'), 'fields' => array( 'phone' => $this->getPhones(), @@ -316,29 +334,35 @@ class ExtendedProfile ), ), 'personal' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Personal'), 'fields' => array( 'birthday' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Birthday'), 'type' => 'date', 'vcard' => 'bday', ), 'spouse' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Spouse\'s name'), 'vcard' => 'x-spouse', ), 'kids' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Kids\' names') ), ), ), 'experience' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Work experience'), 'fields' => array( 'experience' => $this->getExperiences() ), ), 'education' => array( + // TRANS: Field label for extended profile properties. 'label' => _m('Education'), 'fields' => array( 'education' => $this->getEducation() diff --git a/plugins/ExtendedProfile/lib/extendedprofilewidget.php b/plugins/ExtendedProfile/lib/extendedprofilewidget.php index 24c8b2f3d4..03be420bea 100644 --- a/plugins/ExtendedProfile/lib/extendedprofilewidget.php +++ b/plugins/ExtendedProfile/lib/extendedprofilewidget.php @@ -80,9 +80,11 @@ class ExtendedProfileWidget extends Form // For JQuery UI modal dialog $this->out->elementStart( 'div', - array('id' => 'confirm-dialog', 'title' => 'Confirmation Required') + // TRANS: Title for extended profile entry deletion dialog. + array('id' => 'confirm-dialog', 'title' => _m('Confirmation Required')) ); - $this->out->text('Really delete this entry?'); + // TRANS: Confirmation text for extended profile entry deletion dialog. + $this->out->text(_m('Really delete this entry?')); $this->out->elementEnd('div'); $this->showSections(); } @@ -163,7 +165,9 @@ class ExtendedProfileWidget extends Form if (!empty($field['value'])) { $this->out->text($field['value']); if (!empty($field['rel'])) { - $this->out->text(' (' . $field['rel'] . ')'); + // TRANS: Value between parentheses (phone number, website, or IM address). + $outtext = sprintf(_m('(%s)'),$field['rel']); + $this->out->text(' '.$outtext); } } $this->out->elementEnd('div'); @@ -174,7 +178,9 @@ class ExtendedProfileWidget extends Form $this->out->elementStart('div', array('class' => 'im-display')); $this->out->text($field['value']); if (!empty($field['rel'])) { - $this->out->text(' (' . $field['rel'] . ')'); + // TRANS: Value between parentheses (phone number, website, or IM address). + $outtext = sprintf(_m('(%s)'),$field['rel']); + $this->out->text(' '.$outtext); } $this->out->elementEnd('div'); } @@ -196,7 +202,9 @@ class ExtendedProfileWidget extends Form ); if (!empty($field['rel'])) { - $this->out->text(' (' . $field['rel'] . ')'); + // TRANS: Value between parentheses (phone number, website, or IM address). + $outtext = sprintf(_m('(%s)'),$field['rel']); + $this->out->text(' '.$outtext); } $this->out->elementEnd('div'); } @@ -314,11 +322,13 @@ class ExtendedProfileWidget extends Form protected function showExperience($name, $field) { $this->out->elementStart('div', 'experience-item'); + // TRANS: Field label in experience area of extended profile. $this->out->element('div', 'label', _m('Company')); if (!empty($field['company'])) { $this->out->element('div', 'field', $field['company']); + // TRANS: Field label in experience area of extended profile (when did one start a position). $this->out->element('div', 'label', _m('Start')); $this->out->element( 'div', @@ -326,6 +336,7 @@ class ExtendedProfileWidget extends Form date('j M Y', strtotime($field['start']) ) ); + // TRANS: Field label in experience area of extended profile (when did one end a position). $this->out->element('div', 'label', _m('End')); $this->out->element( 'div', @@ -338,7 +349,8 @@ class ExtendedProfileWidget extends Form $this->out->element( 'div', array('class' => 'field current'), - '(' . _m('Current') . ')' + // TRANS: Field value in experience area of extended profile (one still holds a position). + _m('(Current)') ); } } @@ -356,6 +368,7 @@ class ExtendedProfileWidget extends Form ) ); + // TRANS: Field label in experience edit area of extended profile (which company does one work for). $this->out->element('div', 'label', _m('Company')); $this->out->input( $id, @@ -363,6 +376,7 @@ class ExtendedProfileWidget extends Form isset($field['company']) ? $field['company'] : null ); + // TRANS: Field label in experience edit area of extended profile (when did one start at a company). $this->out->element('div', 'label', _m('Start')); $this->out->input( $id . '-start', @@ -370,6 +384,7 @@ class ExtendedProfileWidget extends Form isset($field['start']) ? date('j M Y', strtotime($field['start'])) : null ); + // TRANS: Field label in experience edit area of extended profile (when did one terminate at a company). $this->out->element('div', 'label', _m('End')); $this->out->input( @@ -384,6 +399,7 @@ class ExtendedProfileWidget extends Form $this->out->elementStart('div', 'current-checkbox'); $this->out->checkbox( $id . '-current', + // TRANS: Checkbox label in experience edit area of extended profile (one still works at a company). _m('Current'), $field['current'] ); @@ -396,14 +412,17 @@ class ExtendedProfileWidget extends Form protected function showEducation($name, $field) { $this->out->elementStart('div', 'education-item'); + // TRANS: Field label in education area of extended profile. $this->out->element('div', 'label', _m('Institution')); if (!empty($field['school'])) { - $this->out->element('div', 'field', $field['school']); + // TRANS: Field label in education area of extended profile. $this->out->element('div', 'label', _m('Degree')); $this->out->element('div', 'field', $field['degree']); + // TRANS: Field label in education area of extended profile. $this->out->element('div', 'label', _m('Description')); $this->out->element('div', 'field', $field['description']); + // TRANS: Field label in education area of extended profile (when did one start an education). $this->out->element('div', 'label', _m('Start')); $this->out->element( 'div', @@ -411,6 +430,7 @@ class ExtendedProfileWidget extends Form date('j M Y', strtotime($field['start']) ) ); + // TRANS: Field label in education area of extended profile (when did one end a education). $this->out->element('div', 'label', _m('End')); $this->out->element( 'div', @@ -432,6 +452,7 @@ class ExtendedProfileWidget extends Form 'class' => 'education-item' ) ); + // TRANS: Field label in education edit area of extended profile. $this->out->element('div', 'label', _m('Institution')); $this->out->input( $id, @@ -439,6 +460,7 @@ class ExtendedProfileWidget extends Form isset($field['school']) ? $field['school'] : null ); + // TRANS: Field label in education edit area of extended profile. $this->out->element('div', 'label', _m('Degree')); $this->out->input( $id . '-degree', @@ -446,6 +468,7 @@ class ExtendedProfileWidget extends Form isset($field['degree']) ? $field['degree'] : null ); + // TRANS: Field label in education edit area of extended profile. $this->out->element('div', 'label', _m('Description')); $this->out->textarea( @@ -454,17 +477,21 @@ class ExtendedProfileWidget extends Form isset($field['description']) ? $field['description'] : null ); + // TRANS: Field label in education edit area of extended profile (when did one start an education). $this->out->element('div', 'label', _m('Start')); $this->out->input( $id . '-start', null, + // @todo FIXME: does date format need i18n? If so, should probly be dealt with in core. isset($field['start']) ? date('j M Y', strtotime($field['start'])) : null ); + // TRANS: Field label in education edit area of extended profile (when did one end an education). $this->out->element('div', 'label', _m('End')); $this->out->input( $id . '-end', null, + // @todo FIXME: does date format need i18n? If so, should probly be dealt with in core. isset($field['end']) ? date('j M Y', strtotime($field['end'])) : null ); @@ -491,7 +518,8 @@ class ExtendedProfileWidget extends Form 'href' => 'javascript://', 'style' => 'display: none;' ), - 'Add another item' + // TRANS: Link description in extended profile page to add another profile element. + _m('Add another item') ); } @@ -601,7 +629,8 @@ class ExtendedProfileWidget extends Form $this->showEditableEducation($name, $field); break; default: - $out->input($id, null, "TYPE: $type"); + // TRANS: Field label for undefined field in extended profile. + $out->input($id, null, sprintf(_m('TYPE: %s'),$type)); } } @@ -610,14 +639,16 @@ class ExtendedProfileWidget extends Form * * @return void */ - function formActions() { $this->out->submit( 'save', + // TRANS: Button text for saving extended profile properties. _m('BUTTON','Save'), 'submit form_action-secondary', 'save', + // TRANS: . + // TRANS: Button title for saving extended profile properties. _m('Save details') ); } @@ -627,7 +658,6 @@ class ExtendedProfileWidget extends Form * * @return string ID of the form */ - function id() { return 'profile-details-' . $this->profile->id; @@ -638,7 +668,6 @@ class ExtendedProfileWidget extends Form * * @return string of the form class */ - function formClass() { return 'form_profile_details form_settings'; @@ -649,7 +678,6 @@ class ExtendedProfileWidget extends Form * * @return string URL of the action */ - function action() { return common_local_url('profiledetailsettings'); diff --git a/plugins/FacebookBridge/FacebookBridgePlugin.php b/plugins/FacebookBridge/FacebookBridgePlugin.php index 68e931e387..d893baf62d 100644 --- a/plugins/FacebookBridge/FacebookBridgePlugin.php +++ b/plugins/FacebookBridge/FacebookBridgePlugin.php @@ -101,7 +101,6 @@ class FacebookBridgePlugin extends Plugin */ function onAutoload($cls) { - $dir = dirname(__FILE__); //common_debug("class = " . $cls); @@ -128,7 +127,6 @@ class FacebookBridgePlugin extends Plugin default: return true; } - } /** @@ -214,10 +212,11 @@ class FacebookBridgePlugin extends Plugin if ($this->hasApplication()) { $action->menuItem( + // TRANS: Menu item for "Facebook" login. common_local_url('facebooklogin'), _m('MENU', 'Facebook'), - // TRANS: Tooltip for menu item "Facebook". - _m('Login or register using Facebook'), + // TRANS: Menu title for "Facebook" login. + _m('Login or register using Facebook.'), 'facebooklogin' === $action_name ); } @@ -253,10 +252,10 @@ class FacebookBridgePlugin extends Plugin $nav->out->menuItem( common_local_url('facebookadminpanel'), - // TRANS: Menu item. + // TRANS: Menu item for "Facebook" in administration panel. _m('MENU','Facebook'), - // TRANS: Tooltip for menu item "Facebook". - _m('Facebook integration configuration'), + // TRANS: Menu title for "Facebook" in administration panel. + _m('Facebook integration configuration.'), $action_name == 'facebookadminpanel', 'nav_facebook_admin_panel' ); @@ -294,16 +293,14 @@ class FacebookBridgePlugin extends Plugin $action->menuItem( common_local_url('facebooksettings'), - // TRANS: Menu item tab. + // TRANS: Menu item for "Facebook" in user settings. _m('MENU','Facebook'), - // TRANS: Tooltip for menu item "Facebook". - _m('Facebook settings'), + // TRANS: Menu title for "Facebook" in user settings. + _m('Facebook settings.'), $action_name === 'facebooksettings' ); - } } - } /* @@ -324,7 +321,6 @@ class FacebookBridgePlugin extends Plugin if (!empty($appId) && !empty($secret)) { return true; } - } return false; @@ -420,7 +416,6 @@ ENDOFSCRIPT; common_debug("LOGOUT URL = $logoutUrl"); common_redirect($logoutUrl, 303); } - } } @@ -561,6 +556,7 @@ ENDOFSCRIPT; 'author' => 'Craig Andrews, Zach Copley', 'homepage' => 'http://status.net/wiki/Plugin:FacebookBridge', 'rawdescription' => + // TRANS: Plugin description. _m('A plugin for integrating StatusNet with Facebook.') ); diff --git a/plugins/FacebookBridge/actions/facebookadminpanel.php b/plugins/FacebookBridge/actions/facebookadminpanel.php index 034b58b2fa..21c3589008 100644 --- a/plugins/FacebookBridge/actions/facebookadminpanel.php +++ b/plugins/FacebookBridge/actions/facebookadminpanel.php @@ -49,7 +49,8 @@ class FacebookadminpanelAction extends AdminPanelAction */ function title() { - return _m('Facebook'); + // TRANS: Title for Facebook administration panel. + return _m('TITLE','Facebook integration settings'); } /** @@ -59,6 +60,7 @@ class FacebookadminpanelAction extends AdminPanelAction */ function getInstructions() { + // TRANS: Instruction for Facebook administration panel. return _m('Facebook integration settings'); } @@ -120,12 +122,14 @@ class FacebookadminpanelAction extends AdminPanelAction if (mb_strlen($values['facebook']['appid']) > 255) { $this->clientError( + // TRANS: Client error displayed when providing too long a Facebook application ID. _m("Invalid Facebook ID. Maximum length is 255 characters.") ); } if (mb_strlen($values['facebook']['secret']) > 255) { $this->clientError( + // TRANS: Client error displayed when providing too long a Facebook secret key. _m("Invalid Facebook secret. Maximum length is 255 characters.") ); } @@ -175,13 +179,16 @@ class FacebookAdminPanelForm extends AdminForm 'fieldset', array('id' => 'settings_facebook-application') ); + // TRANS: Fieldset legend. $this->out->element('legend', null, _m('Facebook application settings')); $this->out->elementStart('ul', 'form_data'); $this->li(); $this->input( 'appid', + // TRANS: Field label for Facebook application ID. _m('Application ID'), + // TRANS: Field title for Facebook application ID. _m('ID of your Facebook application.'), 'facebook' ); @@ -190,7 +197,9 @@ class FacebookAdminPanelForm extends AdminForm $this->li(); $this->input( 'secret', - _m('Secret'), + // TRANS: Field label for Facebook secret key. + _m('Secret'), + // TRANS: Field title for Facebook secret key. _m('Application secret.'), 'facebook' ); @@ -207,6 +216,9 @@ class FacebookAdminPanelForm extends AdminForm */ function formActions() { - $this->out->submit('submit', _m('BUTTON','Save'), 'submit', null, _m('Save Facebook settings.')); + // TRANS: Button text to save Facebook integration settings. + $this->out->submit('submit', _m('BUTTON','Save'), + // TRANS: Button title to save Facebook integration settings. + 'submit', null, _m('Save Facebook settings.')); } } diff --git a/plugins/FacebookBridge/actions/facebookdeauthorize.php b/plugins/FacebookBridge/actions/facebookdeauthorize.php index 6813ccf1d2..1a83c3a003 100644 --- a/plugins/FacebookBridge/actions/facebookdeauthorize.php +++ b/plugins/FacebookBridge/actions/facebookdeauthorize.php @@ -140,5 +140,4 @@ class FacebookdeauthorizeAction extends Action } } } - -} \ No newline at end of file +} diff --git a/plugins/FacebookBridge/actions/facebookfinishlogin.php b/plugins/FacebookBridge/actions/facebookfinishlogin.php index f952ad2e2b..3d2fb571d7 100644 --- a/plugins/FacebookBridge/actions/facebookfinishlogin.php +++ b/plugins/FacebookBridge/actions/facebookfinishlogin.php @@ -38,7 +38,6 @@ class FacebookfinishloginAction extends Action private $fbuser = null; // Facebook user object (JSON) function prepare($args) { - parent::prepare($args); $this->facebook = new Facebook( @@ -64,7 +63,6 @@ class FacebookfinishloginAction extends Action } if (!empty($this->fbuser)) { - // OKAY, all is well... proceed to register common_debug("Found a valid Facebook user.", __FILE__); @@ -85,6 +83,7 @@ class FacebookfinishloginAction extends Action ); $this->clientError( + // TRANS: Client error displayed when trying to connect to Facebook while not logged in. _m('You must be logged into Facebook to register a local account using Facebook.') ); } @@ -115,6 +114,8 @@ class FacebookfinishloginAction extends Action ); $this->clientError( + // TRANS: Client error displayed when trying to connect to a Facebook account that is already linked + // TRANS: in the same StatusNet site. _m('There is already a local account linked with that Facebook account.') ); @@ -138,6 +139,7 @@ class FacebookfinishloginAction extends Action if (!$token || $token != common_session_token()) { $this->showForm( + // TRANS: Client error displayed when the session token does not match or is not given. _m('There was a problem with your session token. Try again, please.') ); return; @@ -147,6 +149,7 @@ class FacebookfinishloginAction extends Action if (!$this->boolean('license')) { $this->showForm( + // TRANS: Form validation error displayed when user has not agreed to the license. _m('You cannot register if you do not agree to the license.'), $this->trimmed('newname') ); @@ -164,6 +167,7 @@ class FacebookfinishloginAction extends Action } else { $this->showForm( + // TRANS: Form validation error displayed when an unhandled error occurs. _m('An unknown error has occured.'), $this->trimmed('newname') ); @@ -180,8 +184,9 @@ class FacebookfinishloginAction extends Action $this->element( 'div', 'instructions', - // TRANS: %s is the site name. sprintf( + // TRANS: Form instructions for connecting to Facebook. + // TRANS: %s is the site name. _m('This is the first time you have logged into %s so we must connect your Facebook to a local account. You can either create a new local account, or connect with an existing local account.'), common_config('site', 'name') ) @@ -209,7 +214,7 @@ class FacebookfinishloginAction extends Action } /** - * @fixme much of this duplicates core code, which is very fragile. + * @todo FIXME: Much of this duplicates core code, which is very fragile. * Should probably be replaced with an extensible mini version of * the core registration form. */ @@ -225,7 +230,7 @@ class FacebookfinishloginAction extends Action 'class' => 'form_settings', 'action' => common_local_url('facebookfinishlogin'))); $this->elementStart('fieldset', array('id' => 'settings_facebook_connect_options')); - // TRANS: Legend. + // TRANS: Fieldset legend. $this->element('legend', null, _m('Connection options')); $this->elementStart('ul', 'form_data'); $this->elementStart('li'); @@ -252,9 +257,10 @@ class FacebookfinishloginAction extends Action $this->elementStart('fieldset'); $this->hidden('token', common_session_token()); $this->element('legend', null, - // TRANS: Legend. + // TRANS: Fieldset legend. _m('Create new account')); $this->element('p', null, + // TRANS: Form instructions. _m('Create a new user with this nickname.')); $this->elementStart('ul', 'form_data'); @@ -265,6 +271,7 @@ class FacebookfinishloginAction extends Action // TRANS: Field label. $this->input('newname', _m('New nickname'), ($this->username) ? $this->username : '', + // TRANS: Field title. _m('1-64 lowercase letters or numbers, no punctuation or spaces.')); $this->elementEnd('li'); @@ -272,15 +279,16 @@ class FacebookfinishloginAction extends Action Event::handle('EndRegistrationFormData', array($this)); $this->elementEnd('ul'); - // TRANS: Submit button. + // TRANS: Submit button to create a new account. $this->submit('create', _m('BUTTON','Create')); $this->elementEnd('fieldset'); $this->elementStart('fieldset'); - // TRANS: Legend. $this->element('legend', null, + // TRANS: Fieldset legend. _m('Connect existing account')); $this->element('p', null, + // TRANS: Form instructions. _m('If you already have an account, login with your username and password to connect it to your Facebook.')); $this->elementStart('ul', 'form_data'); $this->elementStart('li'); @@ -288,10 +296,11 @@ class FacebookfinishloginAction extends Action $this->input('nickname', _m('Existing nickname')); $this->elementEnd('li'); $this->elementStart('li'); + // TRANS: Field label. $this->password('password', _m('Password')); $this->elementEnd('li'); $this->elementEnd('ul'); - // TRANS: Submit button. + // TRANS: Submit button to connect a Facebook account to an existing StatusNet account. $this->submit('connect', _m('BUTTON','Connect')); $this->elementEnd('fieldset'); @@ -344,11 +353,13 @@ class FacebookfinishloginAction extends Action } if (!User::allowed_nickname($nickname)) { + // TRANS: Form validation error displayed when picking a nickname that is not allowed. $this->showForm(_m('Nickname not allowed.')); return; } if (User::staticGet('nickname', $nickname)) { + // TRANS: Form validation error displayed when picking a nickname that is already in use. $this->showForm(_m('Nickname already in use. Try another one.')); return; } @@ -377,6 +388,7 @@ class FacebookfinishloginAction extends Action $result = $this->flinkUser($user->id, $this->fbuid); if (!$result) { + // TRANS: Server error displayed when connecting to Facebook fails. $this->serverError(_m('Error connecting user to Facebook.')); return; } @@ -479,6 +491,7 @@ class FacebookfinishloginAction extends Action $password = $this->trimmed('password'); if (!common_check_user($nickname, $password)) { + // TRANS: Form validation error displayed when username/password combination is incorrect. $this->showForm(_m('Invalid username or password.')); return; } @@ -516,6 +529,7 @@ class FacebookfinishloginAction extends Action $result = $this->flinkUser($user->id, $this->fbuid); if (empty($result)) { + // TRANS: Server error displayed when connecting to Facebook fails. $this->serverError(_m('Error connecting user to Facebook.')); return; } @@ -687,5 +701,4 @@ class FacebookfinishloginAction extends Action return false; } - } diff --git a/plugins/FacebookBridge/actions/facebooklogin.php b/plugins/FacebookBridge/actions/facebooklogin.php index 924dd46565..fa3cc7a6f2 100644 --- a/plugins/FacebookBridge/actions/facebooklogin.php +++ b/plugins/FacebookBridge/actions/facebooklogin.php @@ -34,12 +34,12 @@ if (!defined('STATUSNET')) { class FacebookloginAction extends Action { - function handle($args) { parent::handle($args); if (common_is_real_login()) { + // TRANS: Client error displayed when trying to login while already logged in. $this->clientError(_m('Already logged in.')); } else { $this->showPage(); @@ -48,7 +48,7 @@ class FacebookloginAction extends Action function getInstructions() { - // TRANS: Instructions. + // TRANS: Form instructions. return _m('Login with your Facebook Account'); } @@ -68,7 +68,6 @@ class FacebookloginAction extends Action } function showContent() { - $this->elementStart('fieldset'); $facebook = Facebookclient::getFacebook(); @@ -90,8 +89,10 @@ class FacebookloginAction extends Action $attrs = array( 'src' => Plugin::staticPath('FacebookBridge', 'images/login-button.png'), - 'alt' => 'Login with Facebook', - 'title' => 'Login with Facebook' + // TRANS: Alt text for "Login with Facebook" image. + 'alt' => _m('Login with Facebook'), + // TRANS: Title for "Login with Facebook" image. + 'title' => _m('Login with Facebook.') ); $this->element('img', $attrs); @@ -117,4 +118,3 @@ class FacebookloginAction extends Action $nav->show(); } } - diff --git a/plugins/FacebookBridge/actions/facebooksettings.php b/plugins/FacebookBridge/actions/facebooksettings.php index 7d45cc03e6..aaa2204035 100644 --- a/plugins/FacebookBridge/actions/facebooksettings.php +++ b/plugins/FacebookBridge/actions/facebooksettings.php @@ -83,6 +83,7 @@ class FacebooksettingsAction extends SettingsAction { $token = $this->trimmed('token'); if (!$token || $token != common_session_token()) { $this->showForm( + // TRANS: Client error displayed when the session token does not match or is not given. _m('There was a problem with your session token. Try again, please.') ); return; @@ -102,7 +103,7 @@ class FacebooksettingsAction extends SettingsAction { */ function title() { // TRANS: Page title for Facebook settings. - return _m('Facebook settings'); + return _m('TITLE','Facebook settings'); } /** @@ -111,6 +112,7 @@ class FacebooksettingsAction extends SettingsAction { * @return instructions for use */ function getInstructions() { + // TRANS: Instructions for Facebook settings. return _m('Facebook settings'); } @@ -134,6 +136,7 @@ class FacebooksettingsAction extends SettingsAction { $this->hidden('token', common_session_token()); + // TRANS: Form note. User is connected to facebook. $this->element('p', 'form_note', _m('Connected Facebook user')); $this->elementStart('p', array('class' => 'facebook-user-display')); @@ -161,6 +164,7 @@ class FacebooksettingsAction extends SettingsAction { $this->checkbox( 'noticesync', + // TRANS: Checkbox label in Facebook settings. _m('Publish my notices to Facebook.'), ($this->flink) ? ($this->flink->noticesync & FOREIGN_NOTICE_SEND) : true ); @@ -171,6 +175,7 @@ class FacebooksettingsAction extends SettingsAction { $this->checkbox( 'replysync', + // TRANS: Checkbox label in Facebook settings. _m('Send "@" replies to Facebook.'), ($this->flink) ? ($this->flink->noticesync & FOREIGN_NOTICE_SEND_REPLY) : true ); @@ -188,13 +193,14 @@ class FacebooksettingsAction extends SettingsAction { $this->elementStart('fieldset'); - // TRANS: Legend. + // TRANS: Fieldset legend for form to disconnect from Facebook. $this->element('legend', null, _m('Disconnect my account from Facebook')); if (empty($this->user->password)) { $this->elementStart('p', array('class' => 'form_guide')); $msg = sprintf( + // TRANS: Notice in disconnect from Facebook form if user has no local StatusNet password. _m( 'Disconnecting your Faceboook would make it impossible to ' . 'log in! Please [set a password](%s) first.' @@ -206,14 +212,11 @@ class FacebooksettingsAction extends SettingsAction { $this->elementEnd('p'); } else { // @todo FIXME: i18n: This message is not being used. - $msg = sprintf( - // TRANS: Message displayed when initiating disconnect of a StatusNet user - // TRANS: from a Facebook account. %1$s is the StatusNet site name. - _m( - 'Keep your %1$s account but disconnect from Facebook. ' . - 'You\'ll use your %1$s password to log in.' - ), - common_config('site', 'name') + // TRANS: Message displayed when initiating disconnect of a StatusNet user + // TRANS: from a Facebook account. %1$s is the StatusNet site name. + $msg = sprintf(_m('Keep your %1$s account but disconnect from Facebook. ' . + 'You\'ll use your %1$s password to log in.'), + common_config('site', 'name') ); // TRANS: Submit button. @@ -240,6 +243,7 @@ class FacebooksettingsAction extends SettingsAction { $result = $this->flink->update($original); if ($result === false) { + // TRANS: Notice in case saving of synchronisation preferences fail. $this->showForm(_m('There was a problem saving your sync preferences.')); } else { // TRANS: Confirmation that synchronisation settings have been saved into the system. @@ -257,10 +261,12 @@ class FacebooksettingsAction extends SettingsAction { if ($result === false) { common_log_db_error($user, 'DELETE', __FILE__); + // TRANS: Server error displayed when deleting the link to a Facebook account fails. $this->serverError(_m('Could not delete link to Facebook.')); return; } + // TRANS: Confirmation message. StatusNet account was unlinked from Facebook. $this->showForm(_m('You have disconnected from Facebook.'), true); } } diff --git a/plugins/FacebookBridge/classes/Notice_to_item.php b/plugins/FacebookBridge/classes/Notice_to_item.php index a6a8030342..d37c95ffc1 100644 --- a/plugins/FacebookBridge/classes/Notice_to_item.php +++ b/plugins/FacebookBridge/classes/Notice_to_item.php @@ -48,7 +48,6 @@ require_once INSTALLDIR . '/classes/Memcached_DataObject.php'; * * @see DB_DataObject */ - class Notice_to_item extends Memcached_DataObject { public $__table = 'notice_to_item'; // table name @@ -67,7 +66,6 @@ class Notice_to_item extends Memcached_DataObject * @return Notice_to_item object found, or null for no hits * */ - function staticGet($k, $v=null) { return Memcached_DataObject::staticGet('Notice_to_item', $k, $v); @@ -81,7 +79,6 @@ class Notice_to_item extends Memcached_DataObject * * @return array array of column definitions */ - function table() { return array( @@ -109,7 +106,6 @@ class Notice_to_item extends Memcached_DataObject * * @return array list of key field names */ - function keys() { return array_keys($this->keyTypes()); @@ -127,7 +123,6 @@ class Notice_to_item extends Memcached_DataObject * 'K' for primary key: for compound keys, add an entry for each component; * 'U' for unique keys: compound keys are not well supported here. */ - function keyTypes() { return array('notice_id' => 'K', 'item_id' => 'U'); @@ -143,7 +138,6 @@ class Notice_to_item extends Memcached_DataObject * * @return array magic three-false array that stops auto-incrementing. */ - function sequenceKey() { return array(false, false, false); @@ -157,7 +151,6 @@ class Notice_to_item extends Memcached_DataObject * * @return Notice_to_item new object for this value */ - static function saveNew($notice_id, $item_id) { $n2i = Notice_to_item::staticGet('notice_id', $notice_id); diff --git a/plugins/FacebookBridge/lib/facebookclient.php b/plugins/FacebookBridge/lib/facebookclient.php index 37d6a0a7a0..ec1331b2a0 100644 --- a/plugins/FacebookBridge/lib/facebookclient.php +++ b/plugins/FacebookBridge/lib/facebookclient.php @@ -340,7 +340,8 @@ class Facebookclient function checkPermission($permission) { if (!in_array($permission, array('publish_stream', 'status_update'))) { - throw new ServerException("No such permission!"); + // TRANS: Server exception thrown when permission check fails. + throw new ServerException(_('No such permission!')); } $fbuid = $this->flink->foreign_id; @@ -397,7 +398,6 @@ class Facebookclient ); return false; - } } @@ -461,7 +461,7 @@ class Facebookclient ), __FILE__ ); - // @fixme: We want to rety at a later time when the throttling has expired + // @todo FIXME: We want to rety at a later time when the throttling has expired // instead of just giving up. return true; break; @@ -582,7 +582,6 @@ class Facebookclient ); if (!empty($result)) { // result will contain the item ID - // Save a mapping Notice_to_item::saveNew($this->notice->id, $result); @@ -598,7 +597,6 @@ class Facebookclient ), __FILE__ ); - } else { $msg = sprintf( @@ -740,7 +738,6 @@ class Facebookclient $result = $this->mailFacebookDisconnect(); if (!$result) { - $msg = 'Unable to send email to notify %s (%d), fbuid %d ' . 'about his/her Facebook link being removed.'; @@ -755,9 +752,7 @@ class Facebookclient __FILE__ ); } - } else { - $msg = 'Unable to send email to notify %s (%d), fbuid %d ' . 'about his/her Facebook link being removed because the ' . 'user has not set an email address.'; @@ -789,26 +784,23 @@ class Facebookclient common_switch_locale($this->user->language); + // TRANS: E-mail subject. $subject = _m('Your Facebook connection has been removed'); - $msg = <<user->nickname, $siteName ); @@ -848,22 +840,21 @@ BODY; common_switch_locale($user->language); + // TRANS: E-mail subject. %s is the StatusNet sitename. $subject = _m('Contact the %s administrator to retrieve your account'); - $msg = <<nickname, $siteName, $siteEmail @@ -990,9 +981,7 @@ BODY; $n2i = Notice_to_item::staticGet('notice_id', $this->notice->id); if (!empty($this->flink) && !empty($n2i)) { - try { - $result = $this->facebook->api( array( 'method' => 'stream.remove', @@ -1002,7 +991,6 @@ BODY; ); if (!empty($result) && result == true) { - common_log( LOG_INFO, sprintf( @@ -1020,7 +1008,6 @@ BODY; } else { throw new FaceboookApiException(var_export($result, true)); } - } catch (FacebookApiException $e) { common_log( LOG_WARNING, @@ -1049,9 +1036,7 @@ BODY; $n2i = Notice_to_item::staticGet('notice_id', $this->notice->id); if (!empty($this->flink) && !empty($n2i)) { - try { - $result = $this->facebook->api( array( 'method' => 'stream.addlike', @@ -1061,7 +1046,6 @@ BODY; ); if (!empty($result) && result == true) { - common_log( LOG_INFO, sprintf( @@ -1073,11 +1057,9 @@ BODY; ), __FILE__ ); - } else { throw new FacebookApiException(var_export($result, true)); } - } catch (FacebookApiException $e) { common_log( LOG_WARNING, @@ -1105,9 +1087,7 @@ BODY; $n2i = Notice_to_item::staticGet('notice_id', $this->notice->id); if (!empty($this->flink) && !empty($n2i)) { - try { - $result = $this->facebook->api( array( 'method' => 'stream.removeLike', @@ -1117,7 +1097,6 @@ BODY; ); if (!empty($result) && result == true) { - common_log( LOG_INFO, sprintf( @@ -1133,7 +1112,6 @@ BODY; } else { throw new FacebookApiException(var_export($result, true)); } - } catch (FacebookApiException $e) { common_log( LOG_WARNING, @@ -1151,5 +1129,4 @@ BODY; } } } - } diff --git a/plugins/Mapstraction/allmap.php b/plugins/Mapstraction/allmap.php index 62d8d04458..d1a9fddabb 100644 --- a/plugins/Mapstraction/allmap.php +++ b/plugins/Mapstraction/allmap.php @@ -46,15 +46,15 @@ class AllmapAction extends MapAction { function prepare($args) { - if(parent::prepare($args)) { + if (parent::prepare($args)) { $cur = common_current_user(); - if (!empty($cur) && $cur->id == $this->user->id) { - $this->notice = $this->user->noticeInbox(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); - } else { - $this->notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); - } + $stream = new InboxNoticeStream($this->user, $cur->getProfile()); + $this->notice = $stream->getNotices(($this->page-1)*NOTICES_PER_PAGE, + NOTICES_PER_PAGE + 1, + null, + null); return true; - }else{ + } else { return false; } } diff --git a/plugins/SQLStats/SQLStatsPlugin.php b/plugins/SQLStats/SQLStatsPlugin.php index 9e810a3ffc..20a9cbada2 100644 --- a/plugins/SQLStats/SQLStatsPlugin.php +++ b/plugins/SQLStats/SQLStatsPlugin.php @@ -25,9 +25,8 @@ if (!defined('STATUSNET')) { * Check DB queries for filesorts and such and log em. * * @package SQLStatsPlugin - * @maintainer Evan Prodromou + * @maintainer Evan Prodromou */ - class SQLStatsPlugin extends Plugin { protected $queryCount = 0; @@ -42,6 +41,7 @@ class SQLStatsPlugin extends Plugin 'author' => 'Evan Prodromou', 'homepage' => 'http://status.net/wiki/Plugin:SQLStats', 'rawdescription' => + // TRANS: Plugin decription. _m('Debug tool to watch for poorly indexed DB queries.')); return true; diff --git a/scripts/createsim.php b/scripts/createsim.php index b460be1dd2..f25890676e 100644 --- a/scripts/createsim.php +++ b/scripts/createsim.php @@ -82,7 +82,8 @@ function newNotice($i, $tagmax) if ($is_reply == 0) { common_set_user($user); - $notices = $user->noticesWithFriends(0, 20); + $stream = new InboxNoticeStream($user); + $notices = $stream->getNotices(0, 20, null, null); if ($notices->N > 0) { $nval = rand(0, $notices->N - 1); $notices->fetch(); // go to 0th