* Copyright (C) 2011, StatusNet, Inc.
*
* Stream of notices for the user's inbox
- *
+ *
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
-
class InboxNoticeStream extends ScopingNoticeStream
{
/**
return $ids;
}
-}
\ No newline at end of file
+}
}
if (empty($api)) {
+ // TRANS: Server exception thrown in oEmbed action if no API endpoint is available.
throw new ServerException(_('No oEmbed API endpoint available.'));
}
'author' => 'Zach Copley',
'homepage' => 'http://status.net/wiki/Plugin:Echo',
'rawdescription' =>
+ // TRANS: Plugin description.
_m('Use <a href="http://aboutecho.com/">Echo</a>'.
' to add commenting to notice pages.'));
return true;
'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;
}
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.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
-
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'),
* @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__);
* @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',
'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;
}
}
/**
* Data class for email summaries
- *
+ *
* Email summary information for users
*
* @category Action
*
* @see DB_DataObject
*/
-
class Email_summary_status extends Memcached_DataObject
{
public $__table = 'email_summary_status'; // table name
*
* @return array array of column definitions
*/
-
function table()
{
return array('user_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
*
* @return array list of key field names
*/
-
function keys()
{
return array_keys($this->keyTypes());
*
* @return array magic three-false array that stops auto-incrementing.
*/
-
function sequenceKey()
{
return array(false, false, false);
*
* @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);
*
* @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 {
<?php
/*
* StatusNet - the distributed open-source microblogging tool
- *
+ *
* Handler for queue items of type 'sitesum', sends email summaries
* to all users on the site.
*
}
/**
- *
+ *
* Handler for queue items of type 'sitesum', sends email summaries
* to all users on the site.
*
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
-
class SiteEmailSummaryHandler extends QueueHandler
{
*
* @return string
*/
-
function transport()
{
return 'sitesum';
/**
* Handle the site
- *
+ *
* @param mixed $object
* @return boolean true on success, false on failure
*/
-
function handle($object)
{
$qm = QueueManager::get();
try {
// Enqueue a summary for all users
-
+
$user = new User();
$user->find();
-
+
while ($user->fetch()) {
try {
$qm->enqueue($user->id, 'usersum');
} catch (Exception $e) {
common_log(LOG_WARNING, $e->getMessage());
}
-
+
return true;
}
}
-
<?php
/**
* StatusNet - the distributed open-source microblogging tool
- *
+ *
* Handler for queue items of type 'usersum', sends an email summaries
* to a particular user.
*
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
-
class UserEmailSummaryHandler extends QueueHandler
{
// Maximum number of notices to include by default. This is probably too much.
-
const MAX_NOTICES = 200;
-
+
/**
* Return transport keyword which identifies items this queue handler
* services; must be defined for all subclasses.
*
* @return string
*/
-
function transport()
{
return 'sitesum';
/**
* Send a summary email to the user
- *
+ *
* @param mixed $object
* @return boolean true on success, false on failure
*/
-
function handle($user_id)
{
// Skip if they've asked not to get summaries
$ess = Email_summary_status::staticGet('user_id', $user_id);
-
+
if (!empty($ess) && !$ess->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) {
// 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');
'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');
$out->elementEnd('td');
$out->elementEnd('tr');
}
-
+
$out->elementEnd('table');
$out->raw(sprintf(_m('<p><a href="%1s">change your email settings for %2s</a></p>'),
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;
}
}
/**
* 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
{
*
* @return boolean hook value; true means continue processing, false means stop.
*/
-
function onRouterInitialized($m)
{
$m->connect('main/event/new',
'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() {
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.'));
}
switch ($activity->verb) {
case ActivityVerb::POST:
- $notice = Happening::saveNew($actor,
- $start_time,
+ $notice = Happening::saveNew($actor,
+ $start_time,
$end_time,
$happeningObj->title,
null,
$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;
*
* @return ActivityObject
*/
-
function activityObjectFromNotice($notice)
{
$happening = null;
}
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.'));
}
*
* @return ActivityObject
*/
-
function onEndNoticeAsActivity($notice, &$act) {
switch ($notice->object_type) {
case RSVP::POSITIVE:
* @param Notice $notice
* @param HTMLOutputter $out
*/
-
function showNotice($notice, $out)
{
switch ($notice->object_type) {
$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',
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');
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');
$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.
* @param HTMLOutputter $out
* @return Widget
*/
-
function entryForm($out)
{
return new EventForm($out);
*
* @param Notice $notice
*/
-
function deleteRelated($notice)
{
switch ($notice->object_type) {
*
* @see Managed_DataObject
*/
-
class Happening extends Managed_DataObject
{
const OBJECT_TYPE = 'http://activitystrea.ms/schema/1.0/event';
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.'));
}
}
$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('<span class="vevent">'.
'<span class="summary">%1$s</span> '.
'<abbr class="dtstart" title="%2$s">%3$s</a> - '.
*
* @see Managed_DataObject
*/
-
class RSVP extends Managed_DataObject
{
const POSITIVE = 'http://activitystrea.ms/schema/1.0/rsvp-yes';
* @param mixed $v Value to lookup
*
* @return RSVP object found, or null for no hits
- *
*/
function staticGet($k, $v=null)
{
* @param array $kv array of key-value mappings
*
* @return Bookmark object found, or null for no hits
- *
*/
function pkeyGet($kv)
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.'));
}
}
'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.'));
}
// XXX: come up with something sexier
$content = $rsvp->asString();
-
+
$rendered = $rsvp->asHTML();
$options = array_merge(array('object_type' => $verb),
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));
}
}
return RSVP::POSSIBLE;
break;
default:
+ // TRANS: Exception thrown when requesting an undefined code for RSVP.
throw new Exception(sprintf(_m('Unknown code "%s".'),$code));
}
}
{
$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;
{
$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;
{
$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;
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("<span class='automatic event-rsvp'><a href='%1\$s'>%2\$s</a> is attending <a href='%3\$s'>%4\$s</a>.</span>");
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("<span class='automatic event-rsvp'><a href='%1\$s'>%2\$s</a> is not attending <a href='%3\$s'>%4\$s</a>.</span>");
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("<span class='automatic event-rsvp'><a href='%1\$s'>%2\$s</a> might attend <a href='%3\$s'>%4\$s</a>.</span>");
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();
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();
* 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
* @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.
* @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;
*
* @return string Action title
*/
-
function title()
{
- return _m('Cancel RSVP');
+ // TRANS: Title for RSVP ("please respond") action.
+ return _m('TITLE','Cancel RSVP');
}
/**
*
* @return boolean true
*/
-
function prepare($argarray)
{
parent::prepare($argarray);
$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.'));
}
*
* @return void
*/
-
function handle($argarray=null)
{
parent::handle($argarray);
*
* @return void
*/
-
function cancelRSVP()
{
try {
*
* @return void
*/
-
function showContent()
{
if (!empty($this->error)) {
*
* @return boolean is read only action?
*/
-
function isReadOnly($args)
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
* 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
* @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;
*
* @return int ID of the form
*/
-
function id()
{
return 'form_event_rsvp';
*
* @return string class of the form
*/
-
function formClass()
{
return 'ajax';
*
* @return string URL of the action
*/
-
function action()
{
return common_local_url('cancelrsvp');
*
* @return void
*/
-
function formData()
{
$this->out->elementStart('fieldset', array('id' => 'new_rsvp_data'));
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;
}
*
* @return void
*/
-
function formActions()
{
+ // TRANS: Button text to cancel responding to an RSVP ("please respond") item.
$this->out->submit('cancel', _m('BUTTON', 'Cancel'));
}
}
.event-title { margin-left: 0px; }
#content .event .entry-title { margin-left: 0px; }
#content .event .entry-content { margin-left: 0px; }
-
* 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
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
-
class EventForm extends Form
{
/**
*
* @return int ID of the form
*/
-
function id()
{
return 'form_new_event';
*
* @return string class of the form
*/
-
function formClass()
{
return 'form_settings ajax-notice';
*
* @return string URL of the action
*/
-
function action()
{
return common_local_url('newevent');
*
* @return void
*/
-
function formData()
{
$this->out->elementStart('fieldset', array('id' => 'new_bookmark_data'));
$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();
*
* @return void
*/
-
function formActions()
{
+ // TRANS: Button text to save an event..
$this->out->submit('submit', _m('BUTTON', 'Save'));
}
}
* Copyright (C) 2011, StatusNet, Inc.
*
* Add a new event
- *
+ *
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* @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.
* @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;
*
* @return string Action title
*/
-
function title()
{
- return _m('New event');
+ // TRANS: Title for new event form.
+ return _m('TITLE','New event');
}
/**
*
* @return boolean true
*/
-
function prepare($argarray)
{
parent::prepare($argarray);
$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);
}
$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.'));
}
$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.'));
}
$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.'));
}
$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));
}
*
* @return void
*/
-
function handle($argarray=null)
{
parent::handle($argarray);
*
* @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.'));
}
// Does the heavy-lifting for getting "To:" information
ToSelector::fillOptions($this, $options);
-
+
$profile = $this->user->getProfile();
$saved = Happening::saveNew($profile,
*
* @return void
*/
-
function showContent()
{
if (!empty($this->error)) {
*
* @return boolean is read only action?
*/
-
function isReadOnly($args)
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
* Copyright (C) 2011, StatusNet, Inc.
*
* RSVP for an event
- *
+ *
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* @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.
* @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;
*
* @return string Action title
*/
-
function title()
{
- return _m('New RSVP');
+ // TRANS: Title for RSVP ("please respond") action.
+ return _m('TITLE','New RSVP');
}
/**
*
* @return boolean true
*/
-
function prepare($argarray)
{
parent::prepare($argarray);
$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.'));
}
$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;
*
* @return void
*/
-
function handle($argarray=null)
{
parent::handle($argarray);
*
* @return void
*/
-
function newRSVP()
{
try {
$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');
*
* @return void
*/
-
function showContent()
{
if (!empty($this->error)) {
*
* @return boolean is read only action?
*/
-
function isReadOnly($args)
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
* 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
* @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;
*
* @return int ID of the form
*/
-
function id()
{
return 'form_event_rsvp';
*
* @return string class of the form
*/
-
function formClass()
{
return 'ajax';
*
* @return string URL of the action
*/
-
function action()
{
return common_local_url('newrsvp');
*
* @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);
*
* @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',
* Copyright (C) 2011, StatusNet, Inc.
*
* Show a single event
- *
+ *
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* Copyright (C) 2010, StatusNet, Inc.
*
* Show a single RSVP
- *
+ *
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
*/
class ExtendedProfilePlugin extends Plugin
{
-
function onPluginVersion(&$versions)
{
$versions[] = array(
'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;
$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;
}
-
}
* @return User_greeting_count object found, or null for no hits
*
*/
-
function staticGet($k, $v=null)
{
return Memcached_DataObject::staticGet('Profile_detail', $k, $v);
* @return Bookmark object found, or null for no hits
*
*/
-
function pkeyGet($kv)
{
return Memcached_DataObject::pkeyGet('Profile_detail', $kv);
static function schemaDef()
{
return array(
+ // No need for i18n. Table properties.
'description'
=> 'Additional profile details for the ExtendedProfile plugin',
'fields' => array(
)
);
}
-
}
if (empty($phones)) {
$pArrays[] = array(
+ // TRANS: Field label for extended profile properties.
'label' => _m('Phone'),
'index' => 0,
'type' => 'phone',
} 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),
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),
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),
if (empty($companies)) {
$eArrays[] = array(
+ // TRANS: Field label for extended profile properties.
'label' => _m('Employer'),
'type' => 'experience',
'company' => null,
} 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,
if (empty($schools)) {
$iArrays[] = array(
'type' => 'education',
+ // TRANS: Field label for extended profile properties.
'label' => _m('Institution'),
'school' => null,
'degree' => null,
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,
{
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',
),
),
'contact' => array(
+ // TRANS: Field label for extended profile properties.
'label' => _m('Contact'),
'fields' => array(
'phone' => $this->getPhones(),
),
),
'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()
// 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();
}
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');
$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');
}
);
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');
}
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',
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',
$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)')
);
}
}
)
);
+ // 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,
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',
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(
$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']
);
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',
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',
'class' => 'education-item'
)
);
+ // TRANS: Field label in education edit area of extended profile.
$this->out->element('div', 'label', _m('Institution'));
$this->out->input(
$id,
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',
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(
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
);
'href' => 'javascript://',
'style' => 'display: none;'
),
- 'Add another item'
+ // TRANS: Link description in extended profile page to add another profile element.
+ _m('Add another item')
);
}
$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));
}
}
*
* @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')
);
}
*
* @return string ID of the form
*/
-
function id()
{
return 'profile-details-' . $this->profile->id;
*
* @return string of the form class
*/
-
function formClass()
{
return 'form_profile_details form_settings';
*
* @return string URL of the action
*/
-
function action()
{
return common_local_url('profiledetailsettings');
*/
function onAutoload($cls)
{
-
$dir = dirname(__FILE__);
//common_debug("class = " . $cls);
default:
return true;
}
-
}
/**
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
);
}
$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'
);
$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'
);
-
}
}
-
}
/*
if (!empty($appId) && !empty($secret)) {
return true;
}
-
}
return false;
common_debug("LOGOUT URL = $logoutUrl");
common_redirect($logoutUrl, 303);
}
-
}
}
'author' => 'Craig Andrews, Zach Copley',
'homepage' => 'http://status.net/wiki/Plugin:FacebookBridge',
'rawdescription' =>
+ // TRANS: Plugin description.
_m('A plugin for integrating StatusNet with Facebook.')
);
*/
function title()
{
- return _m('Facebook');
+ // TRANS: Title for Facebook administration panel.
+ return _m('TITLE','Facebook integration settings');
}
/**
*/
function getInstructions()
{
+ // TRANS: Instruction for Facebook administration panel.
return _m('Facebook integration settings');
}
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.")
);
}
'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'
);
$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'
);
*/
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.'));
}
}
}
}
}
-
-}
\ No newline at end of file
+}
private $fbuser = null; // Facebook user object (JSON)
function prepare($args) {
-
parent::prepare($args);
$this->facebook = new Facebook(
}
if (!empty($this->fbuser)) {
-
// OKAY, all is well... proceed to register
common_debug("Found a valid Facebook user.", __FILE__);
);
$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.')
);
}
);
$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.')
);
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;
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')
);
} else {
$this->showForm(
+ // TRANS: Form validation error displayed when an unhandled error occurs.
_m('An unknown error has occured.'),
$this->trimmed('newname')
);
$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')
)
}
/**
- * @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.
*/
'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');
$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');
// 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');
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');
$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');
}
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;
}
$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;
}
$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;
}
$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;
}
return false;
}
-
}
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();
function getInstructions()
{
- // TRANS: Instructions.
+ // TRANS: Form instructions.
return _m('Login with your Facebook Account');
}
}
function showContent() {
-
$this->elementStart('fieldset');
$facebook = Facebookclient::getFacebook();
$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);
$nav->show();
}
}
-
$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;
*/
function title() {
// TRANS: Page title for Facebook settings.
- return _m('Facebook settings');
+ return _m('TITLE','Facebook settings');
}
/**
* @return instructions for use
*/
function getInstructions() {
+ // TRANS: Instructions for Facebook settings.
return _m('Facebook settings');
}
$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'));
$this->checkbox(
'noticesync',
+ // TRANS: Checkbox label in Facebook settings.
_m('Publish my notices to Facebook.'),
($this->flink) ? ($this->flink->noticesync & FOREIGN_NOTICE_SEND) : true
);
$this->checkbox(
'replysync',
+ // TRANS: Checkbox label in Facebook settings.
_m('Send "@" replies to Facebook.'),
($this->flink) ? ($this->flink->noticesync & FOREIGN_NOTICE_SEND_REPLY) : true
);
$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.'
$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.
$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.
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);
}
}
*
* @see DB_DataObject
*/
-
class Notice_to_item extends Memcached_DataObject
{
public $__table = 'notice_to_item'; // table name
* @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);
*
* @return array array of column definitions
*/
-
function table()
{
return array(
*
* @return array list of key field names
*/
-
function keys()
{
return array_keys($this->keyTypes());
* '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');
*
* @return array magic three-false array that stops auto-incrementing.
*/
-
function sequenceKey()
{
return array(false, false, false);
*
* @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);
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;
);
return false;
-
}
}
),
__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;
);
if (!empty($result)) { // result will contain the item ID
-
// Save a mapping
Notice_to_item::saveNew($this->notice->id, $result);
),
__FILE__
);
-
} else {
$msg = sprintf(
$result = $this->mailFacebookDisconnect();
if (!$result) {
-
$msg = 'Unable to send email to notify %s (%d), fbuid %d '
. 'about his/her Facebook link being removed.';
__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.';
common_switch_locale($this->user->language);
+ // TRANS: E-mail subject.
$subject = _m('Your Facebook connection has been removed');
- $msg = <<<BODY
-Hi %1$s,
-
-We're sorry to inform you we are unable to publish your notice to
-Facebook, and have removed the connection between your %2$s account and
-Facebook.
+ // TRANS: E-mail body. %1$s is a username, %2$s is the StatusNet sitename.
+ $msg = _m("Hi %1\$s,\n\n".
+ "We are sorry to inform you we are unable to publish your notice to\n".
+ "Facebook, and have removed the connection between your %2\$s account and\n".
+ "Facebook.\n\n".
+ "This may have happened because you have removed permission for %2\$s\n".
+ "to post on your behalf, or perhaps you have deactivated your Facebook\n".
+ "account. You can reconnect your %2\$s account to Facebook at any time by\n".
+ "logging in with Facebook again.\n\n".
+ "Sincerely,\n\n".
+ "%2\$s\n");
-This may have happened because you have removed permission for %2$s
-to post on your behalf, or perhaps you have deactivated your Facebook
-account. You can reconnect your %s account to Facebook at any time by
-logging in with Facebook again.
-
-Sincerely,
-
-%2$s
-BODY;
$body = sprintf(
- _m($msg),
+ $msg,
$this->user->nickname,
$siteName
);
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 = <<<BODY
-Hi %1$s,
-
-We've noticed you have deauthorized the Facebook connection for your
-%2$s account. You have not set a password for your %2$s account yet, so
-you will not be able to login. If you wish to continue using your %2$s
-account, please contact the site administrator (%3$s) to set a password.
+ // TRANS: E-mail body. %1$s is a username,
+ // TRANS: %2$s is the StatusNet sitename, %3$s is the site contact e-mail address.
+ $msg = _m("Hi %1\$s,\n\n".
+ "We have noticed you have deauthorized the Facebook connection for your\n".
+ "%2\$s account. You have not set a password for your %2\$s account yet, so\n".
+ "you will not be able to login. If you wish to continue using your %2\$s\n".
+ "account, please contact the site administrator (%3\$s) to set a password.\n\n".
+ "Sincerely,\n\n".
+ "%2\$s\n");
-Sincerely,
-
-%2$s
-BODY;
$body = sprintf(
- _m($msg),
+ $msg,
$user->nickname,
$siteName,
$siteEmail
$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',
);
if (!empty($result) && result == true) {
-
common_log(
LOG_INFO,
sprintf(
} else {
throw new FaceboookApiException(var_export($result, true));
}
-
} catch (FacebookApiException $e) {
common_log(
LOG_WARNING,
$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',
);
if (!empty($result) && result == true) {
-
common_log(
LOG_INFO,
sprintf(
),
__FILE__
);
-
} else {
throw new FacebookApiException(var_export($result, true));
}
-
} catch (FacebookApiException $e) {
common_log(
LOG_WARNING,
$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',
);
if (!empty($result) && result == true) {
-
common_log(
LOG_INFO,
sprintf(
} else {
throw new FacebookApiException(var_export($result, true));
}
-
} catch (FacebookApiException $e) {
common_log(
LOG_WARNING,
}
}
}
-
}
<?php
/*
-StatusNet Plugin: 0.9
-Plugin Name: FirePHP
-Description: Sends StatusNet log output to FirePHP
-Version: 0.1
-Author: Craig Andrews <candrews@integralblue.com>
-Author URI: http://candrews.integralblue.com/
+ * StatusNet Plugin: 0.9
+ * Plugin Name: FirePHP
+ * Description: Sends StatusNet log output to FirePHP
+ * Version: 0.1
+ * Author: Craig Andrews <candrews@integralblue.com>
+ * Author URI: http://candrews.integralblue.com/
*/
/*
'author' => 'Craig Andrews',
'homepage' => 'http://status.net/wiki/Plugin:FirePHP',
'rawdescription' =>
+ // TRANS: Plugin description.
_m('The FirePHP plugin writes StatusNet\'s log output to FirePHP.'));
return true;
}
The FirePHP plugin writes StatusNet's log output to FirePHP.
Using FirePHP on production sites can expose sensitive information.
- You must protect the security of your application by disabling FirePHP
- logging on your live site.
+
+You must protect the security of your application by disabling FirePHP logging
+on your live site!
Installation
============
=======
addPlugin('FirePHP', array());
-
* @param User &$newUser The new user
*
* @return boolean hook value
- *
*/
function onEndUserRegister(&$newProfile, &$newUser)
{
$schema = Schema::get();
// For storing user-submitted flags on profiles
-
$schema->ensureTable('user_followeveryone_prefs',
array(new ColumnDef('user_id', 'integer', null,
true, 'PRI'),
'author' => 'Evan Prodromou',
'homepage' => 'http://status.net/wiki/Plugin:FollowEveryone',
'rawdescription' =>
+ // TRANS: Plugin description.
_m('New users follow everyone at registration and are followed in return.'));
return true;
}
* List by local nickname.
*/
public $post = array();
-
+
/**
* New user registrations will automatically join these groups on
* registration. They're not prevented from leaving, however.
- *
+ *
* List by local nickname.
*/
public $join = array();
'author' => 'Evan Prodromou',
'homepage' => 'http://status.net/wiki/Plugin:GeoURL',
'rawdescription' =>
+ // TRANS: Plugin description.
_m('Ping <a href="http://geourl.org/">GeoURL</a> when '.
'new geolocation-enhanced notices are posted.'));
return true;
function getGeonames($method, $params)
{
if ($this->lastTimeout && (time() - $this->lastTimeout < $this->timeoutWindow)) {
- throw new Exception("skipping due to recent web service timeout");
+ // TRANS: Exception thrown when a geo names service is not used because of a recent timeout.
+ throw new Exception(_m('Skipping due to recent web service timeout.'));
}
$client = HTTPClient::start();
}
if (!$result->isOk()) {
- throw new Exception("HTTP error code " . $result->getStatus());
+ // TRANS: Exception thrown when a geo names service does not return an expected response.
+ // TRANS: %s is an HTTP error code.
+ throw new Exception(sprintf(_m('HTTP error code %s.'),$result->getStatus()));
}
$body = $result->getBody();
if (empty($body)) {
- throw new Exception("Empty HTTP body in response");
+ // TRANS: Exception thrown when a geo names service returns an empty body.
+ throw new Exception(_m('Empty HTTP body in response.'));
}
// This will throw an exception if the XML is mal-formed
}
if (isset($document->status)) {
- throw new Exception("Error #".$document->status['value']." ('".$document->status['message']."')");
+ // TRANS: Exception thrown when a geo names service return a specific error number and error text.
+ // TRANS: %1$s is an error code, %2$s is an error message.
+ throw new Exception(sprintf(_m('Error #%1$s ("%2$s").'),$document->status['value'],$document->status['message']));
}
// Array of elements, >0 elements
'author' => 'Evan Prodromou',
'homepage' => 'http://status.net/wiki/Plugin:Geonames',
'rawdescription' =>
+ // TRANS: Plugin description.
_m('Uses <a href="http://geonames.org/">Geonames</a> service to get human-readable '.
'names for locations based on user-provided lat/long pairs.'));
return true;
'author' => 'Evan Prodromou',
'homepage' => 'http://status.net/wiki/Plugin:GoogleAnalytics',
'rawdescription' =>
+ // TRANS: Plugin description.
_m('Use <a href="http://www.google.com/analytics/">Google Analytics</a>'.
' to track web access.'));
return true;
'action' =>
common_local_url('avatarsettings')));
$action->elementStart('fieldset', array('id' => 'settings_gravatar_add'));
+ // TRANS: Fieldset legend. Gravatar is an avatar service.
$action->element('legend', null, _m('Set Gravatar'));
$action->hidden('token', common_session_token());
$action->element('p', 'form_guide',
+ // TRANS: Form guide. Gravatar is an avatar service.
_m('If you want to use your Gravatar image, click "Add".'));
$action->element('input', array('type' => 'submit',
'id' => 'settings_gravatar_add_action-submit',
'name' => 'add',
'class' => 'submit',
- 'value' => _m('Add')));
+ // TRANS: Button text to add a Gravatar. Gravatar is an avatar service.
+ 'value' => _m('BUTTON','Add')));
$action->elementEnd('fieldset');
$action->elementEnd('form');
} elseif($hasGravatar) {
'action' =>
common_local_url('avatarsettings')));
$action->elementStart('fieldset', array('id' => 'settings_gravatar_remove'));
+ // TRANS: Fieldset legend. Gravatar is an avatar service.
$action->element('legend', null, _m('Remove Gravatar'));
$action->hidden('token', common_session_token());
$action->element('p', 'form_guide',
+ // TRANS: Form guide. Gravatar is an avatar service.
_m('If you want to remove your Gravatar image, click "Remove".'));
$action->element('input', array('type' => 'submit',
'id' => 'settings_gravatar_remove_action-submit',
'name' => 'remove',
'class' => 'submit',
+ // TRANS: Button text to remove a Gravatar. Gravatar is an avatar service.
'value' => _m('Remove')));
$action->elementEnd('fieldset');
$action->elementEnd('form');
} else {
$action->element('p', 'form_guide',
+ // TRANS: Form guide. Gravatar is an avatar service.
_m('To use a Gravatar first enter in an email address.'));
}
}
$cur = common_current_user();
if(empty($cur->email)) {
+ // TRANS: Message displayed when no e-mail address was set when saving Gravatar setting. Gravatar is an avatar service.
return array('message' => _m('You do not have an email address set in your profile.'),
'success' => false);
}
$gravatar->created = DB_DataObject_Cast::dateTime(); # current time
if (!$gravatar->insert()) {
+ // TRANS: Message displayed when saving Gravatar setting fails. Gravatar is an avatar service.
return array('message' => _m('Failed to save Gravatar to the database.'),
'success' => false);
}
}
+ // TRANS: Message displayed when Gravatar was added. Gravatar is an avatar service.
return array('message' => _m('Gravatar added.'),
'success' => true);
}
$avatar = $profile->getAvatar(AVATAR_MINI_SIZE);
if($avatar) $avatar->delete();
+ // TRANS: Message displayed when Gravatar was removed. Gravatar is an avatar service.
return array('message' => _m('Gravatar removed.'),
'success' => true);
}
'author' => 'Eric Helgeson',
'homepage' => 'http://status.net/wiki/Plugin:Gravatar',
'rawdescription' =>
+ // TRANS: Plugin decsription.
_m('The Gravatar plugin allows users to use their <a href="http://www.gravatar.com/">Gravatar</a> with StatusNet.'));
return true;
GravatarPlugin 0.1
-About
+About:
This will allow users to use their Gravatar Avatar with your StatusNet install.
-Configuration
+Configuration:
add this to your config.php:
addPlugin('Gravatar', array());
-ToDo:
+To do:
Site default all on for gravatar by default
Migration Script
-Localize
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
-
class GroupPrivateMessagePlugin extends Plugin
{
/**
*
* @return boolean hook value
*/
-
function onCheckSchema()
{
$schema = Schema::get();
'datetime'),
new ColumnDef('modified',
'timestamp')));
-
+
$schema->ensureTable('group_message',
array(new ColumnDef('id',
'char',
*
* @return boolean hook value
*/
-
function onAutoload($cls)
{
$dir = dirname(__FILE__);
*
* @return boolean hook value
*/
-
function onRouterInitialized($m)
{
$m->connect('group/:nickname/inbox',
*
* @see Action
*/
-
function onEndGroupGroupNav($groupnav)
{
$action = $groupnav->action;
$action->menuItem(common_local_url('groupinbox',
array('nickname' => $group->nickname)),
+ // TRANS: Menu item in group page.
_m('MENU','Inbox'),
+ // TRANS: Menu title in group page.
_m('Private messages for this group.'),
$action->trimmed('action') == 'groupinbox',
'nav_group_inbox');
*
* @result boolean hook value
*/
-
function onEndGroupSave($group)
{
$gps = new Group_privacy_settings();
*
* @param GroupEditForm $form form being shown
*/
-
function onEndGroupEditFormData($form)
{
$gps = null;
$form->out->elementStart('li');
$form->out->dropdown('allow_privacy',
+ // TRANS: Dropdown label in group settings page for if group allows private messages.
_m('Private messages'),
+ // TRANS: Dropdown option in group settings page for allowing private messages.
array(Group_privacy_settings::SOMETIMES => _m('Sometimes'),
+ // TRANS: Dropdown option in group settings page for allowing private messages.
Group_privacy_settings::ALWAYS => _m('Always'),
+ // TRANS: Dropdown option in group settings page for allowing private messages.
Group_privacy_settings::NEVER => _m('Never')),
+ // TRANS: Dropdown title in group settings page for if group allows private messages.
_m('Whether to allow private messages to this group.'),
false,
(empty($gps)) ? Group_privacy_settings::SOMETIMES : $gps->allow_privacy);
$form->out->elementEnd('li');
$form->out->elementStart('li');
$form->out->dropdown('allow_sender',
+ // TRANS: Dropdown label in group settings page for who can send private messages to the group.
_m('Private senders'),
+ // TRANS: Dropdown option in group settings page for who can send private messages.
array(Group_privacy_settings::EVERYONE => _m('Everyone'),
+ // TRANS: Dropdown option in group settings page for who can send private messages.
Group_privacy_settings::MEMBER => _m('Member'),
+ // TRANS: Dropdown option in group settings page for who can send private messages.
Group_privacy_settings::ADMIN => _m('Admin')),
+ // TRANS: Dropdown title in group settings page for who can send private messages to the group.
_m('Who can send private messages to the group.'),
false,
(empty($gps)) ? Group_privacy_settings::MEMBER : $gps->allow_sender);
} else {
$orig = clone($gps);
}
-
+
$gps->allow_privacy = $action->trimmed('allow_privacy');
$gps->allow_sender = $action->trimmed('allow_sender');
} else {
$gps->update($orig);
}
-
+
return true;
}
/**
* Overload 'd' command to send private messages to groups.
- *
+ *
* 'd !group word word word' will send the private message
* 'word word word' to the group 'group'.
- *
+ *
* @param string $cmd Command being run
* @param string $arg Rest of the message (including address)
* @param User $user User sending the message
* @param Command &$result The resulting command object to be run.
- *
+ *
* @return boolean hook value
*/
function onStartIntepretCommand($cmd, $arg, $user, &$result)
*
* @param Widget $widget The showgroup action being shown
* @param User_group $group The current group
- *
+ *
* @return boolean hook value
*/
function onEndGroupActionsList($widget, $group)
$action->elementStart('li', 'entity_send-a-message');
$action->element('a', array('href' => common_local_url('newgroupmessage', array('nickname' => $group->nickname)),
+ // TRANS: Title for action in group actions list.
'title' => _m('Send a direct message to this group.')),
- _m('Message'));
+ // TRANS: Link text for action in group actions list to send a private message to a group.
+ _m('LINKTEXT','Message'));
// $form = new GroupMessageForm($action, $group);
// $form->hidden = true;
// $form->show();
* privacy == always, force a group private message to all mentioned groups.
* If any of the groups disallows private messages, skip it.
*
- * @param
- *
+ * @param
*/
-
function onStartNoticeSave(&$notice) {
-
// Look for group tags
// FIXME: won't work for remote groups
// @fixme if Notice::saveNew is refactored so we can just pull its list
$profile = $notice->getProfile();
if ($count > 0) {
-
/* Add them to the database */
foreach (array_unique($match[1]) as $nickname) {
-
$group = User_group::getForNickname($nickname, $profile);
if (empty($group)) {
}
if ($forcePrivate) {
-
foreach ($ignored as $group) {
common_log(LOG_NOTICE,
"Notice forced to group direct message ".
// Don't save the notice!
// FIXME: this is probably cheating.
+ // TRANS: Client exception thrown when a private group message has to be forced.
throw new ClientException(sprintf(_m('Forced notice to private group message.')),
200);
}
}
-
+
return true;
}
*
* @return boolean hook value
*/
-
function onEndGroupProfileElements($action, $group)
{
$gps = Group_privacy_settings::forGroup($group);
-
+
if ($gps->allow_privacy == Group_privacy_settings::ALWAYS) {
+ // TRANS: Indicator on the group page that the group is (essentially) private.
$action->element('p', 'privategroupindicator', _m('Private'));
}
{
if ($action instanceof ShowgroupAction) {
$gps = Group_privacy_settings::forGroup($action->group);
-
+
if ($gps->allow_privacy == Group_privacy_settings::ALWAYS) {
return false;
}
'author' => 'Evan Prodromou',
'homepage' => 'http://status.net/wiki/Plugin:GroupPrivateMessage',
'rawdescription' =>
+ // TRANS: Plugin description.
_m('Allow posting private messages to groups.'));
return true;
}
*
* @see DB_DataObject
*/
-
class Group_message extends Memcached_DataObject
{
public $__table = 'group_message'; // table name
* @param mixed $v Value to lookup
*
* @return Group_message object found, or null for no hits
- *
*/
function staticGet($k, $v=null)
{
{
if (!$user->hasRight(Right::NEWMESSAGE)) {
// XXX: maybe break this out into a separate right
+ // TRANS: Exception thrown when trying to send group private message without having the right to do that.
+ // TRANS: %s is a user nickname.
throw new Exception(sprintf(_m('User %s is not allowed to send private messages.'),
$user->nickname));
}
// We use the same limits as for 'regular' private messages.
if (Message::contentTooLong($text)) {
+ // TRANS: Exception thrown when trying to send group private message that is too long.
+ // TRANS: %d is the maximum meggage length.
throw new Exception(sprintf(_m('That\'s too long. Maximum message size is %d character.',
'That\'s too long. Maximum message size is %d characters.',
Message::maxContent()),
// Valid! Let's do this thing!
$gm = new Group_message();
-
+
$gm->id = UUID::gen();
$gm->uri = common_local_url('showgroupmessage', array('id' => $gm->id));
$gm->from_profile = $user->id;
function distribute()
{
$group = User_group::staticGet('id', $this->to_group);
-
+
$member = $group->getMembers();
while ($member->fetch()) {
{
$group = User_group::staticGet('id', $this->to_group);
if (empty($group)) {
+ // TRANS: Exception thrown when trying to send group private message to a non-existing group.
throw new ServerException(_m('No group for group message.'));
}
return $group;
{
$sender = Profile::staticGet('id', $this->from_profile);
if (empty($sender)) {
+ // TRANS: Exception thrown when trying to send group private message without having a sender.
throw new ServerException(_m('No sender for group message.'));
}
return $sender;
return $gm;
}
-
}
*
* @see DB_DataObject
*/
-
class Group_message_profile extends Memcached_DataObject
{
public $__table = 'group_message_profile'; // table name
* @param mixed $v Value to lookup
*
* @return Group_message object found, or null for no hits
- *
*/
function staticGet($k, $v=null)
{
function send($gm, $profile)
{
$gmp = new Group_message_profile();
-
+
$gmp->group_message_id = $gm->id;
$gmp->to_profile = $profile->id;
$gmp->created = common_sql_now();
$this->notifyByMail();
}
- function notifyByMail()
+ function notifyByMail()
{
$to = User::staticGet('id', $this->to_profile);
// TRANS: %3$s is the message content, %4$s a URL to the message,
// TRANS: %5$s is the StatusNet sitename.
$body = sprintf(_m("%1\$s (%2\$s) sent a private message to group %3\$s:\n\n".
- "------------------------------------------------------\n".
- "%4\$s\n".
- "------------------------------------------------------\n\n".
- "You can reply to their message here:\n\n".
- "%5\$s\n\n".
- "Do not reply to this email; it will not get to them.\n\n".
- "With kind regards,\n".
- "%6\$s"),
+ "------------------------------------------------------\n".
+ "%4\$s\n".
+ "------------------------------------------------------\n\n".
+ "You can reply to their message here:\n\n".
+ "%5\$s\n\n".
+ "Do not reply to this email; it will not get to them.\n\n".
+ "With kind regards,\n".
+ "%6\$s"),
$from_profile->getBestName(),
$from_profile->nickname,
$group->nickname,
*
* @see DB_DataObject
*/
-
class Group_privacy_settings extends Memcached_DataObject
{
public $__table = 'group_privacy_settings';
/** ID of the group. */
- public $group_id;
+ public $group_id;
/** When to allow privacy: always, sometimes, or never. */
public $allow_privacy;
/** Who can send private messages: everyone, member, admin */
- public $allow_sender;
+ public $allow_sender;
/** row creation timestamp */
public $created;
/** Last-modified timestamp */
*
* @return User_greeting_count object found, or null for no hits
*/
-
function staticGet($k, $v=null)
{
return Memcached_DataObject::staticGet('Group_privacy_settings', $k, $v);
*
* @return array array of column definitions
*/
-
function table()
{
return array('group_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
'allow_sender' => DB_DATAOBJECT_INT,
'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL,
'modified' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
-
+
}
/**
*
* @return array list of key field names
*/
-
function keys()
{
return array_keys($this->keyTypes());
* '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('group_id' => 'K');
*
* @return array magic three-false array that stops auto-incrementing.
*/
-
function sequenceKey()
{
return array(false, false, false);
$gps = self::forGroup($group);
if ($gps->allow_privacy == Group_privacy_settings::NEVER) {
+ // TRANS: Exception thrown when trying to set group privacy setting if group %s does not allow private messages.
throw new Exception(sprintf(_m('Group %s does not allow private messages.'),
$group->nickname));
}
case Group_privacy_settings::EVERYONE:
$profile = $user->getProfile();
if (Group_block::isBlocked($group, $profile)) {
+ // TRANS: Exception thrown when trying to send group private message while blocked from that group.
+ // TRANS: %1$s is a user nickname, %2$s is a group nickname.
throw new Exception(sprintf(_m('User %1$s is blocked from group %2$s.'),
$user->nickname,
$group->nickname));
break;
case Group_privacy_settings::MEMBER:
if (!$user->isMember($group)) {
+ // TRANS: Exception thrown when trying to send group private message while not a member.
+ // TRANS: %1$s is a user nickname, %2$s is a group nickname.
throw new Exception(sprintf(_m('User %1$s is not a member of group %2$s.'),
$user->nickname,
$group->nickname));
break;
case Group_privacy_settings::ADMIN:
if (!$user->isAdmin($group)) {
+ // TRANS: Exception thrown when trying to send group private message while not a group administrator.
+ // TRANS: %1$s is a user nickname, %2$s is a group nickname.
throw new Exception(sprintf(_m('User %1$s is not an administrator of group %2$s.'),
$user->nickname,
$group->nickname));
}
break;
default:
+ // TRANS: Exception thrown when encountering undefined group privacy settings.
+ // TRANS: %s is a group nickname.
throw new Exception(sprintf(_m('Unknown privacy settings for group %s.'),
$group->nickname));
}
* Copyright (C) 2011, StatusNet, Inc.
*
* List of private messages to this group
- *
+ *
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
-
class GroupinboxAction extends GroupDesignAction
{
var $gm;
$cur = common_current_user();
if (empty($cur)) {
+ // TRANS: Client exception thrown when trying to view group inbox while not logged in.
throw new ClientException(_m('Only for logged-in users.'), 403);
}
$localGroup = Local_group::staticGet('nickname', $nickname);
if (empty($localGroup)) {
+ // TRANS: Client exception thrown when trying to view group inbox for non-existing group.
throw new ClientException(_m('No such group.'), 404);
}
$this->group = User_group::staticGet('id', $localGroup->group_id);
if (empty($this->group)) {
+ // TRANS: Client exception thrown when trying to view group inbox for non-existing group.
throw new ClientException(_m('No such group.'), 404);
}
if (!$cur->isMember($this->group)) {
+ // TRANS: Client exception thrown when trying to view group inbox while not a member.
throw new ClientException(_m('Only for members.'), 403);
}
if (!$this->page) {
$this->page = 1;
}
-
- $this->gm = Group_message::forGroup($this->group,
+
+ $this->gm = Group_message::forGroup($this->group,
($this->page - 1) * MESSAGES_PER_PAGE,
MESSAGES_PER_PAGE + 1);
return true;
$cnt = $gml->show();
if ($cnt == 0) {
+ // TRANS: Text of group inbox if no private messages were sent to it.
$this->element('p', 'guide', _m('This group has not received any private messages.'));
}
$this->pagination($this->page > 1,
$base = $this->group->getFancyName();
if ($this->page == 1) {
+ // TRANS: Title of inbox for group %s.
return sprintf(_m('%s group inbox'), $base);
} else {
// TRANS: Page title for any but first group page.
*
* @return void
*/
-
function showPageNotice()
{
$instr = $this->getInstructions();
* Copyright (C) 2011, StatusNet, Inc.
*
* Command object for messages to groups
- *
+ *
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
-
class GroupMessageCommand extends Command
{
/** User sending the message. */
* @param string $nickname Nickname of the group
* @param string $text Text of message
*/
-
function __construct($user, $nickname, $text)
{
$this->user = $user;
$gm = Group_message::send($this->user, $group, $this->text);
- $channel->output($this->user,
- sprintf(_m('Direct message to group %s sent.'),
+ $channel->output($this->user,
+ // TRANS: Succes message after sending private group message to group %s.
+ sprintf(_m('Direct message to group %s sent.'),
$group->nickname));
return true;
* Copyright (C) 2011, StatusNet, Inc.
*
* Form for posting a group message
- *
+ *
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
-
class GroupMessageForm extends Form
{
var $group;
*
* @todo add a drop-down list to post to any group
*/
-
function __construct($out, $group, $content=null)
{
parent::__construct($out);
* Action for the form
*/
function action()
- {
+ {
return common_local_url('newgroupmessage',
array('nickname' => $this->group->nickname));
}
{
$this->out->element('legend',
null,
+ // TRANS: Form legend for sending private message to group %s.
sprintf(_m('Message to %s'), $this->group->nickname));
}
*
* @return
*/
-
function id()
{
return 'form_notice-group-message';
*
* @return
*/
-
function formClass()
{
return 'form_notice';
*
* @return
*/
-
function formData()
{
$this->out->element('label', array('for' => 'notice_data-text',
'id' => 'notice_data-text-label'),
+ // TRANS: Field label for private group message to group %s.
sprintf(_m('Direct message to %s'), $this->group->nickname));
$this->out->element('textarea', array('id' => 'notice_data-text',
if ($contentLimit > 0) {
$this->out->elementStart('dl', 'form_note');
+ // TRANS: Indicator for number of chatacters still available for notice.
$this->out->element('dt', null, _m('Available characters'));
$this->out->element('dd', array('class' => 'count'),
$contentLimit);
*
* @return
*/
-
function formActions()
{
$this->out->element('input', array('id' => 'notice_action-submit',
'class' => 'submit',
'name' => 'message_send',
'type' => 'submit',
+ // TRANS: Send button text for sending private group notice.
'value' => _m('Send button for sending notice', 'Send')));
}
}
* Copyright (C) 2011, StatusNet, Inc.
*
* Widget for showing list of group messages
- *
+ *
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* Copyright (C) 2011, StatusNet, Inc.
*
* Widget for showing an individual group message
- *
+ *
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
{
$group = $this->gm->getGroup();
$sender = $this->gm->getSender();
-
+
$this->out->elementStart('li', array('class' => 'hentry notice message group-message',
'id' => 'message-' . $this->gm->id));
$this->out->elementStart('div', 'entry-title');
$this->out->elementStart('span', 'vcard author');
- $this->out->elementStart('a',
+ $this->out->elementStart('a',
array('href' => $sender->profileurl,
'class' => 'url'));
$avatar = $sender->getAvatar(AVATAR_STREAM_SIZE);
* Copyright (C) 2011, StatusNet, Inc.
*
* Action for adding a new group message
- *
+ *
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
-
class NewgroupmessageAction extends Action
{
var $group;
*
* @return boolean true
*/
-
function prepare($argarray)
{
parent::prepare($argarray);
$this->user = common_current_user();
if (empty($this->user)) {
+ // TRANS: Client exception thrown when trying to send a private group message while not logged in.
throw new ClientException(_m('Must be logged in.'), 403);
}
if (!$this->user->hasRight(Right::NEWMESSAGE)) {
+ // TRANS: Exception thrown when user %s is not allowed to send a private group message.
throw new Exception(sprintf(_m('User %s is not allowed to send private messages.'),
$this->user->nickname));
}
$localGroup = Local_group::staticGet('nickname', $nickname);
if (empty($localGroup)) {
+ // TRANS: Client exception thrown when trying to send a private group message to a non-existing group.
throw new ClientException(_m('No such group.'), 404);
}
$this->group = User_group::staticGet('id', $localGroup->group_id);
if (empty($this->group)) {
+ // TRANS: Client exception thrown when trying to send a private group message to a non-existing group.
throw new ClientException(_m('No such group.'), 404);
}
// This throws an exception on error
-
Group_privacy_settings::ensurePost($this->user, $this->group);
// If we're posted to, check session token and get text
-
if ($this->isPost()) {
$this->checkSessionToken();
$this->text = $this->trimmed('content');
*
* @return void
*/
-
function handle($argarray=null)
{
if ($this->isPost()) {
if ($this->boolean('ajax')) {
$this->startHTML('text/xml;charset=utf-8');
$this->elementStart('head');
+ // TRANS: Title after sending a private group message.
$this->element('title', null, _m('Message sent'));
$this->elementEnd('head');
$this->elementStart('body');
$this->element('p',
array('id' => 'command_result'),
+ // TRANS: Succes text after sending a direct message to group %s.
sprintf(_m('Direct message to %s sent.'),
$this->group->nickname));
$this->elementEnd('body');
function title()
{
+ // TRANS: Title of form for new private group message.
return sprintf(_m('New message to group %s'), $this->group->nickname);
}
}
* Copyright (C) 2011, StatusNet, Inc.
*
* Show a single group message
- *
+ *
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
-
class ShowgroupmessageAction extends Action
{
var $gm;
*
* @return boolean true
*/
-
function prepare($argarray)
{
parent::prepare($argarray);
$this->user = common_current_user();
if (empty($this->user)) {
+ // TRANS: Client exception thrown when trying to view group private messages without being logged in.
throw new ClientException(_m('Only logged-in users can view private messages.'),
403);
}
$this->gm = Group_message::staticGet('id', $id);
if (empty($this->gm)) {
+ // TRANS: Client exception thrown when trying to view a non-existing group private message.
throw new ClientException(_m('No such message.'), 404);
}
$this->group = User_group::staticGet('id', $this->gm->to_group);
if (empty($this->group)) {
+ // TRANS: Server exception thrown when trying to view group private messages for a non-exsting group.
throw new ServerException(_m('Group not found.'));
}
if (!$this->user->isMember($this->group)) {
+ // TRANS: Client exception thrown when trying to view a group private message without being a group member.
throw new ClientException(_m('Cannot read message.'), 403);
}
$this->sender = Profile::staticGet('id', $this->gm->from_profile);
if (empty($this->sender)) {
+ // TRANS: Server exception thrown when trying to view a group private message without a sender.
throw new ServerException(_m('No sender found.'));
}
*
* @return void
*/
-
function handle($argarray=null)
{
$this->showPage();
/**
* Title of the page
*/
-
function title()
{
+ // TRANS: Title for private group message.
+ // TRANS: %1$s is the sender name, %2$s is the group name, %3$s is a timestamp.
return sprintf(_m('Message from %1$s to group %2$s on %3$s'),
$this->sender->nickname,
$this->group->nickname,
/**
* Show the content area.
*/
-
function showContent()
{
$this->elementStart('ul', 'notices messages');
*
* @return boolean is read only action?
*/
-
function isReadOnly($args)
{
return true;
* Check DB queries for filesorts and such and log em.
*
* @package SQLStatsPlugin
- * @maintainer Evan Prodromou <brion@status.net>
+ * @maintainer Evan Prodromou <evan@status.net>
*/
-
class SQLStatsPlugin extends Plugin
{
protected $queryCount = 0;
'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;
margin: 0px;
}
-.question fieldset legend, .qna-full-question fieldset legend {
+.question fieldset legend, .qna-full-question fieldset legend, .answer fieldset legend {
display: none;
}
margin-top: 0px;
}
-.question p.best {
+.question p.best, .answer p.best {
background: url(../images/rosette.png) no-repeat top left;
padding-left: 20px;
}
#export_data li {
list-style-type:none;
- display: inline;
- line-height: 2;
+ line-height: 2.5;
}
#export_data li a {
- padding-left: 20px;
- margin-right: 10px;
-}
-#export_data li a.foaf {
padding-left: 30px;
}