Merge branch 'testing'

Conflicts:
	plugins/Facebook/facebookaction.php
	plugins/Facebook/facebookhome.php
	plugins/Facebook/facebookutil.php
This commit is contained in:
Evan Prodromou 2011-02-08 11:52:40 -05:00
commit 8eb6646716
1550 changed files with 178132 additions and 82191 deletions

1
.gitignore vendored
View File

@ -26,3 +26,4 @@ lac08.log
php.log php.log
.DS_Store .DS_Store
nbproject nbproject
*.mo

View File

@ -118,16 +118,16 @@ EndShowHTML: Showing after the html element
- $action: the current action - $action: the current action
StartPublicGroupNav: Showing the public group nav menu StartPublicGroupNav: Showing the public group nav menu
- $action: the current action - $menu: the menu widget; use $menu->action for output
EndPublicGroupNav: At the end of the public group nav menu EndPublicGroupNav: At the end of the public group nav menu
- $action: the current action - $menu: the menu widget; use $menu->action for output
StartSubGroupNav: Showing the subscriptions group nav menu StartSubGroupNav: Showing the subscriptions group nav menu
- $action: the current action - $menu: the menu widget; use $menu->action for output
EndSubGroupNav: At the end of the subscriptions group nav menu EndSubGroupNav: At the end of the subscriptions group nav menu
- $action: the current action - $menu: the menu widget; use $menu->action for output
StartInitializeRouter: Before the router instance has been initialized; good place to add routes StartInitializeRouter: Before the router instance has been initialized; good place to add routes
- $m: the Net_URL_Mapper that has just been set up - $m: the Net_URL_Mapper that has just been set up
@ -302,6 +302,20 @@ StartProfileSaveForm: before starting to save a profile settings form
EndProfileSaveForm: after saving a profile settings form (after commit, no profile or user object!) EndProfileSaveForm: after saving a profile settings form (after commit, no profile or user object!)
- $action: action object being shown - $action: action object being shown
StartEmailFormData: just before showing text entry fields on email settings page
- $action: action object being shown
EndEmailFormData: just after showing text entry fields on email settings page
- $action: action object being shown
StartEmailSaveForm: before starting to save a email settings form
- $action: action object being shown
- &$user: user being saved
EndEmailSaveForm: after saving a email settings form (after commit)
- $action: action object being shown
- &$user: user being saved
StartRegistrationFormData: just before showing text entry fields on registration page StartRegistrationFormData: just before showing text entry fields on registration page
- $action: action object being shown - $action: action object being shown
@ -365,6 +379,14 @@ GetValidDaemons: Just before determining which daemons to run
HandleQueuedNotice: Handle a queued notice at queue time (or immediately if no queue) HandleQueuedNotice: Handle a queued notice at queue time (or immediately if no queue)
- &$notice: notice to handle - &$notice: notice to handle
StartHtmlElement: Reight before outputting the HTML element - allows plugins to add namespaces
- $action: the current action
- &$attrs: attributes for the HTML element
EndHtmlElement: Right after outputting the HTML element
- $action: the current action
- &$attrs: attributes for the HTML element
StartShowHeadElements: Right after the <head> tag StartShowHeadElements: Right after the <head> tag
- $action: the current action - $action: the current action
@ -569,6 +591,12 @@ EndPublicXRDS: End XRDS output (right before the closing XRDS tag)
- $action: the current action - $action: the current action
- &$xrdsoutputter - XRDSOutputter object to write to - &$xrdsoutputter - XRDSOutputter object to write to
StartHostMetaLinks: Start /.well-known/host-meta links
- &links: array containing the links elements to be written
EndHostMetaLinks: End /.well-known/host-meta links
- &links: array containing the links elements to be written
StartCheckPassword: Check a username/password StartCheckPassword: Check a username/password
- $nickname: The nickname to check - $nickname: The nickname to check
- $password: The password to check - $password: The password to check
@ -852,233 +880,13 @@ EndDeleteUser: handling the post for deleting a user
- $action: action being shown - $action: action being shown
- $user: user being deleted - $user: user being deleted
StartActivityStart: starting the output for a notice activity <event> StartNoticeAsActivity: before converting a notice to an activity
- &$notice: notice being output - $notice: notice being converted
- &$xs: XMLStringer for output - &$activity: initially empty activity
- &$attrs: <entry> attributes (mostly namespace declarations, if any)
EndActivityStart: end the opening tag for an activity <event> EndNoticeAsActivity: after converting a notice to an activity (good time to customize!)
- &$notice: notice being output - $notice: notice being converted
- &$xs: XMLStringer for output - &$activity: activity, now more-or-less full
- $attrs: <entry> attributes (mostly namespace declarations, if any)
StartActivitySource: before outputting the <source> element for a notice activity
- &$notice: notice being output
- &$xs: XMLStringer for output
EndActivitySource: after outputting the <source> element for a notice activity
- &$notice: notice being output
- &$xs: XMLStringer for output
StartActivityTitle: before outputting notice activity title
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$title: title of the notice, mutable
EndActivityTitle: after outputting notice activity title
- $notice: notice being output
- &$xs: XMLStringer for output
- $title: title of the notice
StartActivityAuthor: before outputting atom author
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$atomAuthor: string for XML representing atom author
EndActivityAuthor: after outputting atom author
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$atomAuthor: string for XML representing atom author
StartActivityActor: before outputting activity actor element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$actor: string for XML representing activity actor
EndActivityActor: after outputting activity actor element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$actor: string for XML representing activity actor
StartActivityLink: before outputting activity HTML link element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$url: URL for activity HTML link element for a notice activity entry
EndActivityLink: before outputting activity HTML link element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $url: URL for activity HTML link element for a notice activity entry
StartActivityId: before outputting atom:id element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$id: atom:id (notice URI by default)
EndActivityId: after outputting atom:id element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $id: atom:id (notice URI by default)
StartActivityPublished: before outputting atom:published element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$published: atom:published value (notice created by default)
EndActivityPublished: before outputting atom:published element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $published: atom:published value (notice created by default)
StartActivityUpdated: before outputting atom:updated element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$updated: atom:updated value (same as atom:published by default)
EndActivityUpdated: after outputting atom:updated element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $updated: atom:updated value (same as atom:published by default)
StartActivityContent: before outputting atom:content element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$content: atom:content value (notice rendered HTML by default)
EndActivityContent: after outputting atom:content element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $content: atom:content value (notice rendered HTML by default)
StartActivityVerb: before outputting activity:verb element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$verb: activity:verb URI ('http://activitystrea.ms/schema/1.0/post' by default)
EndActivityVerb: after outputting activity:verb element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $verb: activity:verb URI ('http://activitystrea.ms/schema/1.0/post' by default)
StartActivityDefaultObjectType: before outputting activity:object-type element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$type: activity:object-type URI for default object ('http://activitystrea.ms/schema/1.0/note' by default)
EndActivityDefaultObjectType: after outputting activity:verb element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $type: activity:object-type URI for default object ('http://activitystrea.ms/schema/1.0/note' by default)
StartActivityObjects: before outputting activity:object elements for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$objects: array of ActivityObject objects to output (empty by default)
EndActivityObjects: after outputting activity:object elements for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $objects: array of ActivityObject objects to output (empty by default)
StartActivityNoticeInfo: before outputting statusnet:notice-info element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$noticeInfoAttr: array of attributes for notice info element
EndActivityNoticeInfo: after outputting statusnet:notice-info element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $noticeInfoAttr: array of attributes for notice info element
StartActivityInReplyTo: before outputting thr:in-reply-to element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$replyNotice: Notice object the main notice is in-reply-to
EndActivityInReplyTo: after outputting thr:in-reply-to element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $replyNotice: Notice object the main notice is in-reply-to
StartActivityConversation: before outputting ostatus:conversation link element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$conv: Conversation object
EndActivityConversation: after outputting ostatus:conversation link element for a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $conv: Conversation object
StartActivityAttentionProfiles: before outputting ostatus:attention link element for people in a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$replyProfiles: array of profiles of people being replied to
EndActivityAttentionProfiles: after outputting ostatus:attention link element for people in a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $replyProfiles: array of Profile object of people being replied to
StartActivityAttentionGroups: before outputting ostatus:attention link element for groups in a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$groups: array of Group objects of groups being addressed
EndActivityAttentionGroups: after outputting ostatus:attention link element for groups in a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $groups: array of Group objects of groups being addressed
StartActivityForward: before outputting ostatus:forward link element in a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$repeat: Notice that was repeated
EndActivityForward: after outputting ostatus:forward link element in a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $repeat: Notice that was repeated
StartActivityCategories: before outputting atom:category elements in a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$tags: array of strings for tags on the notice (used for categories)
EndActivityCategories: after outputting atom:category elements in a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $tags: array of strings for tags on the notice (used for categories)
StartActivityEnclosures: before outputting enclosure link elements in a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$enclosures: array of enclosure objects (see File::getEnclosure() for details)
EndActivityEnclosures: after outputting enclosure link elements in a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $enclosures: array of enclosure objects (see File::getEnclosure() for details)
StartActivityGeo: before outputting geo:rss element in a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- &$lat: latitude
- &$lon: longitude
EndActivityGeo: after outputting geo:rss element in a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
- $lat: latitude
- $lon: longitude
StartActivityEnd: before the closing </entry> in a notice activity entry (last chance for data!)
- &$notice: notice being output
- &$xs: XMLStringer for output
EndActivityEnd: after the closing </entry> in a notice activity entry
- &$notice: notice being output
- &$xs: XMLStringer for output
StartNoticeSaveWeb: before saving a notice through the Web interface StartNoticeSaveWeb: before saving a notice through the Web interface
- $action: action being executed (instance of NewNoticeAction) - $action: action being executed (instance of NewNoticeAction)
@ -1158,3 +966,134 @@ StartRevokeRole: when a role is being revoked
EndRevokeRole: when a role has been revoked EndRevokeRole: when a role has been revoked
- $profile: profile that lost the role - $profile: profile that lost the role
- $role: string name of the role - $role: string name of the role
StartAtomPubNewActivity: When a new activity comes in through Atom Pub API
- &$activity: received activity
- $user: user publishing the entry
- &$notice: notice created; initially null, can be set
EndAtomPubNewActivity: When a new activity comes in through Atom Pub API
- $activity: received activity
- $user: user publishing the entry
- $notice: notice that was created
StartXrdActionAliases: About to set aliases for the XRD object for a user
- &$xrd: XRD object being shown
- $user: User being shown
EndXrdActionAliases: Done with aliases for the XRD object for a user
- &$xrd: XRD object being shown
- $user: User being shown
StartXrdActionLinks: About to set links for the XRD object for a user
- &$xrd: XRD object being shown
- $user: User being shown
EndXrdActionLinks: Done with links for the XRD object for a user
- &$xrd: XRD object being shown
- $user: User being shown
AdminPanelCheck: When checking whether the current user can access a given admin panel
- $name: Name of the admin panel
- &$isOK: Boolean whether the user is allowed to use the panel
StartAdminPanelNav: Before displaying the first item in the list of admin panels
- $nav The AdminPanelNav widget
EndAdminPanelNav: After displaying the last item in the list of admin panels
- $nav The AdminPanelNav widget
StartActivityObjectFromNotice: When converting a notice to an activity:object
- $notice: The notice being converted
- &$object: The resulting object. Fill this and return false to override defaults.
EndActivityObjectFromNotice: After converting a notice to an activity:object
- $notice: The notice being converted
- &$object: The resulting object. Can be edited
StartActivityObjectFromProfile: When converting a profile to an activity:object
- $profile: The profile being converted
- &$object: The (empty) object. Fill it up and return false to override defaults.
EndActivityObjectFromProfile: After converting a profile to an activity:object
- $profile: The profile being converted
- &$object: The finished object. Can be tweaked
StartActivityObjectFromGroup: When converting a group to an activity:object
- $group: The group being converted
- &$object: The (empty) object. Fill and return false to override.
EndActivityObjectFromGroup: After converting a group to an activity:object
- $group: The group being converted
- &$object: The finished object. Tweak as needed.
StartImportActivity: when we start to import an activity
- $user: User to make the author import
- $author: Author of the feed; good for comparisons
- $activity: The current activity
- $trusted: How "trusted" the process is
- &$done: Return value; whether to continue
EndImportActivity: when we finish importing an activity
- $user: User to make the author import
- $author: Author of the feed; good for comparisons
- $activity: The current activity
- $trusted: How "trusted" the process is
StartProfileSettingsActions: when we're showing account-management action list
- $action: Action being shown (use for output)
EndProfileSettingsActions: when we're showing account-management action list
- $action: Action being shown (use for output)
StartOpenNoticeListItemElement: Before the opening <li> of a notice list element
- $nli: The notice list item being shown
EndOpenNoticeListItemElement: After the opening <li> of a notice list element
- $nli: The notice list item being shown
StartCloseNoticeListItemElement: Before the closing </li> of a notice list element
- $nli: The notice list item being shown
EndCloseNoticeListItemElement: After the closing </li> of a notice list element
- $nli: The notice list item being shown
StartGroupEditFormData: Beginning the group edit form entries
- $form: The form widget being shown
EndGroupEditFormData: Ending the group edit form entries
- $form: The form widget being shown
StartGroupSave: After initializing but before saving a group
- &$group: group about to be saved
EndGroupSave: After saving a group, aliases, and first member
- $group: group that was saved
StartInterpretCommand: Before running a command
- $cmd: First word in the string, 'foo' in 'foo argument'
- $arg: Argument, if any, like 'argument' in 'foo argument'
- $user: User who issued the command
- &$result: Resulting command; you can set this!
EndInterpretCommand: Before running a command
- $cmd: First word in the string, 'foo' in 'foo argument'
- $arg: Argument, if any, like 'argument' in 'foo argument'
- $user: User who issued the command
- $result: Resulting command
StartGroupActionsList: Start the list of actions on a group profile page (after <ul>, before first <li>)
- $action: action being executed (for output and params)
- $group: group for the page
EndGroupActionsList: End the list of actions on a group profile page (before </ul>, after last </li>)
- $action: action being executed (for output and params)
- $group: group for the page
StartGroupProfileElements: Start showing stuff about the group on its profile page
- $action: action being executed (for output and params)
- $group: group for the page
EndGroupProfileElements: Start showing stuff about the group on its profile page
- $action: action being executed (for output and params)
- $group: group for the page

28
README
View File

@ -220,14 +220,12 @@ and the URLs are listed here for your convenience.
version may render your StatusNet site unable to send or receive XMPP version may render your StatusNet site unable to send or receive XMPP
messages. messages.
- Facebook library. Used for the Facebook application. - Facebook library. Used for the Facebook application.
- PEAR Services_oEmbed. Used for some multimedia integration. - PEAR Validate is used for URL and email validation.
- PEAR HTTP_Request is an oEmbed dependency.
- PEAR Validate is an oEmbed dependency.
- PEAR Net_URL2 is an oEmbed dependency.
- Console_GetOpt for parsing command-line options. - Console_GetOpt for parsing command-line options.
- libomb. a library for implementing OpenMicroBlogging 0.1, the - libomb. a library for implementing OpenMicroBlogging 0.1, the
predecessor to OStatus. predecessor to OStatus.
- HTTP_Request2, a library for making HTTP requests. - HTTP_Request2, a library for making HTTP requests.
- PEAR Net_URL2 is an HTTP_Request2 dependency.
A design goal of StatusNet is that the basic Web functionality should A design goal of StatusNet is that the basic Web functionality should
work on even the most restrictive commercial hosting services. work on even the most restrictive commercial hosting services.
@ -1278,6 +1276,12 @@ Profile management.
biolimit: max character length of bio; 0 means no limit; null means to use biolimit: max character length of bio; 0 means no limit; null means to use
the site text limit default. the site text limit default.
backup: whether users can backup their own profiles. Defaults to true.
restore: whether users can restore their profiles from backup files. Defaults
to true.
delete: whether users can delete their own accounts. Defaults to true.
move: whether users can move their accounts to another server. Defaults
to true.
newuser newuser
------- -------
@ -1552,6 +1556,22 @@ cache: whether to cache the router in memcache (or another caching
router cached) or others who see strange behavior. You're unlikely router cached) or others who see strange behavior. You're unlikely
to need this unless you're a developer. to need this unless you're a developer.
http
----
Settings for the HTTP client.
ssl_cafile: location of the CA file for SSL. If not set, won't verify
SSL peers. Default unset.
curl: Use cURL <http://curl.haxx.se/> for doing HTTP calls. You must
have the PHP curl extension installed for this to work.
proxy_host: Host to use for proxying HTTP requests. If unset, doesn't
do any HTTP proxy stuff. Default unset.
proxy_port: Port to use to connect to HTTP proxy host. Default null.
proxy_user: Username to use for authenticating to the HTTP proxy. Default null.
proxy_password: Password to use for authenticating to the HTTP proxy. Default null.
proxy_auth_scheme: Scheme to use for authenticating to the HTTP proxy. Default null.
Plugins Plugins
======= =======

View File

@ -143,7 +143,7 @@ class ApiAccountUpdateDeliveryDeviceAction extends ApiAuthAction
if ($this->format == 'xml') { if ($this->format == 'xml') {
$this->initDocument('xml'); $this->initDocument('xml');
$this->showTwitterXmlUser($twitter_user); $this->showTwitterXmlUser($twitter_user, 'user', true);
$this->endDocument('xml'); $this->endDocument('xml');
} elseif ($this->format == 'json') { } elseif ($this->format == 'json') {
$this->initDocument('json'); $this->initDocument('json');

View File

@ -154,7 +154,7 @@ class ApiAccountUpdateProfileAction extends ApiAuthAction
if ($this->format == 'xml') { if ($this->format == 'xml') {
$this->initDocument('xml'); $this->initDocument('xml');
$this->showTwitterXmlUser($twitter_user); $this->showTwitterXmlUser($twitter_user, 'user', true);
$this->endDocument('xml'); $this->endDocument('xml');
} elseif ($this->format == 'json') { } elseif ($this->format == 'json') {
$this->initDocument('json'); $this->initDocument('json');

View File

@ -204,7 +204,7 @@ class ApiAccountUpdateProfileBackgroundImageAction extends ApiAuthAction
if ($this->format == 'xml') { if ($this->format == 'xml') {
$this->initDocument('xml'); $this->initDocument('xml');
$this->showTwitterXmlUser($twitter_user); $this->showTwitterXmlUser($twitter_user, 'user', true);
$this->endDocument('xml'); $this->endDocument('xml');
} elseif ($this->format == 'json') { } elseif ($this->format == 'json') {
$this->initDocument('json'); $this->initDocument('json');

View File

@ -188,7 +188,7 @@ class ApiAccountUpdateProfileColorsAction extends ApiAuthAction
if ($this->format == 'xml') { if ($this->format == 'xml') {
$this->initDocument('xml'); $this->initDocument('xml');
$this->showTwitterXmlUser($twitter_user); $this->showTwitterXmlUser($twitter_user, 'user', true);
$this->endDocument('xml'); $this->endDocument('xml');
} elseif ($this->format == 'json') { } elseif ($this->format == 'json') {
$this->initDocument('json'); $this->initDocument('json');

View File

@ -112,16 +112,17 @@ class ApiAccountUpdateProfileImageAction extends ApiAuthAction
return; return;
} }
$type = $imagefile->preferredType();
$filename = Avatar::filename( $filename = Avatar::filename(
$user->id, $user->id,
image_type_to_extension($imagefile->type), image_type_to_extension($type),
null, null,
'tmp'.common_timestamp() 'tmp'.common_timestamp()
); );
$filepath = Avatar::path($filename); $filepath = Avatar::path($filename);
move_uploaded_file($imagefile->filepath, $filepath); $imagefile->copyTo($filepath);
$profile = $this->user->getProfile(); $profile = $this->user->getProfile();
@ -139,7 +140,7 @@ class ApiAccountUpdateProfileImageAction extends ApiAuthAction
if ($this->format == 'xml') { if ($this->format == 'xml') {
$this->initDocument('xml'); $this->initDocument('xml');
$this->showTwitterXmlUser($twitter_user); $this->showTwitterXmlUser($twitter_user, 'user', true);
$this->endDocument('xml'); $this->endDocument('xml');
} elseif ($this->format == 'json') { } elseif ($this->format == 'json') {
$this->initDocument('json'); $this->initDocument('json');

135
actions/apiatomservice.php Normal file
View File

@ -0,0 +1,135 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* An AtomPub service document for a user
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category API
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
* @link http://status.net/
*/
require_once INSTALLDIR.'/lib/apibareauth.php';
/**
* Shows an AtomPub service document for a user
*
* @category API
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
* @link http://status.net/
*/
class ApiAtomServiceAction extends ApiBareAuthAction
{
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*
*/
function prepare($args)
{
parent::prepare($args);
$this->user = $this->getTargetUser($this->arg('id'));
if (empty($this->user)) {
// TRANS: Client error displayed when making an Atom API request for an unknown user.
$this->clientError(_('No such user.'), 404, $this->format);
return;
}
return true;
}
/**
* Handle the arguments. In our case, show a service document.
*
* @param Array $args unused.
*
* @return void
*/
function handle($args)
{
parent::handle($args);
header('Content-Type: application/atomsvc+xml');
$this->startXML();
$this->elementStart('service', array('xmlns' => 'http://www.w3.org/2007/app',
'xmlns:atom' => 'http://www.w3.org/2005/Atom',
'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/'));
$this->elementStart('workspace');
// TRANS: Title for Atom feed.
$this->element('atom:title', null, _m('ATOM','Main'));
$this->elementStart('collection',
array('href' => common_local_url('ApiTimelineUser',
array('id' => $this->user->id,
'format' => 'atom'))));
$this->element('atom:title',
null,
// TRANS: Title for Atom feed. %s is a user nickname.
sprintf(_("%s timeline"),
$this->user->nickname));
$this->element('accept', null, 'application/atom+xml;type=entry');
$this->element('activity:verb', null, ActivityVerb::POST);
$this->elementEnd('collection');
$this->elementStart('collection',
array('href' => common_local_url('AtomPubSubscriptionFeed',
array('subscriber' => $this->user->id))));
$this->element('atom:title',
null,
// TRANS: Title for Atom feed with a user's subscriptions. %s is a user nickname.
sprintf(_("%s subscriptions"),
$this->user->nickname));
$this->element('accept', null, 'application/atom+xml;type=entry');
$this->element('activity:verb', null, ActivityVerb::FOLLOW);
$this->elementEnd('collection');
$this->elementStart('collection',
array('href' => common_local_url('AtomPubFavoriteFeed',
array('profile' => $this->user->id))));
$this->element('atom:title',
null,
// TRANS: Title for Atom feed with a user's favorite notices. %s is a user nickname.
sprintf(_("%s favorites"),
$this->user->nickname));
$this->element('accept', null, 'application/atom+xml;type=entry');
$this->element('activity:verb', null, ActivityVerb::FAVORITE);
$this->elementEnd('collection');
$this->elementStart('collection',
array('href' => common_local_url('AtomPubMembershipFeed',
array('profile' => $this->user->id))));
$this->element('atom:title',
null,
// TRANS: Title for Atom feed with a user's memberships. %s is a user nickname.
sprintf(_("%s memberships"),
$this->user->nickname));
$this->element('accept', null, 'application/atom+xml;type=entry');
$this->element('activity:verb', null, ActivityVerb::JOIN);
$this->elementEnd('collection');
$this->elementEnd('workspace');
$this->elementEnd('service');
$this->endXML();
}
}

View File

@ -92,6 +92,7 @@ class ApiBlockCreateAction extends ApiAuthAction
} }
if (empty($this->user) || empty($this->other)) { if (empty($this->user) || empty($this->other)) {
// TRANS: Client error displayed when trying to block a non-existing user or a user from another site.
$this->clientError(_('No such user.'), 404, $this->format); $this->clientError(_('No such user.'), 404, $this->format);
return; return;
} }

View File

@ -119,7 +119,7 @@ class ApiDirectMessageNewAction extends ApiAuthAction
$this->format $this->format
); );
} else { } else {
$content_shortened = common_shorten_links($this->content); $content_shortened = $this->auth_user->shortenLinks($this->content);
if (Message::contentTooLong($content_shortened)) { if (Message::contentTooLong($content_shortened)) {
$this->clientError( $this->clientError(
// TRANS: Client error displayed when message content is too long. // TRANS: Client error displayed when message content is too long.

View File

@ -85,7 +85,7 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction
if (empty($this->profile_a) || empty($this->profile_b)) { if (empty($this->profile_a) || empty($this->profile_b)) {
$this->clientError( $this->clientError(
// TRANS: Client error displayed when supplying invalid parameters to an API call checking if a friendship exists. // TRANS: Client error displayed when supplying invalid parameters to an API call checking if a friendship exists.
_('Two valid IDs or screen_names must be supplied.'), _('Two valid IDs or nick names must be supplied.'),
400, 400,
$this->format $this->format
); );

View File

@ -73,7 +73,7 @@ class ApiGroupCreateAction extends ApiAuthAction
$this->user = $this->auth_user; $this->user = $this->auth_user;
$this->nickname = $this->arg('nickname'); $this->nickname = Nickname::normalize($this->arg('nickname'));
$this->fullname = $this->arg('full_name'); $this->fullname = $this->arg('full_name');
$this->homepage = $this->arg('homepage'); $this->homepage = $this->arg('homepage');
$this->description = $this->arg('description'); $this->description = $this->arg('description');
@ -150,26 +150,7 @@ class ApiGroupCreateAction extends ApiAuthAction
*/ */
function validateParams() function validateParams()
{ {
$valid = Validate::string( if ($this->groupNicknameExists($this->nickname)) {
$this->nickname, array(
'min_length' => 1,
'max_length' => 64,
'format' => NICKNAME_FMT
)
);
if (!$valid) {
$this->clientError(
// TRANS: Validation error in form for group creation.
_(
'Nickname must have only lowercase letters ' .
'and numbers and no spaces.'
),
403,
$this->format
);
return false;
} elseif ($this->groupNicknameExists($this->nickname)) {
$this->clientError( $this->clientError(
// TRANS: Client error trying to create a group with a nickname this is already in use. // TRANS: Client error trying to create a group with a nickname this is already in use.
_('Nickname already in use. Try another one.'), _('Nickname already in use. Try another one.'),
@ -265,15 +246,7 @@ class ApiGroupCreateAction extends ApiAuthAction
foreach ($this->aliases as $alias) { foreach ($this->aliases as $alias) {
$valid = Validate::string( if (!Nickname::isValid($alias)) {
$alias, array(
'min_length' => 1,
'max_length' => 64,
'format' => NICKNAME_FMT
)
);
if (!$valid) {
$this->clientError( $this->clientError(
// TRANS: Client error shown when providing an invalid alias during group creation. // TRANS: Client error shown when providing an invalid alias during group creation.
// TRANS: %s is the invalid alias. // TRANS: %s is the invalid alias.

View File

@ -66,6 +66,12 @@ class ApiGroupMembershipAction extends ApiPrivateAuthAction
parent::prepare($args); parent::prepare($args);
$this->group = $this->getTargetGroup($this->arg('id')); $this->group = $this->getTargetGroup($this->arg('id'));
if (empty($this->group)) {
// TRANS: Client error displayed trying to show group membership on a non-existing group.
$this->clientError(_('Group not found.'), 404, $this->format);
return false;
}
$this->profiles = $this->getProfiles(); $this->profiles = $this->getProfiles();
return true; return true;
@ -84,12 +90,6 @@ class ApiGroupMembershipAction extends ApiPrivateAuthAction
{ {
parent::handle($args); parent::handle($args);
if (empty($this->group)) {
// TRANS: Client error displayed trying to show group membership on a non-existing group.
$this->clientError(_('Group not found.'), 404, $this->format);
return false;
}
// XXX: RSS and Atom // XXX: RSS and Atom
switch($this->format) { switch($this->format) {

View File

@ -421,7 +421,7 @@ class ApiOauthAuthorizeAction extends Action
if ($this->app->name == 'anonymous') { if ($this->app->name == 'anonymous') {
// Special message for the anonymous app and consumer. // Special message for the anonymous app and consumer.
// TRANS: User notification of external application requesting account access. // TRANS: User notification of external application requesting account access.
// TRANS: %3$s is the access type requested, %4$s is the StatusNet sitename. // TRANS: %3$s is the access type requested (read-write or read-only), %4$s is the StatusNet sitename.
$msg = _('An application would like the ability ' . $msg = _('An application would like the ability ' .
'to <strong>%3$s</strong> your %4$s account data. ' . 'to <strong>%3$s</strong> your %4$s account data. ' .
'You should only give access to your %4$s account ' . 'You should only give access to your %4$s account ' .

View File

@ -100,13 +100,24 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
{ {
parent::handle($args); parent::handle($args);
if (!in_array($this->format, array('xml', 'json'))) { if (!in_array($this->format, array('xml', 'json', 'atom'))) {
// TRANS: Client error displayed when trying to handle an unknown API method. // TRANS: Client error displayed when trying to handle an unknown API method.
$this->clientError(_('API method not found.'), $code = 404); $this->clientError(_('API method not found.'), 404);
return; return;
} }
$this->showNotice(); switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
$this->showNotice();
break;
case 'DELETE':
$this->deleteNotice();
break;
default:
// TRANS: Client error displayed calling an unsupported HTTP error in API status show.
$this->clientError(_('HTTP method not supported.'), 405);
return;
}
} }
/** /**
@ -117,10 +128,20 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
function showNotice() function showNotice()
{ {
if (!empty($this->notice)) { if (!empty($this->notice)) {
if ($this->format == 'xml') { switch ($this->format) {
case 'xml':
$this->showSingleXmlStatus($this->notice); $this->showSingleXmlStatus($this->notice);
} elseif ($this->format == 'json') { break;
case 'json':
$this->show_single_json_status($this->notice); $this->show_single_json_status($this->notice);
break;
case 'atom':
$this->showSingleAtomStatus($this->notice);
break;
default:
// TRANS: Exception thrown requesting an unsupported notice output format.
// TRANS: %s is the requested output format.
throw new Exception(sprintf(_("Unsupported format: %s"), $this->format));
} }
} else { } else {
// XXX: Twitter just sets a 404 header and doens't bother // XXX: Twitter just sets a 404 header and doens't bother
@ -147,15 +168,16 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
} }
/** /**
* Is this action read only? * We expose AtomPub here, so non-GET/HEAD reqs must be read/write.
* *
* @param array $args other arguments * @param array $args other arguments
* *
* @return boolean true * @return boolean true
*/ */
function isReadOnly($args) function isReadOnly($args)
{ {
return true; return ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD');
} }
/** /**
@ -197,4 +219,34 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
return null; return null;
} }
function deleteNotice()
{
if ($this->format != 'atom') {
// TRANS: Client error displayed when trying to delete a notice not using the Atom format.
$this->clientError(_("Can only delete using the Atom format."));
return;
}
if (empty($this->auth_user) ||
($this->notice->profile_id != $this->auth_user->id &&
!$this->auth_user->hasRight(Right::DELETEOTHERSNOTICE))) {
// TRANS: Client error displayed when a user has no rights to delete notices of other users.
$this->clientError(_('Cannot delete this notice.'), 403);
return;
}
if (Event::handle('StartDeleteOwnNotice', array($this->auth_user, $this->notice))) {
$this->notice->delete();
Event::handle('EndDeleteOwnNotice', array($this->auth_user, $this->notice));
}
// @fixme is there better output we could do here?
header('HTTP/1.1 200 OK');
header('Content-Type: text/plain');
// TRANS: Confirmation of notice deletion in API. %d is the ID (number) of the deleted notice.
print(sprintf(_('Deleted notice %d'), $this->notice->id));
print("\n");
}
} }

View File

@ -55,7 +55,7 @@
Yes Yes
@param status (Required) The URL-encoded text of the status update. @param status (Required) The URL-encoded text of the status update.
@param source (Optional) The source of the status. @param source (Optional) The source application name, if using HTTP authentication or an anonymous OAuth consumer.
@param in_reply_to_status_id (Optional) The ID of an existing status that the update is in reply to. @param in_reply_to_status_id (Optional) The ID of an existing status that the update is in reply to.
@param lat (Optional) The latitude the status refers to. @param lat (Optional) The latitude the status refers to.
@param long (Optional) The longitude the status refers to. @param long (Optional) The longitude the status refers to.
@ -67,7 +67,7 @@
@subsection usagenotes Usage notes @subsection usagenotes Usage notes
@li The URL pattern is relative to the @ref apiroot. @li The URL pattern is relative to the @ref apiroot.
@li If the @e source parameter is not supplied the source of the status will default to 'api'. @li If the @e source parameter is not supplied the source of the status will default to 'api'. When authenticated via a registered OAuth application, the application's registered name and URL will always override the source parameter.
@li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a> @li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a>
to encode the latitude and longitude (see example response below <georss:point>). to encode the latitude and longitude (see example response below <georss:point>).
@li Data uploaded via the @e media parameter should be multipart/form-data encoded. @li Data uploaded via the @e media parameter should be multipart/form-data encoded.
@ -231,7 +231,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction
return; return;
} }
$status_shortened = common_shorten_links($this->status); $status_shortened = $this->auth_user->shortenlinks($this->status);
if (Notice::contentTooLong($status_shortened)) { if (Notice::contentTooLong($status_shortened)) {
// Note: Twitter truncates anything over 140, flags the status // Note: Twitter truncates anything over 140, flags the status
@ -377,7 +377,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction
function supported($cmd) function supported($cmd)
{ {
static $cmdlist = array('MessageCommand', 'SubCommand', 'UnsubCommand', static $cmdlist = array('MessageCommand', 'SubCommand', 'UnsubCommand',
'FavCommand', 'OnCommand', 'OffCommand'); 'FavCommand', 'OnCommand', 'OffCommand', 'JoinCommand', 'LeaveCommand');
if (in_array(get_class($cmd), $cmdlist)) { if (in_array(get_class($cmd), $cmdlist)) {
return true; return true;

View File

@ -125,10 +125,6 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction
header('Content-Type: application/atom+xml; charset=utf-8'); header('Content-Type: application/atom+xml; charset=utf-8');
try { try {
$atom->addAuthorRaw($this->group->asAtomAuthor());
$atom->setActivitySubject($this->group->asActivitySubject());
$atom->setId($self);
$atom->setSelfLink($self);
$atom->addEntryFromNotices($this->notices); $atom->addEntryFromNotices($this->notices);
$this->raw($atom->getString()); $this->raw($atom->getString());
} catch (Atom10FeedException $e) { } catch (Atom10FeedException $e) {

View File

@ -97,7 +97,12 @@ class ApiTimelineUserAction extends ApiBareAuthAction
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
$this->showTimeline();
if ($this->isPost()) {
$this->handlePost();
} else {
$this->showTimeline();
}
} }
/** /**
@ -114,9 +119,9 @@ class ApiTimelineUserAction extends ApiBareAuthAction
$atom = new AtomUserNoticeFeed($this->user, $this->auth_user); $atom = new AtomUserNoticeFeed($this->user, $this->auth_user);
$link = common_local_url( $link = common_local_url(
'showstream', 'showstream',
array('nickname' => $this->user->nickname) array('nickname' => $this->user->nickname)
); );
$self = $this->getSelfUri(); $self = $this->getSelfUri();
@ -132,20 +137,63 @@ class ApiTimelineUserAction extends ApiBareAuthAction
break; break;
case 'rss': case 'rss':
$this->showRssTimeline( $this->showRssTimeline(
$this->notices, $this->notices,
$atom->title, $atom->title,
$link, $link,
$atom->subtitle, $atom->subtitle,
$suplink, $suplink,
$atom->logo, $atom->logo,
$self $self
); );
break; break;
case 'atom': case 'atom':
header('Content-Type: application/atom+xml; charset=utf-8'); header('Content-Type: application/atom+xml; charset=utf-8');
$atom->setId($self); $atom->setId($self);
$atom->setSelfLink($self); $atom->setSelfLink($self);
// Add navigation links: next, prev, first
// Note: we use IDs rather than pages for navigation; page boundaries
// change too quickly!
if (!empty($this->next_id)) {
$nextUrl = common_local_url('ApiTimelineUser',
array('format' => 'atom',
'id' => $this->user->id),
array('max_id' => $this->next_id));
$atom->addLink($nextUrl,
array('rel' => 'next',
'type' => 'application/atom+xml'));
}
if (($this->page > 1 || !empty($this->max_id)) && !empty($this->notices)) {
$lastNotice = $this->notices[0];
$lastId = $lastNotice->id;
$prevUrl = common_local_url('ApiTimelineUser',
array('format' => 'atom',
'id' => $this->user->id),
array('since_id' => $lastId));
$atom->addLink($prevUrl,
array('rel' => 'prev',
'type' => 'application/atom+xml'));
}
if ($this->page > 1 || !empty($this->since_id) || !empty($this->max_id)) {
$firstUrl = common_local_url('ApiTimelineUser',
array('format' => 'atom',
'id' => $this->user->id));
$atom->addLink($firstUrl,
array('rel' => 'first',
'type' => 'application/atom+xml'));
}
$atom->addEntryFromNotices($this->notices); $atom->addEntryFromNotices($this->notices);
$this->raw($atom->getString()); $this->raw($atom->getString());
@ -169,28 +217,34 @@ class ApiTimelineUserAction extends ApiBareAuthAction
{ {
$notices = array(); $notices = array();
$notice = $this->user->getNotices( $notice = $this->user->getNotices(($this->page-1) * $this->count,
($this->page-1) * $this->count, $this->count, $this->count + 1,
$this->since_id, $this->max_id $this->since_id,
); $this->max_id);
while ($notice->fetch()) { while ($notice->fetch()) {
$notices[] = clone($notice); if (count($notices) < $this->count) {
$notices[] = clone($notice);
} else {
$this->next_id = $notice->id;
break;
}
} }
return $notices; return $notices;
} }
/** /**
* Is this action read only? * We expose AtomPub here, so non-GET/HEAD reqs must be read/write.
* *
* @param array $args other arguments * @param array $args other arguments
* *
* @return boolean true * @return boolean true
*/ */
function isReadOnly($args) function isReadOnly($args)
{ {
return true; return ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD');
} }
/** /**
@ -221,17 +275,226 @@ class ApiTimelineUserAction extends ApiBareAuthAction
$last = count($this->notices) - 1; $last = count($this->notices) - 1;
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user), common_user_cache_hash($this->auth_user),
common_language(), common_language(),
$this->user->id, $this->user->id,
strtotime($this->notices[0]->created), strtotime($this->notices[0]->created),
strtotime($this->notices[$last]->created)) strtotime($this->notices[$last]->created))
) )
. '"'; . '"';
} }
return null; return null;
} }
function handlePost()
{
if (empty($this->auth_user) ||
$this->auth_user->id != $this->user->id) {
// TRANS: Client error displayed trying to add a notice to another user's timeline.
$this->clientError(_('Only the user can add to their own timeline.'));
return;
}
// Only handle posts for Atom
if ($this->format != 'atom') {
// TRANS: Client error displayed when using another format than AtomPub.
$this->clientError(_('Only accept AtomPub for Atom feeds.'));
return;
}
$xml = trim(file_get_contents('php://input'));
if (empty($xml)) {
// TRANS: Client error displayed attempting to post an empty API notice.
$this->clientError(_('Atom post must not be empty.'));
}
$dom = DOMDocument::loadXML($xml);
if (!$dom) {
// TRANS: Client error displayed attempting to post an API that is not well-formed XML.
$this->clientError(_('Atom post must be well-formed XML.'));
}
if ($dom->documentElement->namespaceURI != Activity::ATOM ||
$dom->documentElement->localName != 'entry') {
// TRANS: Client error displayed when not using an Atom entry.
$this->clientError(_('Atom post must be an Atom entry.'));
return;
}
$activity = new Activity($dom->documentElement);
$saved = null;
if (Event::handle('StartAtomPubNewActivity', array(&$activity, $this->user, &$saved))) {
if ($activity->verb != ActivityVerb::POST) {
// TRANS: Client error displayed when not using the POST verb. Do not translate POST.
$this->clientError(_('Can only handle POST activities.'));
return;
}
$note = $activity->objects[0];
if (!in_array($note->type, array(ActivityObject::NOTE,
ActivityObject::BLOGENTRY,
ActivityObject::STATUS))) {
// TRANS: Client error displayed when using an unsupported activity object type.
// TRANS: %s is the unsupported activity object type.
$this->clientError(sprintf(_('Cannot handle activity object type "%s".'),
$note->type));
return;
}
$saved = $this->postNote($activity);
Event::handle('EndAtomPubNewActivity', array($activity, $this->user, $saved));
}
if (!empty($saved)) {
header('HTTP/1.1 201 Created');
header("Location: " . common_local_url('ApiStatusesShow', array('id' => $saved->id,
'format' => 'atom')));
$this->showSingleAtomStatus($saved);
}
}
function postNote($activity)
{
$note = $activity->objects[0];
// Use summary as fallback for content
if (!empty($note->content)) {
$sourceContent = $note->content;
} else if (!empty($note->summary)) {
$sourceContent = $note->summary;
} else if (!empty($note->title)) {
$sourceContent = $note->title;
} else {
// @fixme fetch from $sourceUrl?
// TRANS: Client error displayed when posting a notice without content through the API.
// TRANS: %d is the notice ID (number).
$this->clientError(sprintf(_('No content for notice %d.'),
$note->id));
return;
}
// Get (safe!) HTML and text versions of the content
$rendered = $this->purify($sourceContent);
$content = html_entity_decode(strip_tags($rendered), ENT_QUOTES, 'UTF-8');
$shortened = $this->auth_user->shortenLinks($content);
$options = array('is_local' => Notice::LOCAL_PUBLIC,
'rendered' => $rendered,
'replies' => array(),
'groups' => array(),
'tags' => array(),
'urls' => array());
// accept remote URI (not necessarily a good idea)
common_debug("Note ID is {$note->id}");
if (!empty($note->id)) {
$notice = Notice::staticGet('uri', trim($note->id));
if (!empty($notice)) {
// TRANS: Client error displayed when using another format than AtomPub.
$this->clientError(sprintf(_('Notice with URI "%s" already exists.'),
$note->id));
return;
}
common_log(LOG_NOTICE, "Saving client-supplied notice URI '$note->id'");
$options['uri'] = $note->id;
}
// accept remote create time (also maybe not such a good idea)
if (!empty($activity->time)) {
common_log(LOG_NOTICE, "Saving client-supplied create time {$activity->time}");
$options['created'] = common_sql_date($activity->time);
}
// Check for optional attributes...
if (!empty($activity->context)) {
foreach ($activity->context->attention as $uri) {
$profile = Profile::fromURI($uri);
if (!empty($profile)) {
$options['replies'][] = $uri;
} else {
$group = User_group::staticGet('uri', $uri);
if (!empty($group)) {
$options['groups'][] = $uri;
} else {
// @fixme: hook for discovery here
common_log(LOG_WARNING, sprintf('AtomPub post with unknown attention URI %s', $uri));
}
}
}
// Maintain direct reply associations
// @fixme what about conversation ID?
if (!empty($activity->context->replyToID)) {
$orig = Notice::staticGet('uri',
$activity->context->replyToID);
if (!empty($orig)) {
$options['reply_to'] = $orig->id;
}
}
$location = $activity->context->location;
if ($location) {
$options['lat'] = $location->lat;
$options['lon'] = $location->lon;
if ($location->location_id) {
$options['location_ns'] = $location->location_ns;
$options['location_id'] = $location->location_id;
}
}
}
// Atom categories <-> hashtags
foreach ($activity->categories as $cat) {
if ($cat->term) {
$term = common_canonical_tag($cat->term);
if ($term) {
$options['tags'][] = $term;
}
}
}
// Atom enclosures -> attachment URLs
foreach ($activity->enclosures as $href) {
// @fixme save these locally or....?
$options['urls'][] = $href;
}
$saved = Notice::saveNew($this->user->id,
$content,
'atompub', // TODO: deal with this
$options);
return $saved;
}
function purify($content)
{
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
$config = array('safe' => 1,
'deny_attribute' => 'id,style,on*');
return htmLawed($content, $config);
}
} }

View File

@ -0,0 +1,135 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Return a user's avatar image
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category API
* @package StatusNet
* @author Brion Vibber <brion@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
require_once INSTALLDIR . '/lib/apiprivateauth.php';
/**
* Ouputs avatar URL for a user, specified by screen name.
* Unlike most API endpoints, this returns an HTTP redirect rather than direct data.
*
* @category API
* @package StatusNet
* @author Brion Vibber <brion@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class ApiUserProfileImageAction extends ApiPrivateAuthAction
{
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*
*/
function prepare($args)
{
parent::prepare($args);
$this->user = User::staticGet('nickname', $this->arg('screen_name'));
$this->size = $this->arg('size');
return true;
}
/**
* Handle the request
*
* Check the format and show the user info
*
* @param array $args $_REQUEST data (unused)
*
* @return void
*/
function handle($args)
{
parent::handle($args);
if (empty($this->user)) {
// TRANS: Client error displayed when requesting user information for a non-existing user.
$this->clientError(_('User not found.'), 404, $this->format);
return;
}
$profile = $this->user->getProfile();
if (empty($profile)) {
// TRANS: Client error displayed when requesting user information for a user without a profile.
$this->clientError(_('User has no profile.'));
return;
}
$size = $this->avatarSize();
$avatar = $profile->getAvatar($size);
if ($avatar) {
$url = $avatar->displayUrl();
} else {
$url = Avatar::defaultImage($size);
}
// We don't actually output JSON or XML data -- redirect!
common_redirect($url, 302);
}
/**
* Get the appropriate pixel size for an avatar based on the request...
*
* @return int
*/
private function avatarSize()
{
switch ($this->size) {
case 'mini':
return AVATAR_MINI_SIZE; // 24x24
case 'bigger':
return AVATAR_PROFILE_SIZE; // Twitter does 73x73, but we do 96x96
case 'normal': // fall through
default:
return AVATAR_STREAM_SIZE; // 48x48
}
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
return true;
}
}

View File

@ -0,0 +1,374 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* Feed of ActivityStreams 'favorite' actions
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category AtomPub
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
require_once INSTALLDIR . '/lib/apiauth.php';
/**
* Feed of ActivityStreams 'favorite' actions
*
* @category AtomPub
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class AtompubfavoritefeedAction extends ApiAuthAction
{
private $_profile = null;
private $_faves = null;
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
$this->_profile = Profile::staticGet('id', $this->trimmed('profile'));
if (empty($this->_profile)) {
// TRANS: Client exception thrown when requesting a favorite feed for a non-existing profile.
throw new ClientException(_('No such profile.'), 404);
}
$offset = ($this->page-1) * $this->count;
$limit = $this->count + 1;
$this->_faves = Fave::byProfile($this->_profile->id,
$offset,
$limit);
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handle($argarray=null)
{
parent::handle($argarray);
switch ($_SERVER['REQUEST_METHOD']) {
case 'HEAD':
case 'GET':
$this->showFeed();
break;
case 'POST':
$this->addFavorite();
break;
default:
// TRANS: Client exception thrown when using an unsupported HTTP method.
throw new ClientException(_('HTTP method not supported.'), 405);
return;
}
return;
}
/**
* Show a feed of favorite activity streams objects
*
* @return void
*/
function showFeed()
{
header('Content-Type: application/atom+xml; charset=utf-8');
$url = common_local_url('AtomPubFavoriteFeed',
array('profile' => $this->_profile->id));
$feed = new Atom10Feed(true);
$feed->addNamespace('activity',
'http://activitystrea.ms/spec/1.0/');
$feed->addNamespace('poco',
'http://portablecontacts.net/spec/1.0');
$feed->addNamespace('media',
'http://purl.org/syndication/atommedia');
$feed->id = $url;
$feed->setUpdated('now');
$feed->addAuthor($this->_profile->getBestName(),
$this->_profile->getURI());
// TRANS: Title for Atom favorites feed.
// TRANS: %s is a user nickname.
$feed->setTitle(sprintf(_("%s favorites"),
$this->_profile->getBestName()));
// TRANS: Subtitle for Atom favorites feed.
// TRANS: %1$s is a user nickname, %2$s is the StatusNet sitename.
$feed->setSubtitle(sprintf(_('Notices %1$s has favorited on %2$s'),
$this->_profile->getBestName(),
common_config('site', 'name')));
$feed->addLink(common_local_url('showfavorites',
array('nickname' =>
$this->_profile->nickname)));
$feed->addLink($url,
array('rel' => 'self',
'type' => 'application/atom+xml'));
// If there's more...
if ($this->page > 1) {
$feed->addLink($url,
array('rel' => 'first',
'type' => 'application/atom+xml'));
$feed->addLink(common_local_url('AtomPubFavoriteFeed',
array('profile' =>
$this->_profile->id),
array('page' =>
$this->page - 1)),
array('rel' => 'prev',
'type' => 'application/atom+xml'));
}
if ($this->_faves->N > $this->count) {
$feed->addLink(common_local_url('AtomPubFavoriteFeed',
array('profile' =>
$this->_profile->id),
array('page' =>
$this->page + 1)),
array('rel' => 'next',
'type' => 'application/atom+xml'));
}
$i = 0;
while ($this->_faves->fetch()) {
// We get one more than needed; skip that one
$i++;
if ($i > $this->count) {
break;
}
$act = $this->_faves->asActivity();
$feed->addEntryRaw($act->asString(false, false, false));
}
$this->raw($feed->getString());
}
/**
* add a new favorite
*
* @return void
*/
function addFavorite()
{
// XXX: Refactor this; all the same for atompub
if (empty($this->auth_user) ||
$this->auth_user->id != $this->_profile->id) {
// TRANS: Client exception thrown when trying to set a favorite for another user.
throw new ClientException(_("Cannot add someone else's".
" subscription."), 403);
}
$xml = file_get_contents('php://input');
$dom = DOMDocument::loadXML($xml);
if ($dom->documentElement->namespaceURI != Activity::ATOM ||
$dom->documentElement->localName != 'entry') {
// TRANS: Client error displayed when not using an Atom entry.
throw new ClientException(_('Atom post must be an Atom entry.'));
return;
}
$activity = new Activity($dom->documentElement);
$fave = null;
if (Event::handle('StartAtomPubNewActivity', array(&$activity))) {
if ($activity->verb != ActivityVerb::FAVORITE) {
// TRANS: Client exception thrown when trying use an incorrect activity verb for the Atom pub method.
throw new ClientException(_('Can only handle favorite activities.'));
return;
}
$note = $activity->objects[0];
if (!in_array($note->type, array(ActivityObject::NOTE,
ActivityObject::BLOGENTRY,
ActivityObject::STATUS))) {
// TRANS: Client exception thrown when trying favorite an object that is not a notice.
throw new ClientException(_('Can only fave notices.'));
return;
}
$notice = Notice::staticGet('uri', $note->id);
if (empty($notice)) {
// XXX: import from listed URL or something
// TRANS: Client exception thrown when trying favorite a notice without content.
throw new ClientException(_('Unknown note.'));
}
$old = Fave::pkeyGet(array('user_id' => $this->auth_user->id,
'notice_id' => $notice->id));
if (!empty($old)) {
// TRANS: Client exception thrown when trying favorite an already favorited notice.
throw new ClientException(_('Already a favorite.'));
}
$profile = $this->auth_user->getProfile();
$fave = Fave::addNew($profile, $notice);
if (!empty($fave)) {
$this->_profile->blowFavesCache();
$this->notify($fave, $notice, $this->auth_user);
}
Event::handle('EndAtomPubNewActivity', array($activity, $fave));
}
if (!empty($fave)) {
$act = $fave->asActivity();
header('Content-Type: application/atom+xml; charset=utf-8');
header('Content-Location: ' . $act->selfLink);
$this->startXML();
$this->raw($act->asString(true, true, true));
$this->endXML();
}
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
$_SERVER['REQUEST_METHOD'] == 'HEAD') {
return true;
} else {
return false;
}
}
/**
* Return last modified, if applicable.
*
* MAY override
*
* @return string last modified http header
*/
function lastModified()
{
// For comparison with If-Last-Modified
// If not applicable, return null
return null;
}
/**
* Return etag, if applicable.
*
* MAY override
*
* @return string etag http header
*/
function etag()
{
return null;
}
/**
* Does this require authentication?
*
* @return boolean true if delete, else false
*/
function requiresAuth()
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
$_SERVER['REQUEST_METHOD'] == 'HEAD') {
return false;
} else {
return true;
}
}
/**
* Notify the author of the favorite that the user likes their notice
*
* @param Favorite $fave the favorite in question
* @param Notice $notice the notice that's been faved
* @param User $user the user doing the favoriting
*
* @return void
*/
function notify($fave, $notice, $user)
{
$other = User::staticGet('id', $notice->profile_id);
if ($other && $other->id != $user->id) {
if ($other->email && $other->emailnotifyfav) {
mail_notify_fave($other, $user, $notice);
}
// XXX: notify by IM
// XXX: notify by SMS
}
}
}

View File

@ -0,0 +1,357 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* Feed of group memberships for a user, in ActivityStreams format
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category AtomPub
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
require_once INSTALLDIR . '/lib/apiauth.php';
/**
* Feed of group memberships for a user, in ActivityStreams format
*
* @category Action
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class AtompubmembershipfeedAction extends ApiAuthAction
{
private $_profile = null;
private $_memberships = null;
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
$profileId = $this->trimmed('profile');
$this->_profile = Profile::staticGet('id', $profileId);
if (empty($this->_profile)) {
// TRANS: Client exception.
throw new ClientException(_('No such profile.'), 404);
}
$offset = ($this->page-1) * $this->count;
$limit = $this->count + 1;
$this->_memberships = Group_member::byMember($this->_profile->id,
$offset,
$limit);
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handle($argarray=null)
{
parent::handle($argarray);
switch ($_SERVER['REQUEST_METHOD']) {
case 'HEAD':
case 'GET':
$this->showFeed();
break;
case 'POST':
$this->addMembership();
break;
default:
// TRANS: Client exception thrown when using an unsupported HTTP method.
throw new ClientException(_('HTTP method not supported.'), 405);
return;
}
return;
}
/**
* Show a feed of favorite activity streams objects
*
* @return void
*/
function showFeed()
{
header('Content-Type: application/atom+xml; charset=utf-8');
$url = common_local_url('AtomPubMembershipFeed',
array('profile' => $this->_profile->id));
$feed = new Atom10Feed(true);
$feed->addNamespace('activity',
'http://activitystrea.ms/spec/1.0/');
$feed->addNamespace('poco',
'http://portablecontacts.net/spec/1.0');
$feed->addNamespace('media',
'http://purl.org/syndication/atommedia');
$feed->id = $url;
$feed->setUpdated('now');
$feed->addAuthor($this->_profile->getBestName(),
$this->_profile->getURI());
// TRANS: Title for group membership feed.
// TRANS: %s is a username.
$feed->setTitle(sprintf(_("%s group memberships"),
$this->_profile->getBestName()));
// TRANS: Subtitle for group membership feed.
// TRANS: %1$s is a username, %2$s is the StatusNet sitename.
$feed->setSubtitle(sprintf(_('Groups %1$s is a member of on %2$s'),
$this->_profile->getBestName(),
common_config('site', 'name')));
$feed->addLink(common_local_url('usergroups',
array('nickname' =>
$this->_profile->nickname)));
$feed->addLink($url,
array('rel' => 'self',
'type' => 'application/atom+xml'));
// If there's more...
if ($this->page > 1) {
$feed->addLink($url,
array('rel' => 'first',
'type' => 'application/atom+xml'));
$feed->addLink(common_local_url('AtomPubMembershipFeed',
array('profile' =>
$this->_profile->id),
array('page' =>
$this->page - 1)),
array('rel' => 'prev',
'type' => 'application/atom+xml'));
}
if ($this->_memberships->N > $this->count) {
$feed->addLink(common_local_url('AtomPubMembershipFeed',
array('profile' =>
$this->_profile->id),
array('page' =>
$this->page + 1)),
array('rel' => 'next',
'type' => 'application/atom+xml'));
}
$i = 0;
while ($this->_memberships->fetch()) {
// We get one more than needed; skip that one
$i++;
if ($i > $this->count) {
break;
}
$act = $this->_memberships->asActivity();
$feed->addEntryRaw($act->asString(false, false, false));
}
$this->raw($feed->getString());
}
/**
* add a new favorite
*
* @return void
*/
function addMembership()
{
// XXX: Refactor this; all the same for atompub
if (empty($this->auth_user) ||
$this->auth_user->id != $this->_profile->id) {
// TRANS: Client exception thrown when trying subscribe someone else to a group.
throw new ClientException(_("Cannot add someone else's".
" membership."), 403);
}
$xml = file_get_contents('php://input');
$dom = DOMDocument::loadXML($xml);
if ($dom->documentElement->namespaceURI != Activity::ATOM ||
$dom->documentElement->localName != 'entry') {
// TRANS: Client error displayed when not using an Atom entry.
throw new ClientException(_('Atom post must be an Atom entry.'));
return;
}
$activity = new Activity($dom->documentElement);
$membership = null;
if (Event::handle('StartAtomPubNewActivity', array(&$activity))) {
if ($activity->verb != ActivityVerb::JOIN) {
// TRANS: Client error displayed when not using the POST verb.
// TRANS: Do not translate POST.
throw new ClientException(_('Can only handle join activities.'));
return;
}
$groupObj = $activity->objects[0];
if ($groupObj->type != ActivityObject::GROUP) {
// TRANS: Client exception thrown when trying favorite an object that is not a notice.
throw new ClientException(_('Can only fave notices.'));
return;
}
$group = User_group::staticGet('uri', $groupObj->id);
if (empty($group)) {
// XXX: import from listed URL or something
// TRANS: Client exception thrown when trying to subscribe to a non-existing group.
throw new ClientException(_('Unknown group.'));
}
$old = Group_member::pkeyGet(array('profile_id' => $this->auth_user->id,
'group_id' => $group->id));
if (!empty($old)) {
// TRANS: Client exception thrown when trying to subscribe to an already subscribed group.
throw new ClientException(_('Already a member.'));
}
$profile = $this->auth_user->getProfile();
if (Group_block::isBlocked($group, $profile)) {
// XXX: import from listed URL or something
// TRANS: Client exception thrown when trying to subscribe to group while blocked from that group.
throw new ClientException(_('Blocked by admin.'));
}
if (Event::handle('StartJoinGroup', array($group, $this->auth_user))) {
$membership = Group_member::join($group->id, $this->auth_user->id);
Event::handle('EndJoinGroup', array($group, $this->auth_user));
}
Event::handle('EndAtomPubNewActivity', array($activity, $membership));
}
if (!empty($membership)) {
$act = $membership->asActivity();
header('Content-Type: application/atom+xml; charset=utf-8');
header('Content-Location: ' . $act->selfLink);
$this->startXML();
$this->raw($act->asString(true, true, true));
$this->endXML();
}
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
$_SERVER['REQUEST_METHOD'] == 'HEAD') {
return true;
} else {
return false;
}
}
/**
* Return last modified, if applicable.
*
* MAY override
*
* @return string last modified http header
*/
function lastModified()
{
// For comparison with If-Last-Modified
// If not applicable, return null
return null;
}
/**
* Return etag, if applicable.
*
* MAY override
*
* @return string etag http header
*/
function etag()
{
return null;
}
/**
* Does this require authentication?
*
* @return boolean true if delete, else false
*/
function requiresAuth()
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
$_SERVER['REQUEST_METHOD'] == 'HEAD') {
return false;
} else {
return true;
}
}
}

View File

@ -0,0 +1,224 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* Show a single favorite in Atom Activity Streams format
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category AtomPub
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
require_once INSTALLDIR . '/lib/apiauth.php';
/**
* Show a single favorite in Atom Activity Streams format.
*
* Can also be used to delete a favorite.
*
* @category Action
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class AtompubshowfavoriteAction extends ApiAuthAction
{
private $_profile = null;
private $_notice = null;
private $_fave = null;
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
$profileId = $this->trimmed('profile');
$noticeId = $this->trimmed('notice');
$this->_profile = Profile::staticGet('id', $profileId);
if (empty($this->_profile)) {
// TRANS: Client exception.
throw new ClientException(_('No such profile.'), 404);
}
$this->_notice = Notice::staticGet('id', $noticeId);
if (empty($this->_notice)) {
// TRANS: Client exception thrown when referencing a non-existing notice.
throw new ClientException(_('No such notice.'), 404);
}
$this->_fave = Fave::pkeyGet(array('user_id' => $profileId,
'notice_id' => $noticeId));
if (empty($this->_fave)) {
// TRANS: Client exception thrown when referencing a non-existing favorite.
throw new ClientException(_('No such favorite.'), 404);
}
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handle($argarray=null)
{
parent::handle($argarray);
switch ($_SERVER['REQUEST_METHOD']) {
case GET:
case HEAD:
$this->showFave();
break;
case DELETE:
$this->deleteFave();
break;
default:
// TRANS: Client exception thrown using an unsupported HTTP method.
throw new ClientException(_('HTTP method not supported.'),
405);
}
return true;
}
/**
* Show a single favorite, in ActivityStreams format
*
* @return void
*/
function showFave()
{
$activity = $this->_fave->asActivity();
header('Content-Type: application/atom+xml; charset=utf-8');
$this->startXML();
$this->raw($activity->asString(true, true, true));
$this->endXML();
return;
}
/**
* Delete the favorite
*
* @return void
*/
function deleteFave()
{
if (empty($this->auth_user) ||
$this->auth_user->id != $this->_profile->id) {
// TRANS: Client exception thrown when trying to remove a favorite notice of another user.
throw new ClientException(_("Cannot delete someone else's".
" favorite."), 403);
}
$this->_fave->delete();
return;
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
$_SERVER['REQUEST_METHOD'] == 'HEAD') {
return true;
} else {
return false;
}
}
/**
* Return last modified, if applicable.
*
* MAY override
*
* @return string last modified http header
*/
function lastModified()
{
return max(strtotime($this->_profile->modified),
strtotime($this->_notice->modified),
strtotime($this->_fave->modified));
}
/**
* Return etag, if applicable.
*
* MAY override
*
* @return string etag http header
*/
function etag()
{
$mtime = strtotime($this->_fave->modified);
return 'W/"' . implode(':', array('AtomPubShowFavorite',
$this->_profile->id,
$this->_notice->id,
$mtime)) . '"';
}
/**
* Does this require authentication?
*
* @return boolean true if delete, else false
*/
function requiresAuth()
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
$_SERVER['REQUEST_METHOD'] == 'HEAD') {
return false;
} else {
return true;
}
}
}

View File

@ -0,0 +1,233 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* Show a single membership as an Activity Streams entry
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category AtomPub
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
require_once INSTALLDIR . '/lib/apiauth.php';
/**
* Show (or delete) a single membership event as an ActivityStreams entry
*
* @category AtomPub
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class AtompubshowmembershipAction extends ApiAuthAction
{
private $_profile = null;
private $_group = null;
private $_membership = null;
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
$profileId = $this->trimmed('profile');
$this->_profile = Profile::staticGet('id', $profileId);
if (empty($this->_profile)) {
// TRANS: Client exception.
throw new ClientException(_('No such profile.'), 404);
}
$groupId = $this->trimmed('group');
$this->_group = User_group::staticGet('id', $groupId);
if (empty($this->_group)) {
// TRANS: Client exception thrown when referencing a non-existing group.
throw new ClientException(_('No such group.'), 404);
}
$kv = array('group_id' => $groupId,
'profile_id' => $profileId);
$this->_membership = Group_member::pkeyGet($kv);
if (empty($this->_membership)) {
// TRANS: Client exception thrown when trying to show membership of a non-subscribed group
throw new ClientException(_('Not a member.'), 404);
}
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handle($argarray=null)
{
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
case 'HEAD':
$this->showMembership();
break;
case 'DELETE':
$this->deleteMembership();
break;
default:
// TRANS: Client exception thrown when using an unsupported HTTP method.
throw new ClientException(_('HTTP method not supported.'), 405);
break;
}
return;
}
/**
* show a single membership
*
* @return void
*/
function showMembership()
{
$activity = $this->_membership->asActivity();
header('Content-Type: application/atom+xml; charset=utf-8');
$this->startXML();
$this->raw($activity->asString(true, true, true));
$this->endXML();
return;
}
/**
* Delete the membership (leave the group)
*
* @return void
*/
function deleteMembership()
{
if (empty($this->auth_user) ||
$this->auth_user->id != $this->_profile->id) {
// TRANS: Client exception thrown when deleting someone else's membership.
throw new ClientException(_("Cannot delete someone else's".
" membership."), 403);
}
if (Event::handle('StartLeaveGroup', array($this->_group, $this->auth_user))) {
Group_member::leave($this->_group->id, $this->auth_user->id);
Event::handle('EndLeaveGroup', array($this->_group, $this->auth_user));
}
return;
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
$_SERVER['REQUEST_METHOD'] == 'HEAD') {
return true;
} else {
return false;
}
}
/**
* Return last modified, if applicable.
*
* Because the representation depends on the profile and group,
* our last modified value is the maximum of their mod time
* with the actual membership's mod time.
*
* @return string last modified http header
*/
function lastModified()
{
return max(strtotime($this->_profile->modified),
strtotime($this->_group->modified),
strtotime($this->_membership->modified));
}
/**
* Return etag, if applicable.
*
* A "weak" Etag including the profile and group id as well as
* the admin flag and ctime of the membership.
*
* @return string etag http header
*/
function etag()
{
$ctime = strtotime($this->_membership->created);
$adminflag = ($this->_membership->is_admin) ? 't' : 'f';
return 'W/"' . implode(':', array('AtomPubShowMembership',
$this->_profile->id,
$this->_group->id,
$adminflag,
$ctime)) . '"';
}
/**
* Does this require authentication?
*
* @return boolean true if delete, else false
*/
function requiresAuth()
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
$_SERVER['REQUEST_METHOD'] == 'HEAD') {
return false;
} else {
return true;
}
}
}

View File

@ -0,0 +1,223 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* Single subscription
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category AtomPub
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
require_once INSTALLDIR . '/lib/apiauth.php';
/**
* Show a single subscription
*
* @category AtomPub
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class AtompubshowsubscriptionAction extends ApiAuthAction
{
private $_subscriber = null;
private $_subscribed = null;
private $_subscription = null;
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
$subscriberId = $this->trimmed('subscriber');
$this->_subscriber = Profile::staticGet('id', $subscriberId);
if (empty($this->_subscriber)) {
// TRANS: Client exception thrown when trying to display a subscription for a non-existing profile ID.
// TRANS: %d is the non-existing profile ID number.
throw new ClientException(sprintf(_('No such profile id: %d.'),
$subscriberId), 404);
}
$subscribedId = $this->trimmed('subscribed');
$this->_subscribed = Profile::staticGet('id', $subscribedId);
if (empty($this->_subscribed)) {
// TRANS: Client exception thrown when trying to display a subscription for a non-existing profile ID.
// TRANS: %d is the non-existing profile ID number.
throw new ClientException(sprintf(_('No such profile id: %d.'),
$subscribedId), 404);
}
$this->_subscription =
Subscription::pkeyGet(array('subscriber' => $subscriberId,
'subscribed' => $subscribedId));
if (empty($this->_subscription)) {
// TRANS: Client exception thrown when trying to display a subscription for a non-subscribed profile ID.
// TRANS: %1$d is the non-existing subscriber ID number, $2$d is the ID of the profile that was not subscribed to.
$msg = sprintf(_('Profile %1$d not subscribed to profile %2$d.'),
$subscriberId, $subscribedId);
throw new ClientException($msg, 404);
}
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handle($argarray=null)
{
parent::handle($argarray);
switch ($_SERVER['REQUEST_METHOD']) {
case 'HEAD':
case 'GET':
$this->showSubscription();
break;
case 'DELETE':
$this->deleteSubscription();
break;
default:
// TRANS: Client error shown when using a non-supported HTTP method.
$this->clientError(_('HTTP method not supported.'), 405);
return;
}
return;
}
/**
* Show the subscription in ActivityStreams Atom format.
*
* @return void
*/
function showSubscription()
{
$activity = $this->_subscription->asActivity();
header('Content-Type: application/atom+xml; charset=utf-8');
$this->startXML();
$this->raw($activity->asString(true, true, true));
$this->endXML();
return;
}
/**
* Delete the subscription
*
* @return void
*/
function deleteSubscription()
{
if (empty($this->auth_user) ||
$this->auth_user->id != $this->_subscriber->id) {
// TRANS: Client exception thrown when trying to delete a subscription of another user.
throw new ClientException(_("Cannot delete someone else's ".
"subscription."), 403);
}
Subscription::cancel($this->_subscriber,
$this->_subscribed);
return;
}
/**
* Is this action read only?
*
* @param array $args other arguments
*
* @return boolean true
*/
function isReadOnly($args)
{
if ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
return false;
} else {
return true;
}
}
/**
* Return last modified, if applicable.
*
* @return string last modified http header
*/
function lastModified()
{
return max(strtotime($this->_subscriber->modified),
strtotime($this->_subscribed->modified),
strtotime($this->_subscription->modified));
}
/**
* Etag for this object
*
* @return string etag http header
*/
function etag()
{
$mtime = strtotime($this->_subscription->modified);
return 'W/"' . implode(':', array('AtomPubShowSubscription',
$this->_subscriber->id,
$this->_subscribed->id,
$mtime)) . '"';
}
/**
* Does this require authentication?
*
* @return boolean true if delete, else false
*/
function requiresAuth()
{
if ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
return true;
} else {
return false;
}
}
}

View File

@ -0,0 +1,346 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* AtomPub subscription feed
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Cache
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
require_once INSTALLDIR . '/lib/apiauth.php';
/**
* Subscription feed class for AtomPub
*
* Generates a list of the user's subscriptions
*
* @category AtomPub
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class AtompubsubscriptionfeedAction extends ApiAuthAction
{
private $_profile = null;
private $_subscriptions = null;
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
$subscriber = $this->trimmed('subscriber');
$this->_profile = Profile::staticGet('id', $subscriber);
if (empty($this->_profile)) {
// TRANS: Client exception thrown when trying to display a subscription for a non-existing profile ID.
// TRANS: %d is the non-existing profile ID number.
throw new ClientException(sprintf(_('No such profile id: %d.'),
$subscriber), 404);
}
// page and count from ApiAction
$offset = ($this->page-1) * $this->count;
$this->_subscriptions = Subscription::bySubscriber($subscriber,
$offset,
$this->count + 1);
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handle($argarray=null)
{
parent::handle($argarray);
switch ($_SERVER['REQUEST_METHOD']) {
case 'HEAD':
case 'GET':
$this->showFeed();
break;
case 'POST':
$this->addSubscription();
break;
default:
// TRANS: Client exception thrown when using an unsupported HTTP method.
$this->clientError(_('HTTP method not supported.'), 405);
return;
}
return;
}
/**
* Show the feed of subscriptions
*
* @return void
*/
function showFeed()
{
header('Content-Type: application/atom+xml; charset=utf-8');
$url = common_local_url('AtomPubSubscriptionFeed',
array('subscriber' => $this->_profile->id));
$feed = new Atom10Feed(true);
$feed->addNamespace('activity',
'http://activitystrea.ms/spec/1.0/');
$feed->addNamespace('poco',
'http://portablecontacts.net/spec/1.0');
$feed->addNamespace('media',
'http://purl.org/syndication/atommedia');
$feed->id = $url;
$feed->setUpdated('now');
$feed->addAuthor($this->_profile->getBestName(),
$this->_profile->getURI());
// TRANS: Title for Atom subscription feed.
// TRANS: %s is a user nickname.
$feed->setTitle(sprintf(_("%s subscriptions"),
$this->_profile->getBestName()));
// TRANS: Subtitle for Atom subscription feed.
// TRANS: %1$s is a user nickname, %s$s is the StatusNet sitename.
$feed->setSubtitle(sprintf(_("People %1\$s has subscribed to on %2\$s"),
$this->_profile->getBestName(),
common_config('site', 'name')));
$feed->addLink(common_local_url('subscriptions',
array('nickname' =>
$this->_profile->nickname)));
$feed->addLink($url,
array('rel' => 'self',
'type' => 'application/atom+xml'));
// If there's more...
if ($this->page > 1) {
$feed->addLink($url,
array('rel' => 'first',
'type' => 'application/atom+xml'));
$feed->addLink(common_local_url('AtomPubSubscriptionFeed',
array('subscriber' =>
$this->_profile->id),
array('page' =>
$this->page - 1)),
array('rel' => 'prev',
'type' => 'application/atom+xml'));
}
if ($this->_subscriptions->N > $this->count) {
$feed->addLink(common_local_url('AtomPubSubscriptionFeed',
array('subscriber' =>
$this->_profile->id),
array('page' =>
$this->page + 1)),
array('rel' => 'next',
'type' => 'application/atom+xml'));
}
$i = 0;
// XXX: This is kind of inefficient
while ($this->_subscriptions->fetch()) {
// We get one more than needed; skip that one
$i++;
if ($i > $this->count) {
break;
}
$act = $this->_subscriptions->asActivity();
$feed->addEntryRaw($act->asString(false, false, false));
}
$this->raw($feed->getString());
}
/**
* Add a new subscription
*
* Handling the POST method for AtomPub
*
* @return void
*/
function addSubscription()
{
if (empty($this->auth_user) ||
$this->auth_user->id != $this->_profile->id) {
// TRANS: Client exception thrown when trying to subscribe another user.
throw new ClientException(_("Cannot add someone else's".
" subscription."), 403);
}
$xml = file_get_contents('php://input');
$dom = DOMDocument::loadXML($xml);
if ($dom->documentElement->namespaceURI != Activity::ATOM ||
$dom->documentElement->localName != 'entry') {
// TRANS: Client error displayed when not using an Atom entry.
$this->clientError(_('Atom post must be an Atom entry.'));
return;
}
$activity = new Activity($dom->documentElement);
$sub = null;
if (Event::handle('StartAtomPubNewActivity', array(&$activity))) {
if ($activity->verb != ActivityVerb::FOLLOW) {
// TRANS: Client error displayed when not using the follow verb.
$this->clientError(_('Can only handle Follow activities.'));
return;
}
$person = $activity->objects[0];
if ($person->type != ActivityObject::PERSON) {
// TRANS: Client exception thrown when subscribing to an object that is not a person.
$this->clientError(_('Can only follow people.'));
return;
}
// XXX: OStatus discovery (maybe)
$profile = Profile::fromURI($person->id);
if (empty($profile)) {
// TRANS: Client exception thrown when subscribing to a non-existing profile.
// TRANS: %s is the unknown profile ID.
$this->clientError(sprintf(_('Unknown profile %s.'), $person->id));
return;
}
if (Subscription::exists($this->_profile, $profile)) {
// 409 Conflict
// TRANS: Client error displayed trying to subscribe to an already subscribed profile.
// TRANS: %s is the profile the user already has a subscription on.
$this->clientError(sprintf(_('Already subscribed to %s.'),
$person->id),
409);
return;
}
if (Subscription::start($this->_profile, $profile)) {
$sub = Subscription::pkeyGet(array('subscriber' => $this->_profile->id,
'subscribed' => $profile->id));
}
Event::handle('EndAtomPubNewActivity', array($activity, $sub));
}
if (!empty($sub)) {
$act = $sub->asActivity();
header('Content-Type: application/atom+xml; charset=utf-8');
header('Content-Location: ' . $act->selfLink);
$this->startXML();
$this->raw($act->asString(true, true, true));
$this->endXML();
}
}
/**
* Return true if read only.
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
return $_SERVER['REQUEST_METHOD'] != 'POST';
}
/**
* Return last modified, if applicable.
*
* @return string last modified http header
*/
function lastModified()
{
return null;
}
/**
* Return etag, if applicable.
*
* @return string etag http header
*/
function etag()
{
return null;
}
/**
* Does this require authentication?
*
* @return boolean true if delete, else false
*/
function requiresAuth()
{
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
return true;
} else {
return false;
}
}
}

View File

@ -42,7 +42,6 @@ require_once INSTALLDIR.'/lib/attachmentlist.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class AttachmentAction extends Action class AttachmentAction extends Action
{ {
/** /**
@ -70,6 +69,7 @@ class AttachmentAction extends Action
} }
if (empty($this->attachment)) { if (empty($this->attachment)) {
// TRANS: Client error displayed trying to get a non-existing attachment.
$this->clientError(_('No such attachment.'), 404); $this->clientError(_('No such attachment.'), 404);
return false; return false;
} }
@ -81,7 +81,6 @@ class AttachmentAction extends Action
* *
* @return boolean true * @return boolean true
*/ */
function isReadOnly($args) function isReadOnly($args)
{ {
return true; return true;
@ -129,7 +128,6 @@ class AttachmentAction extends Action
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
@ -150,7 +148,6 @@ class AttachmentAction extends Action
* *
* @return void * @return void
*/ */
function showLocalNavBlock() function showLocalNavBlock()
{ {
} }
@ -162,7 +159,6 @@ class AttachmentAction extends Action
* *
* @return void * @return void
*/ */
function showContent() function showContent()
{ {
$ali = new Attachment($this->attachment, $this); $ali = new Attachment($this->attachment, $this);
@ -174,7 +170,6 @@ class AttachmentAction extends Action
* *
* @return void * @return void
*/ */
function showPageNoticeBlock() function showPageNoticeBlock()
{ {
} }
@ -191,4 +186,3 @@ class AttachmentAction extends Action
$atcs->show(); $atcs->show();
} }
} }

View File

@ -42,7 +42,6 @@ require_once INSTALLDIR.'/actions/attachment.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class Attachment_ajaxAction extends AttachmentAction class Attachment_ajaxAction extends AttachmentAction
{ {
/** /**
@ -80,4 +79,3 @@ class Attachment_ajaxAction extends AttachmentAction
$this->elementEnd('div'); $this->elementEnd('div');
} }
} }

View File

@ -42,10 +42,8 @@ require_once INSTALLDIR.'/actions/attachment.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class Attachment_thumbnailAction extends AttachmentAction class Attachment_thumbnailAction extends AttachmentAction
{ {
function handle($args) function handle($args)
{ {
$this->showPage(); $this->showPage();
@ -79,6 +77,4 @@ class Attachment_thumbnailAction extends AttachmentAction
} }
$this->element('img', array('src' => $file_thumbnail->url, 'alt' => 'Thumbnail')); $this->element('img', array('src' => $file_thumbnail->url, 'alt' => 'Thumbnail'));
} }
} }

View File

@ -48,7 +48,7 @@ class AvatarbynicknameAction extends Action
* Class handler. * Class handler.
* *
* @param array $args query arguments * @param array $args query arguments
* *
* @return boolean false if nickname or user isn't found * @return boolean false if nickname or user isn't found
*/ */
function handle($args) function handle($args)
@ -56,27 +56,32 @@ class AvatarbynicknameAction extends Action
parent::handle($args); parent::handle($args);
$nickname = $this->trimmed('nickname'); $nickname = $this->trimmed('nickname');
if (!$nickname) { if (!$nickname) {
// TRANS: Client error displayed trying to get an avatar without providing a nickname.
$this->clientError(_('No nickname.')); $this->clientError(_('No nickname.'));
return; return;
} }
$size = $this->trimmed('size'); $size = $this->trimmed('size');
if (!$size) { if (!$size) {
// TRANS: Client error displayed trying to get an avatar without providing an avatar size.
$this->clientError(_('No size.')); $this->clientError(_('No size.'));
return; return;
} }
$size = strtolower($size); $size = strtolower($size);
if (!in_array($size, array('original', '96', '48', '24'))) { if (!in_array($size, array('original', '96', '48', '24'))) {
// TRANS: Client error displayed trying to get an avatar providing an invalid avatar size.
$this->clientError(_('Invalid size.')); $this->clientError(_('Invalid size.'));
return; return;
} }
$user = User::staticGet('nickname', $nickname); $user = User::staticGet('nickname', $nickname);
if (!$user) { if (!$user) {
// TRANS: Client error displayed trying to get an avatar for a non-existing user.
$this->clientError(_('No such user.')); $this->clientError(_('No such user.'));
return; return;
} }
$profile = $user->getProfile(); $profile = $user->getProfile();
if (!$profile) { if (!$profile) {
// TRANS: Client error displayed trying to get an avatar for a user without a profile.
$this->clientError(_('User has no profile.')); $this->clientError(_('User has no profile.'));
return; return;
} }
@ -103,4 +108,3 @@ class AvatarbynicknameAction extends Action
return true; return true;
} }
} }

View File

@ -49,7 +49,6 @@ define('MAX_ORIGINAL', 480);
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class AvatarsettingsAction extends AccountSettingsAction class AvatarsettingsAction extends AccountSettingsAction
{ {
var $mode = null; var $mode = null;
@ -61,9 +60,9 @@ class AvatarsettingsAction extends AccountSettingsAction
* *
* @return string Title of the page * @return string Title of the page
*/ */
function title() function title()
{ {
// TRANS: Title for avatar upload page.
return _('Avatar'); return _('Avatar');
} }
@ -72,10 +71,12 @@ class AvatarsettingsAction extends AccountSettingsAction
* *
* @return instructions for use * @return instructions for use
*/ */
function getInstructions() function getInstructions()
{ {
return sprintf(_('You can upload your personal avatar. The maximum file size is %s.'), ImageFile::maxFileSize()); // TRANS: Instruction for avatar upload page.
// TRANS: %s is the maximum file size, for example "500b", "10kB" or "2MB".
return sprintf(_('You can upload your personal avatar. The maximum file size is %s.'),
ImageFile::maxFileSize());
} }
/** /**
@ -103,6 +104,7 @@ class AvatarsettingsAction extends AccountSettingsAction
if (!$profile) { if (!$profile) {
common_log_db_error($user, 'SELECT', __FILE__); common_log_db_error($user, 'SELECT', __FILE__);
// TRANS: Server error displayed in avatar upload page when no matching profile can be found for a user.
$this->serverError(_('User without matching profile.')); $this->serverError(_('User without matching profile.'));
return; return;
} }
@ -116,14 +118,16 @@ class AvatarsettingsAction extends AccountSettingsAction
'action' => 'action' =>
common_local_url('avatarsettings'))); common_local_url('avatarsettings')));
$this->elementStart('fieldset'); $this->elementStart('fieldset');
// TRANS: Avatar upload page form legend.
$this->element('legend', null, _('Avatar settings')); $this->element('legend', null, _('Avatar settings'));
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
if (Event::handle('StartAvatarFormData', array($this))) { if (Event::handle('StartAvatarFormData', array($this))) {
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
if ($original) { if ($original) {
$this->elementStart('li', array('id' => 'avatar_original', $this->elementStart('li', array('id' => 'avatar_original',
'class' => 'avatar_view')); 'class' => 'avatar_view'));
// TRANS: Header on avatar upload page for thumbnail of originally uploaded avatar (h2).
$this->element('h2', null, _("Original")); $this->element('h2', null, _("Original"));
$this->elementStart('div', array('id'=>'avatar_original_view')); $this->elementStart('div', array('id'=>'avatar_original_view'));
$this->element('img', array('src' => $original->url, $this->element('img', array('src' => $original->url,
@ -139,6 +143,7 @@ class AvatarsettingsAction extends AccountSettingsAction
if ($avatar) { if ($avatar) {
$this->elementStart('li', array('id' => 'avatar_preview', $this->elementStart('li', array('id' => 'avatar_preview',
'class' => 'avatar_view')); 'class' => 'avatar_view'));
// TRANS: Header on avatar upload page for thumbnail of to be used rendition of uploaded avatar (h2).
$this->element('h2', null, _("Preview")); $this->element('h2', null, _("Preview"));
$this->elementStart('div', array('id'=>'avatar_preview_view')); $this->elementStart('div', array('id'=>'avatar_preview_view'));
$this->element('img', array('src' => $original->url, $this->element('img', array('src' => $original->url,
@ -146,24 +151,26 @@ class AvatarsettingsAction extends AccountSettingsAction
'height' => AVATAR_PROFILE_SIZE, 'height' => AVATAR_PROFILE_SIZE,
'alt' => $user->nickname)); 'alt' => $user->nickname));
$this->elementEnd('div'); $this->elementEnd('div');
$this->submit('delete', _('Delete')); // TRANS: Button on avatar upload page to delete current avatar.
$this->submit('delete', _m('BUTTON','Delete'));
$this->elementEnd('li'); $this->elementEnd('li');
} }
$this->elementStart('li', array ('id' => 'settings_attach')); $this->elementStart('li', array ('id' => 'settings_attach'));
$this->element('input', array('name' => 'avatarfile',
'type' => 'file',
'id' => 'avatarfile'));
$this->element('input', array('name' => 'MAX_FILE_SIZE', $this->element('input', array('name' => 'MAX_FILE_SIZE',
'type' => 'hidden', 'type' => 'hidden',
'id' => 'MAX_FILE_SIZE', 'id' => 'MAX_FILE_SIZE',
'value' => ImageFile::maxFileSizeInt())); 'value' => ImageFile::maxFileSizeInt()));
$this->element('input', array('name' => 'avatarfile',
'type' => 'file',
'id' => 'avatarfile'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->elementStart('ul', 'form_actions'); $this->elementStart('ul', 'form_actions');
$this->elementStart('li'); $this->elementStart('li');
$this->submit('upload', _('Upload')); // TRANS: Button on avatar upload page to upload an avatar.
$this->submit('upload', _m('BUTTON','Upload'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
} }
@ -171,7 +178,6 @@ class AvatarsettingsAction extends AccountSettingsAction
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }
function showCropForm() function showCropForm()
@ -182,6 +188,7 @@ class AvatarsettingsAction extends AccountSettingsAction
if (!$profile) { if (!$profile) {
common_log_db_error($user, 'SELECT', __FILE__); common_log_db_error($user, 'SELECT', __FILE__);
// TRANS: Server error displayed in avatar upload page when no matching profile can be found for a user.
$this->serverError(_('User without matching profile.')); $this->serverError(_('User without matching profile.'));
return; return;
} }
@ -194,6 +201,7 @@ class AvatarsettingsAction extends AccountSettingsAction
'action' => 'action' =>
common_local_url('avatarsettings'))); common_local_url('avatarsettings')));
$this->elementStart('fieldset'); $this->elementStart('fieldset');
// TRANS: Avatar upload page crop form legend.
$this->element('legend', null, _('Avatar settings')); $this->element('legend', null, _('Avatar settings'));
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
@ -202,6 +210,7 @@ class AvatarsettingsAction extends AccountSettingsAction
$this->elementStart('li', $this->elementStart('li',
array('id' => 'avatar_original', array('id' => 'avatar_original',
'class' => 'avatar_view')); 'class' => 'avatar_view'));
// TRANS: Header on avatar upload crop form for thumbnail of originally uploaded avatar (h2).
$this->element('h2', null, _("Original")); $this->element('h2', null, _("Original"));
$this->elementStart('div', array('id'=>'avatar_original_view')); $this->elementStart('div', array('id'=>'avatar_original_view'));
$this->element('img', array('src' => Avatar::url($this->filedata['filename']), $this->element('img', array('src' => Avatar::url($this->filedata['filename']),
@ -214,6 +223,7 @@ class AvatarsettingsAction extends AccountSettingsAction
$this->elementStart('li', $this->elementStart('li',
array('id' => 'avatar_preview', array('id' => 'avatar_preview',
'class' => 'avatar_view')); 'class' => 'avatar_view'));
// TRANS: Header on avatar upload crop form for thumbnail of to be used rendition of uploaded avatar (h2).
$this->element('h2', null, _("Preview")); $this->element('h2', null, _("Preview"));
$this->elementStart('div', array('id'=>'avatar_preview_view')); $this->elementStart('div', array('id'=>'avatar_preview_view'));
$this->element('img', array('src' => Avatar::url($this->filedata['filename']), $this->element('img', array('src' => Avatar::url($this->filedata['filename']),
@ -228,13 +238,14 @@ class AvatarsettingsAction extends AccountSettingsAction
'type' => 'hidden', 'type' => 'hidden',
'id' => $crop_info)); 'id' => $crop_info));
} }
$this->submit('crop', _('Crop'));
// TRANS: Button on avatar upload crop form to confirm a selected crop as avatar.
$this->submit('crop', _m('BUTTON','Crop'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }
/** /**
@ -244,7 +255,6 @@ class AvatarsettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function handlePost() function handlePost()
{ {
// Workaround for PHP returning empty $_POST and $_FILES when POST // Workaround for PHP returning empty $_POST and $_FILES when POST
@ -271,7 +281,7 @@ class AvatarsettingsAction extends AccountSettingsAction
'Try again, please.')); 'Try again, please.'));
return; return;
} }
if (Event::handle('StartAvatarSaveForm', array($this))) { if (Event::handle('StartAvatarSaveForm', array($this))) {
if ($this->arg('upload')) { if ($this->arg('upload')) {
$this->uploadAvatar(); $this->uploadAvatar();
@ -280,6 +290,7 @@ class AvatarsettingsAction extends AccountSettingsAction
} else if ($this->arg('delete')) { } else if ($this->arg('delete')) {
$this->deleteAvatar(); $this->deleteAvatar();
} else { } else {
// TRANS: Unexpected validation error on avatar upload form.
$this->showForm(_('Unexpected form submission.')); $this->showForm(_('Unexpected form submission.'));
} }
Event::handle('EndAvatarSaveForm', array($this)); Event::handle('EndAvatarSaveForm', array($this));
@ -294,7 +305,6 @@ class AvatarsettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function uploadAvatar() function uploadAvatar()
{ {
try { try {
@ -304,26 +314,26 @@ class AvatarsettingsAction extends AccountSettingsAction
return; return;
} }
if ($imagefile === null) { if ($imagefile === null) {
// TRANS: Validation error on avatar upload form when no file was uploaded.
$this->showForm(_('No file uploaded.')); $this->showForm(_('No file uploaded.'));
return; return;
} }
$cur = common_current_user(); $cur = common_current_user();
$type = $imagefile->preferredType();
$filename = Avatar::filename($cur->id, $filename = Avatar::filename($cur->id,
image_type_to_extension($imagefile->type), image_type_to_extension($type),
null, null,
'tmp'.common_timestamp()); 'tmp'.common_timestamp());
$filepath = Avatar::path($filename); $filepath = Avatar::path($filename);
$imagefile->copyTo($filepath);
move_uploaded_file($imagefile->filepath, $filepath);
$filedata = array('filename' => $filename, $filedata = array('filename' => $filename,
'filepath' => $filepath, 'filepath' => $filepath,
'width' => $imagefile->width, 'width' => $imagefile->width,
'height' => $imagefile->height, 'height' => $imagefile->height,
'type' => $imagefile->type); 'type' => $type);
$_SESSION['FILEDATA'] = $filedata; $_SESSION['FILEDATA'] = $filedata;
@ -331,6 +341,7 @@ class AvatarsettingsAction extends AccountSettingsAction
$this->mode = 'crop'; $this->mode = 'crop';
// TRANS: Avatar upload form unstruction after uploading a file.
$this->showForm(_('Pick a square area of the image to be your avatar'), $this->showForm(_('Pick a square area of the image to be your avatar'),
true); true);
} }
@ -340,12 +351,12 @@ class AvatarsettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function cropAvatar() function cropAvatar()
{ {
$filedata = $_SESSION['FILEDATA']; $filedata = $_SESSION['FILEDATA'];
if (!$filedata) { if (!$filedata) {
// TRANS: Server error displayed if an avatar upload went wrong somehow server side.
$this->serverError(_('Lost our file data.')); $this->serverError(_('Lost our file data.'));
return; return;
} }
@ -369,24 +380,25 @@ class AvatarsettingsAction extends AccountSettingsAction
@unlink($filedata['filepath']); @unlink($filedata['filepath']);
unset($_SESSION['FILEDATA']); unset($_SESSION['FILEDATA']);
$this->mode = 'upload'; $this->mode = 'upload';
// TRANS: Success message for having updated a user avatar.
$this->showForm(_('Avatar updated.'), true); $this->showForm(_('Avatar updated.'), true);
common_broadcast_profile($profile); common_broadcast_profile($profile);
} else { } else {
// TRANS: Error displayed on the avatar upload page if the avatar could not be updated for an unknown reason.
$this->showForm(_('Failed updating avatar.')); $this->showForm(_('Failed updating avatar.'));
} }
} }
/** /**
* Get rid of the current avatar. * Get rid of the current avatar.
* *
* @return void * @return void
*/ */
function deleteAvatar() function deleteAvatar()
{ {
$user = common_current_user(); $user = common_current_user();
$profile = $user->getProfile(); $profile = $user->getProfile();
$avatar = $profile->getOriginalAvatar(); $avatar = $profile->getOriginalAvatar();
if($avatar) $avatar->delete(); if($avatar) $avatar->delete();
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
@ -396,6 +408,7 @@ class AvatarsettingsAction extends AccountSettingsAction
$avatar = $profile->getAvatar(AVATAR_MINI_SIZE); $avatar = $profile->getAvatar(AVATAR_MINI_SIZE);
if($avatar) $avatar->delete(); if($avatar) $avatar->delete();
// TRANS: Success message for deleting a user avatar.
$this->showForm(_('Avatar deleted.'), true); $this->showForm(_('Avatar deleted.'), true);
} }
@ -416,7 +429,6 @@ class AvatarsettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function showScripts() function showScripts()
{ {
parent::showScripts(); parent::showScripts();

254
actions/backupaccount.php Normal file
View File

@ -0,0 +1,254 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* Download a backup of your own account to the browser
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Account
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
/**
* Download a backup of your own account to the browser
*
* We go through some hoops to make this only respond to POST, since
* it's kind of expensive and there's probably some downside to having
* your account in all kinds of search engines.
*
* @category Account
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class BackupaccountAction extends Action
{
/**
* Returns the title of the page
*
* @return string page title
*/
function title()
{
// TRANS: Title for backup account page.
return _("Backup account");
}
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
$cur = common_current_user();
if (empty($cur)) {
// TRANS: Client exception thrown when trying to backup an account while not logged in.
throw new ClientException(_('Only logged-in users can backup their account.'), 403);
}
if (!$cur->hasRight(Right::BACKUPACCOUNT)) {
// TRANS: Client exception thrown when trying to backup an account without having backup rights.
throw new ClientException(_('You may not backup your account.'), 403);
}
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handle($argarray=null)
{
parent::handle($argarray);
if ($this->isPost()) {
$this->sendFeed();
} else {
$this->showPage();
}
return;
}
/**
* Send a feed of the user's activities to the browser
*
* Uses the UserActivityStream class; may take a long time!
*
* @return void
*/
function sendFeed()
{
$cur = common_current_user();
$stream = new UserActivityStream($cur);
header('Content-Disposition: attachment; filename='.$cur->nickname.'.atom');
header('Content-Type: application/atom+xml; charset=utf-8');
$this->raw($stream->getString());
}
/**
* Show a little form so that the person can request a backup.
*
* @return void
*/
function showContent()
{
$form = new BackupAccountForm($this);
$form->show();
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
return false;
}
/**
* Return last modified, if applicable.
*
* MAY override
*
* @return string last modified http header
*/
function lastModified()
{
// For comparison with If-Last-Modified
// If not applicable, return null
return null;
}
/**
* Return etag, if applicable.
*
* MAY override
*
* @return string etag http header
*/
function etag()
{
return null;
}
}
/**
* A form for backing up the account.
*
* @category Account
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class BackupAccountForm extends Form
{
/**
* Class of the form.
*
* @return string the form's class
*/
function formClass()
{
return 'form_profile_backup';
}
/**
* URL the form posts to
*
* @return string the form's action URL
*/
function action()
{
return common_local_url('backupaccount');
}
/**
* Output form data
*
* Really, just instructions for doing a backup.
*
* @return void
*/
function formData()
{
$msg =
// TRANS: Information displayed on the backup account page.
_('You can backup your account data in '.
'<a href="http://activitystrea.ms/">Activity Streams</a> '.
'format. This is an experimental feature and provides an '.
'incomplete backup; private account '.
'information like email and IM addresses is not backed up. '.
'Additionally, uploaded files and direct messages are not '.
'backed up.');
$this->out->elementStart('p');
$this->out->raw($msg);
$this->out->elementEnd('p');
}
/**
* Buttons for the form
*
* In this case, a single submit button
*
* @return void
*/
function formActions()
{
$this->out->submit('submit',
// TRANS: Submit button to backup an account on the backup account page.
_m('BUTTON', 'Backup'),
'submit',
null,
// TRANS: Title for submit button to backup an account on the backup account page.
_('Backup your account'));
}
}

View File

@ -42,7 +42,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */
class BlockAction extends ProfileFormAction class BlockAction extends ProfileFormAction
{ {
var $profile = null; var $profile = null;
@ -54,7 +53,6 @@ class BlockAction extends ProfileFormAction
* *
* @return boolean success flag * @return boolean success flag
*/ */
function prepare($args) function prepare($args)
{ {
if (!parent::prepare($args)) { if (!parent::prepare($args)) {
@ -66,6 +64,7 @@ class BlockAction extends ProfileFormAction
assert(!empty($cur)); // checked by parent assert(!empty($cur)); // checked by parent
if ($cur->hasBlocked($this->profile)) { if ($cur->hasBlocked($this->profile)) {
// TRANS: Client error displayed when blocking a user that has already been blocked.
$this->clientError(_('You already blocked that user.')); $this->clientError(_('You already blocked that user.'));
return false; return false;
} }
@ -82,7 +81,6 @@ class BlockAction extends ProfileFormAction
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($_SERVER['REQUEST_METHOD'] == 'POST') {
@ -104,6 +102,7 @@ class BlockAction extends ProfileFormAction
} }
function title() { function title() {
// TRANS: Title for block user page.
return _('Block user'); return _('Block user');
} }
@ -133,8 +132,10 @@ class BlockAction extends ProfileFormAction
'action' => common_local_url('block'))); 'action' => common_local_url('block')));
$this->elementStart('fieldset'); $this->elementStart('fieldset');
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
// TRANS: Legend for block user form.
$this->element('legend', _('Block user')); $this->element('legend', _('Block user'));
$this->element('p', null, $this->element('p', null,
// TRANS: Explanation of consequences when blocking a user on the block user page.
_('Are you sure you want to block this user? '. _('Are you sure you want to block this user? '.
'Afterwards, they will be unsubscribed from you, '. 'Afterwards, they will be unsubscribed from you, '.
'unable to subscribe to you in the future, and '. 'unable to subscribe to you in the future, and '.
@ -184,6 +185,7 @@ class BlockAction extends ProfileFormAction
} }
if (!$result) { if (!$result) {
// TRANS: Server error displayed when blocking a user fails.
$this->serverError(_('Failed to save block information.')); $this->serverError(_('Failed to save block information.'));
return; return;
} }
@ -199,7 +201,7 @@ class BlockAction extends ProfileFormAction
* Override for form session token checks; on our first hit we're just * Override for form session token checks; on our first hit we're just
* requesting confirmation, which doesn't need a token. We need to be * requesting confirmation, which doesn't need a token. We need to be
* able to take regular GET requests from email! * able to take regular GET requests from email!
* *
* @throws ClientException if token is bad on POST request or if we have * @throws ClientException if token is bad on POST request or if we have
* confirmation parameters which could trigger something. * confirmation parameters which could trigger something.
*/ */
@ -216,7 +218,7 @@ class BlockAction extends ProfileFormAction
/** /**
* If we reached this form without returnto arguments, return to the * If we reached this form without returnto arguments, return to the
* current user's subscription list. * current user's subscription list.
* *
* @return string URL * @return string URL
*/ */
function defaultReturnTo() function defaultReturnTo()

View File

@ -40,7 +40,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class BlockedfromgroupAction extends GroupDesignAction class BlockedfromgroupAction extends GroupDesignAction
{ {
var $page = null; var $page = null;
@ -70,6 +69,7 @@ class BlockedfromgroupAction extends GroupDesignAction
} }
if (!$nickname) { if (!$nickname) {
// TRANS: Client error displayed when requesting a list of blocked users for a group without providing a group nickname.
$this->clientError(_('No nickname.'), 404); $this->clientError(_('No nickname.'), 404);
return false; return false;
} }
@ -77,6 +77,7 @@ class BlockedfromgroupAction extends GroupDesignAction
$local = Local_group::staticGet('nickname', $nickname); $local = Local_group::staticGet('nickname', $nickname);
if (!$local) { if (!$local) {
// TRANS: Client error displayed when requesting a list of blocked users for a non-local group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -84,6 +85,7 @@ class BlockedfromgroupAction extends GroupDesignAction
$this->group = User_group::staticGet('id', $local->group_id); $this->group = User_group::staticGet('id', $local->group_id);
if (!$this->group) { if (!$this->group) {
// TRANS: Client error displayed when requesting a list of blocked users for a non-existing group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -94,9 +96,13 @@ class BlockedfromgroupAction extends GroupDesignAction
function title() function title()
{ {
if ($this->page == 1) { if ($this->page == 1) {
// TRANS: Title for first page with list of users blocked from a group.
// TRANS: %s is a group nickname.
return sprintf(_('%s blocked profiles'), return sprintf(_('%s blocked profiles'),
$this->group->nickname); $this->group->nickname);
} else { } else {
// TRANS: Title for any but the first page with list of users blocked from a group.
// TRANS: %1$s is a group nickname, %2$d is a page number.
return sprintf(_('%1$s blocked profiles, page %2$d'), return sprintf(_('%1$s blocked profiles, page %2$d'),
$this->group->nickname, $this->group->nickname,
$this->page); $this->page);
@ -112,6 +118,7 @@ class BlockedfromgroupAction extends GroupDesignAction
function showPageNotice() function showPageNotice()
{ {
$this->element('p', 'instructions', $this->element('p', 'instructions',
// TRANS: Instructions for list of users blocked from a group.
_('A list of the users blocked from joining this group.')); _('A list of the users blocked from joining this group.'));
} }
@ -205,7 +212,6 @@ class GroupBlockListItem extends ProfileListItem
* *
* @see UnblockForm * @see UnblockForm
*/ */
class GroupUnblockForm extends Form class GroupUnblockForm extends Form
{ {
/** /**
@ -234,7 +240,6 @@ class GroupUnblockForm extends Form
* @param User_group $group group to block user from * @param User_group $group group to block user from
* @param array $args return-to args * @param array $args return-to args
*/ */
function __construct($out=null, $profile=null, $group=null, $args=null) function __construct($out=null, $profile=null, $group=null, $args=null)
{ {
parent::__construct($out); parent::__construct($out);
@ -249,7 +254,6 @@ class GroupUnblockForm extends Form
* *
* @return int ID of the form * @return int ID of the form
*/ */
function id() function id()
{ {
// This should be unique for the page. // This should be unique for the page.
@ -261,7 +265,6 @@ class GroupUnblockForm extends Form
* *
* @return string class of the form * @return string class of the form
*/ */
function formClass() function formClass()
{ {
return 'form_group_unblock'; return 'form_group_unblock';
@ -272,7 +275,6 @@ class GroupUnblockForm extends Form
* *
* @return string URL of the action * @return string URL of the action
*/ */
function action() function action()
{ {
return common_local_url('groupunblock'); return common_local_url('groupunblock');
@ -285,6 +287,7 @@ class GroupUnblockForm extends Form
*/ */
function formLegend() function formLegend()
{ {
// TRANS: Form legend for unblocking a user from a group.
$this->out->element('legend', null, _('Unblock user from group')); $this->out->element('legend', null, _('Unblock user from group'));
} }
@ -293,7 +296,6 @@ class GroupUnblockForm extends Form
* *
* @return void * @return void
*/ */
function formData() function formData()
{ {
$this->out->hidden('unblockto-' . $this->profile->id, $this->out->hidden('unblockto-' . $this->profile->id,
@ -314,9 +316,14 @@ class GroupUnblockForm extends Form
* *
* @return void * @return void
*/ */
function formActions() function formActions()
{ {
$this->out->submit('submit', _('Unblock'), 'submit', null, _('Unblock this user')); $this->out->submit('submit',
// TRANS: Button text for unblocking a user from a group.
_m('BUTTON','Unblock'),
'submit',
null,
// TRANS: Tooltip for button for unblocking a user from a group.
_('Unblock this user'));
} }
} }

View File

@ -34,7 +34,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
require_once INSTALLDIR . '/actions/newnotice.php'; require_once INSTALLDIR . '/actions/newnotice.php';
/** /**
* Action for posting a notice * Action for posting a notice
* *
* @category Bookmarklet * @category Bookmarklet
* @package StatusNet * @package StatusNet
@ -42,12 +42,12 @@ require_once INSTALLDIR . '/actions/newnotice.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class BookmarkletAction extends NewnoticeAction class BookmarkletAction extends NewnoticeAction
{ {
function showTitle() function showTitle()
{ {
// TRANS: Title for mini-posting window loaded from bookmarklet. // TRANS: Title for mini-posting window loaded from bookmarklet.
// TRANS: %s is the StatusNet site name.
$this->element('title', null, sprintf(_('Post to %s'), common_config('site', 'name'))); $this->element('title', null, sprintf(_('Post to %s'), common_config('site', 'name')));
} }
@ -73,4 +73,3 @@ class BookmarkletAction extends NewnoticeAction
{ {
} }
} }

View File

@ -44,7 +44,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class ConfirmaddressAction extends Action class ConfirmaddressAction extends Action
{ {
/** type of confirmation. */ /** type of confirmation. */
@ -61,7 +60,6 @@ class ConfirmaddressAction extends Action
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
@ -72,27 +70,30 @@ class ConfirmaddressAction extends Action
} }
$code = $this->trimmed('code'); $code = $this->trimmed('code');
if (!$code) { if (!$code) {
// TRANS: Client error displayed when not providing a confirmation code in the contact address confirmation action.
$this->clientError(_('No confirmation code.')); $this->clientError(_('No confirmation code.'));
return; return;
} }
$confirm = Confirm_address::staticGet('code', $code); $confirm = Confirm_address::staticGet('code', $code);
if (!$confirm) { if (!$confirm) {
// TRANS: Client error displayed when providing a non-existing confirmation code in the contact address confirmation action.
$this->clientError(_('Confirmation code not found.')); $this->clientError(_('Confirmation code not found.'));
return; return;
} }
$cur = common_current_user(); $cur = common_current_user();
if ($cur->id != $confirm->user_id) { if ($cur->id != $confirm->user_id) {
// TRANS: Client error displayed when not providing a confirmation code for another user in the contact address confirmation action.
$this->clientError(_('That confirmation code is not for you!')); $this->clientError(_('That confirmation code is not for you!'));
return; return;
} }
$type = $confirm->address_type; $type = $confirm->address_type;
if (!in_array($type, array('email', 'jabber', 'sms'))) { if (!in_array($type, array('email', 'jabber', 'sms'))) {
// TRANS: Server error for an unknow address type, which can be 'email', 'jabber', or 'sms'. // TRANS: Server error for a unknow address type %s, which can be 'email', 'jabber', or 'sms'.
$this->serverError(sprintf(_('Unrecognized address type %s.'), $type)); $this->serverError(sprintf(_('Unrecognized address type %s.'), $type));
return; return;
} }
if ($cur->$type == $confirm->address) { if ($cur->$type == $confirm->address) {
// TRANS: Client error for an already confirmed email/jabbel/sms address. // TRANS: Client error for an already confirmed email/jabber/sms address.
$this->clientError(_('That address has already been confirmed.')); $this->clientError(_('That address has already been confirmed.'));
return; return;
} }
@ -113,7 +114,8 @@ class ConfirmaddressAction extends Action
if (!$result) { if (!$result) {
common_log_db_error($cur, 'UPDATE', __FILE__); common_log_db_error($cur, 'UPDATE', __FILE__);
$this->serverError(_('Couldn\'t update user.')); // TRANS: Server error displayed when a user update to the database fails in the contact address confirmation action.
$this->serverError(_('Could not update user.'));
return; return;
} }
@ -125,7 +127,9 @@ class ConfirmaddressAction extends Action
if (!$result) { if (!$result) {
common_log_db_error($confirm, 'DELETE', __FILE__); common_log_db_error($confirm, 'DELETE', __FILE__);
$this->serverError(_('Couldn\'t delete email confirmation.')); // TRANS: Server error displayed when an address confirmation code deletion from the
// TRANS: database fails in the contact address confirmation action.
$this->serverError(_('Could not delete address confirmation.'));
return; return;
} }
@ -140,9 +144,9 @@ class ConfirmaddressAction extends Action
* *
* @return string title * @return string title
*/ */
function title() function title()
{ {
// TRANS: Title for the contact address confirmation action.
return _('Confirm address'); return _('Confirm address');
} }
@ -151,13 +155,14 @@ class ConfirmaddressAction extends Action
* *
* @return void * @return void
*/ */
function showContent() function showContent()
{ {
$cur = common_current_user(); $cur = common_current_user();
$type = $this->type; $type = $this->type;
$this->element('p', null, $this->element('p', null,
// TRANS: Success message for the contact address confirmation action.
// TRANS: %s can be 'email', 'jabber', or 'sms'.
sprintf(_('The address "%s" has been '. sprintf(_('The address "%s" has been '.
'confirmed for your account.'), 'confirmed for your account.'),
$cur->$type)); $cur->$type));

View File

@ -45,7 +45,6 @@ require_once INSTALLDIR.'/lib/noticelist.php';
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */
class ConversationAction extends Action class ConversationAction extends Action
{ {
var $id = null; var $id = null;
@ -58,7 +57,6 @@ class ConversationAction extends Action
* *
* @return boolean false if id not passed in * @return boolean false if id not passed in
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
@ -81,7 +79,6 @@ class ConversationAction extends Action
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
@ -93,10 +90,10 @@ class ConversationAction extends Action
* *
* @return string page title * @return string page title
*/ */
function title() function title()
{ {
return _("Conversation"); // TRANS: Title for page with a conversion (multiple notices in context).
return _('Conversation');
} }
/** /**
@ -107,7 +104,6 @@ class ConversationAction extends Action
* *
* @return void * @return void
*/ */
function showContent() function showContent()
{ {
$notices = Notice::conversationStream($this->id, null, null); $notices = Notice::conversationStream($this->id, null, null);
@ -134,7 +130,6 @@ class ConversationAction extends Action
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */
class ConversationTree extends NoticeList class ConversationTree extends NoticeList
{ {
var $tree = null; var $tree = null;
@ -145,12 +140,12 @@ class ConversationTree extends NoticeList
* *
* @return void * @return void
*/ */
function show() function show()
{ {
$cnt = $this->_buildTree(); $cnt = $this->_buildTree();
$this->out->elementStart('div', array('id' =>'notices_primary')); $this->out->elementStart('div', array('id' =>'notices_primary'));
// TRANS: Header on conversation page. Hidden by default (h2).
$this->out->element('h2', null, _('Notices')); $this->out->element('h2', null, _('Notices'));
$this->out->elementStart('ol', array('class' => 'notices xoxo')); $this->out->elementStart('ol', array('class' => 'notices xoxo'));
@ -200,7 +195,6 @@ class ConversationTree extends NoticeList
* *
* @return void * @return void
*/ */
function showNoticePlus($id) function showNoticePlus($id)
{ {
$notice = $this->table[$id]; $notice = $this->table[$id];
@ -237,7 +231,6 @@ class ConversationTree extends NoticeList
* *
* @return NoticeListItem a list item to show * @return NoticeListItem a list item to show
*/ */
function newListItem($notice) function newListItem($notice)
{ {
return new ConversationTreeItem($notice, $this->out); return new ConversationTreeItem($notice, $this->out);
@ -255,7 +248,6 @@ class ConversationTree extends NoticeList
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */
class ConversationTreeItem extends NoticeListItem class ConversationTreeItem extends NoticeListItem
{ {
/** /**
@ -266,7 +258,6 @@ class ConversationTreeItem extends NoticeListItem
* *
* @return void * @return void
*/ */
function showStart() function showStart()
{ {
return; return;
@ -280,7 +271,6 @@ class ConversationTreeItem extends NoticeListItem
* *
* @return void * @return void
*/ */
function showEnd() function showEnd()
{ {
return; return;
@ -293,7 +283,6 @@ class ConversationTreeItem extends NoticeListItem
* *
* @return void * @return void
*/ */
function showContext() function showContext()
{ {
return; return;

325
actions/deleteaccount.php Normal file
View File

@ -0,0 +1,325 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* Delete your own account
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Account
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
/**
* Action to delete your own account
*
* Note that this is distinct from DeleteuserAction, which see. I thought
* that making that action do both things (delete another user and delete the
* current user) would open a lot of holes. I'm open to refactoring, however.
*
* @category Account
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class DeleteaccountAction extends Action
{
private $_complete = false;
private $_error = null;
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
$cur = common_current_user();
if (empty($cur)) {
// TRANS: Client exception displayed trying to delete a user account while not logged in.
throw new ClientException(_("Only logged-in users ".
"can delete their account."), 403);
}
if (!$cur->hasRight(Right::DELETEACCOUNT)) {
// TRANS: Client exception displayed trying to delete a user account without have the rights to do that.
throw new ClientException(_("You cannot delete your account."), 403);
}
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handle($argarray=null)
{
parent::handle($argarray);
if ($this->isPost()) {
$this->deleteAccount();
} else {
$this->showPage();
}
return;
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
return false;
}
/**
* Return last modified, if applicable.
*
* MAY override
*
* @return string last modified http header
*/
function lastModified()
{
// For comparison with If-Last-Modified
// If not applicable, return null
return null;
}
/**
* Return etag, if applicable.
*
* MAY override
*
* @return string etag http header
*/
function etag()
{
return null;
}
/**
* Delete the current user's account
*
* Checks for the "I am sure." string to make sure the user really
* wants to delete their account.
*
* Then, marks the account as deleted and begins the deletion process
* (actually done by a back-end handler).
*
* If successful it logs the user out, and shows a brief completion message.
*
* @return void
*/
function deleteAccount()
{
$this->checkSessionToken();
// !!! If this string is changed, it also needs to be changed in DeleteAccountForm::formData()
// TRANS: Confirmation text for user deletion. The user has to type this exactly the same, including punctuation.
$iamsure = _('I am sure.');
if ($this->trimmed('iamsure') != $iamsure ) {
// TRANS: Notification for user about the text that must be input to be able to delete a user account.
// TRANS: %s is the text that needs to be input.
$this->_error = sprintf(_('You must write "%s" exactly in the box.'), $iamsure);
$this->showPage();
return;
}
$cur = common_current_user();
// Mark the account as deleted and shove low-level deletion tasks
// to background queues. Removing a lot of posts can take a while...
if (!$cur->hasRole(Profile_role::DELETED)) {
$cur->grantRole(Profile_role::DELETED);
}
$qm = QueueManager::get();
$qm->enqueue($cur, 'deluser');
// The user is really-truly logged out
common_set_user(null);
common_real_login(false); // not logged in
common_forgetme(); // don't log back in!
$this->_complete = true;
$this->showPage();
}
/**
* Shows the page content.
*
* If the deletion is complete, just shows a completion message.
*
* Otherwise, shows the deletion form.
*
* @return void
*
*/
function showContent()
{
if ($this->_complete) {
$this->element('p', 'confirmation',
// TRANS: Confirmation that a user account has been deleted.
_('Account deleted.'));
return;
}
if (!empty($this->_error)) {
$this->element('p', 'error', $this->_error);
$this->_error = null;
}
$form = new DeleteAccountForm($this);
$form->show();
}
/**
* Show the title of the page
*
* @return string title
*/
function title()
{
// TRANS: Page title for page on which a user account can be deleted.
return _('Delete account');
}
}
/**
* Form for deleting your account
*
* Note that this mostly is here to keep you from accidentally deleting your
* account.
*
* @category Account
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class DeleteAccountForm extends Form
{
/**
* Class of the form.
*
* @return string the form's class
*/
function formClass()
{
return 'form_profile_delete';
}
/**
* URL the form posts to
*
* @return string the form's action URL
*/
function action()
{
return common_local_url('deleteaccount');
}
/**
* Output form data
*
* Instructions plus an 'i am sure' entry box.
*
* @return void
*/
function formData()
{
$cur = common_current_user();
// TRANS: Form text for user deletion form.
$msg = '<p>' . _('This will <strong>permanently delete</strong> '.
'your account data from this server.') . '</p>';
if ($cur->hasRight(Right::BACKUPACCOUNT)) {
// TRANS: Additional form text for user deletion form shown if a user has account backup rights.
// TRANS: %s is a URL to the backup page.
$msg .= '<p>' . sprintf(_('You are strongly advised to '.
'<a href="%s">back up your data</a>'.
' before deletion.'),
common_local_url('backupaccount')) . '</p>';
}
$this->out->elementStart('p');
$this->out->raw($msg);
$this->out->elementEnd('p');
// !!! If this string is changed, it also needs to be changed in class DeleteaccountAction.
// TRANS: Confirmation text for user deletion. The user has to type this exactly the same, including punctuation.
$iamsure = _("I am sure.");
$this->out->input('iamsure',
// TRANS: Field label for delete account confirmation entry.
_('Confirm'),
null,
// TRANS: Input title for the delete account field.
// TRANS: %s is the text that needs to be input.
sprintf(_('Enter "%s" to confirm that '.
'you want to delete your account.'),$iamsure ));
}
/**
* Buttons for the form
*
* In this case, a single submit button
*
* @return void
*/
function formActions()
{
$this->out->submit('submit',
// TRANS: Button text for user account deletion.
_m('BUTTON', 'Delete'),
'submit',
null,
// TRANS: Button title for user account deletion.
_('Permanently delete your account'));
}
}

View File

@ -40,7 +40,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */
class DeleteapplicationAction extends Action class DeleteapplicationAction extends Action
{ {
var $app = null; var $app = null;
@ -52,7 +51,6 @@ class DeleteapplicationAction extends Action
* *
* @return boolean success flag * @return boolean success flag
*/ */
function prepare($args) function prepare($args)
{ {
if (!parent::prepare($args)) { if (!parent::prepare($args)) {
@ -60,6 +58,7 @@ class DeleteapplicationAction extends Action
} }
if (!common_logged_in()) { if (!common_logged_in()) {
// TRANS: Client error displayed trying to delete an application while not logged in.
$this->clientError(_('You must be logged in to delete an application.')); $this->clientError(_('You must be logged in to delete an application.'));
return false; return false;
} }
@ -68,6 +67,7 @@ class DeleteapplicationAction extends Action
$this->app = Oauth_application::staticGet('id', $id); $this->app = Oauth_application::staticGet('id', $id);
if (empty($this->app)) { if (empty($this->app)) {
// TRANS: Client error displayed trying to delete an application that does not exist.
$this->clientError(_('Application not found.')); $this->clientError(_('Application not found.'));
return false; return false;
} }
@ -75,6 +75,7 @@ class DeleteapplicationAction extends Action
$cur = common_current_user(); $cur = common_current_user();
if ($cur->id != $this->app->owner) { if ($cur->id != $this->app->owner) {
// TRANS: Client error displayed trying to delete an application the current user does not own.
$this->clientError(_('You are not the owner of this application.'), 401); $this->clientError(_('You are not the owner of this application.'), 401);
return false; return false;
} }
@ -91,7 +92,6 @@ class DeleteapplicationAction extends Action
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($_SERVER['REQUEST_METHOD'] == 'POST') {
@ -120,6 +120,7 @@ class DeleteapplicationAction extends Action
} }
function title() { function title() {
// TRANS: Title for delete application page.
return _('Delete application'); return _('Delete application');
} }
@ -144,8 +145,10 @@ class DeleteapplicationAction extends Action
array('id' => $this->app->id)))); array('id' => $this->app->id))));
$this->elementStart('fieldset'); $this->elementStart('fieldset');
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
// TRANS: Fieldset legend on delete application page.
$this->element('legend', _('Delete application')); $this->element('legend', _('Delete application'));
$this->element('p', null, $this->element('p', null,
// TRANS: Confirmation text on delete application page.
_('Are you sure you want to delete this application? '. _('Are you sure you want to delete this application? '.
'This will clear all data about the application from the '. 'This will clear all data about the application from the '.
'database, including all existing user connections.')); 'database, including all existing user connections.'));
@ -171,10 +174,8 @@ class DeleteapplicationAction extends Action
* *
* @return void * @return void
*/ */
function handlePost() function handlePost()
{ {
$this->app->delete(); $this->app->delete();
} }
} }

View File

@ -172,7 +172,7 @@ class DeletegroupAction extends RedirectingAction
} }
function title() { function title() {
// TRANS: Title. // TRANS: Title of delete group page.
return _('Delete group'); return _('Delete group');
} }
@ -201,8 +201,8 @@ class DeletegroupAction extends RedirectingAction
// TRANS: Form legend for deleting a group. // TRANS: Form legend for deleting a group.
$this->element('legend', _('Delete group')); $this->element('legend', _('Delete group'));
if (Event::handle('StartDeleteGroupForm', array($this, $this->group))) { if (Event::handle('StartDeleteGroupForm', array($this, $this->group))) {
// TRANS: Warning in form for deleleting a group.
$this->element('p', null, $this->element('p', null,
// TRANS: Warning in form for deleleting a group.
_('Are you sure you want to delete this group? '. _('Are you sure you want to delete this group? '.
'This will clear all data about the group from the '. 'This will clear all data about the group from the '.
'database, without a backup. ' . 'database, without a backup. ' .

View File

@ -32,6 +32,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1); exit(1);
} }
// @todo FIXME: documentation needed.
class DeletenoticeAction extends Action class DeletenoticeAction extends Action
{ {
var $error = null; var $error = null;
@ -47,6 +48,7 @@ class DeletenoticeAction extends Action
$this->user = common_current_user(); $this->user = common_current_user();
if (!$this->user) { if (!$this->user) {
// TRANS: Error message displayed trying to delete a notice while not logged in.
common_user_error(_('Not logged in.')); common_user_error(_('Not logged in.'));
exit; exit;
} }
@ -55,6 +57,7 @@ class DeletenoticeAction extends Action
$this->notice = Notice::staticGet($notice_id); $this->notice = Notice::staticGet($notice_id);
if (!$this->notice) { if (!$this->notice) {
// TRANS: Error message displayed trying to delete a non-existing notice.
common_user_error(_('No such notice.')); common_user_error(_('No such notice.'));
exit; exit;
} }
@ -71,7 +74,8 @@ class DeletenoticeAction extends Action
if ($this->notice->profile_id != $this->user_profile->id && if ($this->notice->profile_id != $this->user_profile->id &&
!$this->user->hasRight(Right::DELETEOTHERSNOTICE)) { !$this->user->hasRight(Right::DELETEOTHERSNOTICE)) {
common_user_error(_('Can\'t delete this notice.')); // TRANS: Error message displayed trying to delete a notice that was not made by the current user.
common_user_error(_('Cannot delete this notice.'));
exit; exit;
} }
// XXX: Ajax! // XXX: Ajax!
@ -90,7 +94,6 @@ class DeletenoticeAction extends Action
* *
* @return void * @return void
*/ */
function showPageNotice() function showPageNotice()
{ {
$instr = $this->getInstructions(); $instr = $this->getInstructions();
@ -103,12 +106,14 @@ class DeletenoticeAction extends Action
function getInstructions() function getInstructions()
{ {
// TRANS: Instructions for deleting a notice.
return _('You are about to permanently delete a notice. ' . return _('You are about to permanently delete a notice. ' .
'Once this is done, it cannot be undone.'); 'Once this is done, it cannot be undone.');
} }
function title() function title()
{ {
// TRANS: Page title when deleting a notice.
return _('Delete notice'); return _('Delete notice');
} }
@ -121,7 +126,6 @@ class DeletenoticeAction extends Action
* *
* @return void * @return void
*/ */
function showForm($error = null) function showForm($error = null)
{ {
$this->error = $error; $this->error = $error;
@ -133,7 +137,6 @@ class DeletenoticeAction extends Action
* *
* @return void * @return void
*/ */
function showContent() function showContent()
{ {
$this->elementStart('form', array('id' => 'form_notice_delete', $this->elementStart('form', array('id' => 'form_notice_delete',
@ -141,9 +144,11 @@ class DeletenoticeAction extends Action
'method' => 'post', 'method' => 'post',
'action' => common_local_url('deletenotice'))); 'action' => common_local_url('deletenotice')));
$this->elementStart('fieldset'); $this->elementStart('fieldset');
// TRANS: Fieldset legend for the delete notice form.
$this->element('legend', null, _('Delete notice')); $this->element('legend', null, _('Delete notice'));
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
$this->hidden('notice', $this->trimmed('notice')); $this->hidden('notice', $this->trimmed('notice'));
// TRANS: Message for the delete notice form.
$this->element('p', null, _('Are you sure you want to delete this notice?')); $this->element('p', null, _('Are you sure you want to delete this notice?'));
$this->submit('form_action-no', $this->submit('form_action-no',
// TRANS: Button label on the delete notice form. // TRANS: Button label on the delete notice form.

View File

@ -40,7 +40,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */
class DeleteuserAction extends ProfileFormAction class DeleteuserAction extends ProfileFormAction
{ {
var $user = null; var $user = null;
@ -52,7 +51,6 @@ class DeleteuserAction extends ProfileFormAction
* *
* @return boolean success flag * @return boolean success flag
*/ */
function prepare($args) function prepare($args)
{ {
if (!parent::prepare($args)) { if (!parent::prepare($args)) {
@ -64,6 +62,7 @@ class DeleteuserAction extends ProfileFormAction
assert(!empty($cur)); // checked by parent assert(!empty($cur)); // checked by parent
if (!$cur->hasRight(Right::DELETEUSER)) { if (!$cur->hasRight(Right::DELETEUSER)) {
// TRANS: Client error displayed when trying to delete a user without having the right to delete users.
$this->clientError(_('You cannot delete users.')); $this->clientError(_('You cannot delete users.'));
return false; return false;
} }
@ -71,6 +70,7 @@ class DeleteuserAction extends ProfileFormAction
$this->user = User::staticGet('id', $this->profile->id); $this->user = User::staticGet('id', $this->profile->id);
if (empty($this->user)) { if (empty($this->user)) {
// TRANS: Client error displayed when trying to delete a non-local user.
$this->clientError(_('You can only delete local users.')); $this->clientError(_('You can only delete local users.'));
return false; return false;
} }
@ -87,7 +87,6 @@ class DeleteuserAction extends ProfileFormAction
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($_SERVER['REQUEST_METHOD'] == 'POST') {
@ -107,7 +106,8 @@ class DeleteuserAction extends ProfileFormAction
} }
function title() { function title() {
return _('Delete user'); // TRANS: Title of delete user page.
return _m('TITLE','Delete user');
} }
function showNoticeForm() { function showNoticeForm() {
@ -130,9 +130,11 @@ class DeleteuserAction extends ProfileFormAction
'action' => common_local_url('deleteuser'))); 'action' => common_local_url('deleteuser')));
$this->elementStart('fieldset'); $this->elementStart('fieldset');
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
// TRANS: Fieldset legend on delete user page.
$this->element('legend', _('Delete user')); $this->element('legend', _('Delete user'));
if (Event::handle('StartDeleteUserForm', array($this, $this->user))) { if (Event::handle('StartDeleteUserForm', array($this, $this->user))) {
$this->element('p', null, $this->element('p', null,
// TRANS: Information text to request if a user is certain that the described action has to be performed.
_('Are you sure you want to delete this user? '. _('Are you sure you want to delete this user? '.
'This will clear all data about the user from the '. 'This will clear all data about the user from the '.
'database, without a backup.')); 'database, without a backup.'));
@ -153,7 +155,7 @@ class DeleteuserAction extends ProfileFormAction
'submit form_action-primary', 'submit form_action-primary',
'no', 'no',
// TRANS: Submit button title for 'No' when deleting a user. // TRANS: Submit button title for 'No' when deleting a user.
_('Do not block this user')); _('Do not delete this user'));
$this->submit('form_action-yes', $this->submit('form_action-yes',
// TRANS: Button label on the delete user form. // TRANS: Button label on the delete user form.
_m('BUTTON','Yes'), _m('BUTTON','Yes'),
@ -170,7 +172,6 @@ class DeleteuserAction extends ProfileFormAction
* *
* @return void * @return void
*/ */
function handlePost() function handlePost()
{ {
if (Event::handle('StartDeleteUser', array($this, $this->user))) { if (Event::handle('StartDeleteUser', array($this, $this->user))) {

View File

@ -44,10 +44,8 @@ if (!defined('STATUSNET')) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class DesignadminpanelAction extends AdminPanelAction class DesignadminpanelAction extends AdminPanelAction
{ {
/* The default site design */ /* The default site design */
var $design = null; var $design = null;
@ -56,7 +54,6 @@ class DesignadminpanelAction extends AdminPanelAction
* *
* @return string page title * @return string page title
*/ */
function title() function title()
{ {
// TRANS: Message used as title for design settings for the site. // TRANS: Message used as title for design settings for the site.
@ -68,9 +65,9 @@ class DesignadminpanelAction extends AdminPanelAction
* *
* @return string instructions * @return string instructions
*/ */
function getInstructions() function getInstructions()
{ {
// TRANS: Instructions for design adminsitration panel.
return _('Design settings for this StatusNet site'); return _('Design settings for this StatusNet site');
} }
@ -79,7 +76,6 @@ class DesignadminpanelAction extends AdminPanelAction
* *
* @return void * @return void
*/ */
function showForm() function showForm()
{ {
$this->design = Design::siteDesign(); $this->design = Design::siteDesign();
@ -93,7 +89,6 @@ class DesignadminpanelAction extends AdminPanelAction
* *
* @return void * @return void
*/ */
function saveSettings() function saveSettings()
{ {
if ($this->arg('save')) { if ($this->arg('save')) {
@ -101,6 +96,7 @@ class DesignadminpanelAction extends AdminPanelAction
} else if ($this->arg('defaults')) { } else if ($this->arg('defaults')) {
$this->restoreDefaults(); $this->restoreDefaults();
} else { } else {
// TRANS: Client error displayed when the submitted form contains unexpected data.
$this->clientError(_('Unexpected form submission.')); $this->clientError(_('Unexpected form submission.'));
} }
} }
@ -110,7 +106,6 @@ class DesignadminpanelAction extends AdminPanelAction
* *
* @return void * @return void
*/ */
function saveDesignSettings() function saveDesignSettings()
{ {
// Workaround for PHP returning empty $_POST and $_FILES when POST // Workaround for PHP returning empty $_POST and $_FILES when POST
@ -225,11 +220,10 @@ class DesignadminpanelAction extends AdminPanelAction
} }
/** /**
* Restore the default design * Restore the default design
* *
* @return void * @return void
*/ */
function restoreDefaults() function restoreDefaults()
{ {
$this->deleteSetting('site', 'logo'); $this->deleteSetting('site', 'logo');
@ -257,7 +251,6 @@ class DesignadminpanelAction extends AdminPanelAction
* *
* @return string $filename the filename of the image * @return string $filename the filename of the image
*/ */
function saveBackgroundImage() function saveBackgroundImage()
{ {
$filename = null; $filename = null;
@ -302,7 +295,6 @@ class DesignadminpanelAction extends AdminPanelAction
* @throws ClientException for invalid theme archives * @throws ClientException for invalid theme archives
* @throws ServerException if trouble saving the theme files * @throws ServerException if trouble saving the theme files
*/ */
function saveCustomTheme() function saveCustomTheme()
{ {
if (common_config('theme_upload', 'enabled') && if (common_config('theme_upload', 'enabled') &&
@ -327,20 +319,23 @@ class DesignadminpanelAction extends AdminPanelAction
* *
* @return void * @return void
*/ */
function validate(&$values) function validate(&$values)
{ {
if (!empty($values['logo']) && if (!empty($values['logo']) &&
!Validate::uri($values['logo'], array('allowed_schemes' => array('http', 'https')))) { !Validate::uri($values['logo'], array('allowed_schemes' => array('http', 'https')))) {
// TRANS: Client error displayed when a logo URL does is not valid.
$this->clientError(_('Invalid logo URL.')); $this->clientError(_('Invalid logo URL.'));
} }
if (!empty($values['ssllogo']) && if (!empty($values['ssllogo']) &&
!Validate::uri($values['ssllogo'], array('allowed_schemes' => array('https')))) { !Validate::uri($values['ssllogo'], array('allowed_schemes' => array('https')))) {
// TRANS: Client error displayed when an SSL logo URL is invalid.
$this->clientError(_('Invalid SSL logo URL.')); $this->clientError(_('Invalid SSL logo URL.'));
} }
if (!in_array($values['theme'], Theme::listAvailable())) { if (!in_array($values['theme'], Theme::listAvailable())) {
// TRANS: Client error displayed when a theme is submitted through the form that is not in the theme list.
// TRANS: %s is the chosen unavailable theme.
$this->clientError(sprintf(_("Theme not available: %s."), $values['theme'])); $this->clientError(sprintf(_("Theme not available: %s."), $values['theme']));
} }
} }
@ -350,7 +345,6 @@ class DesignadminpanelAction extends AdminPanelAction
* *
* @return void * @return void
*/ */
function showStylesheets() function showStylesheets()
{ {
parent::showStylesheets(); parent::showStylesheets();
@ -362,7 +356,6 @@ class DesignadminpanelAction extends AdminPanelAction
* *
* @return void * @return void
*/ */
function showScripts() function showScripts()
{ {
parent::showScripts(); parent::showScripts();
@ -383,7 +376,6 @@ class DesignAdminPanelForm extends AdminForm
* *
* @return int ID of the form * @return int ID of the form
*/ */
function id() function id()
{ {
return 'form_design_admin_panel'; return 'form_design_admin_panel';
@ -394,7 +386,6 @@ class DesignAdminPanelForm extends AdminForm
* *
* @return string class of the form * @return string class of the form
*/ */
function formClass() function formClass()
{ {
return 'form_settings'; return 'form_settings';
@ -408,7 +399,6 @@ class DesignAdminPanelForm extends AdminForm
* *
* @return string the method to use for submitting * @return string the method to use for submitting
*/ */
function method() function method()
{ {
$this->enctype = 'multipart/form-data'; $this->enctype = 'multipart/form-data';
@ -421,7 +411,6 @@ class DesignAdminPanelForm extends AdminForm
* *
* @return string URL of the action * @return string URL of the action
*/ */
function action() function action()
{ {
return common_local_url('designadminpanel'); return common_local_url('designadminpanel');
@ -432,7 +421,6 @@ class DesignAdminPanelForm extends AdminForm
* *
* @return void * @return void
*/ */
function formData() function formData()
{ {
$this->showLogo(); $this->showLogo();
@ -445,16 +433,25 @@ class DesignAdminPanelForm extends AdminForm
function showLogo() function showLogo()
{ {
$this->out->elementStart('fieldset', array('id' => 'settings_design_logo')); $this->out->elementStart('fieldset', array('id' => 'settings_design_logo'));
// TRANS: Fieldset legend for form to change logo.
$this->out->element('legend', null, _('Change logo')); $this->out->element('legend', null, _('Change logo'));
$this->out->elementStart('ul', 'form_data'); $this->out->elementStart('ul', 'form_data');
$this->li(); $this->li();
$this->input('logo', _('Site logo'), 'Logo for the site (full URL)'); $this->input('logo',
// TRANS: Field label for StatusNet site logo.
_('Site logo'),
// TRANS: Title for field label for StatusNet site logo.
'Logo for the site (full URL)');
$this->unli(); $this->unli();
$this->li(); $this->li();
$this->input('ssllogo', _('SSL logo'), 'Logo to show on SSL pages'); $this->input('ssllogo',
// TRANS: Field label for SSL StatusNet site logo.
_('SSL logo'),
// TRANS: Title for field label for SSL StatusNet site logo.
'Logo to show on SSL pages');
$this->unli(); $this->unli();
$this->out->elementEnd('ul'); $this->out->elementEnd('ul');
@ -466,6 +463,7 @@ class DesignAdminPanelForm extends AdminForm
function showTheme() function showTheme()
{ {
$this->out->elementStart('fieldset', array('id' => 'settings_design_theme')); $this->out->elementStart('fieldset', array('id' => 'settings_design_theme'));
// TRANS: Fieldset legend for form change StatusNet site's theme.
$this->out->element('legend', null, _('Change theme')); $this->out->element('legend', null, _('Change theme'));
$this->out->elementStart('ul', 'form_data'); $this->out->elementStart('ul', 'form_data');
@ -483,17 +481,21 @@ class DesignAdminPanelForm extends AdminForm
$themes = array_combine($themes, $themes); $themes = array_combine($themes, $themes);
$this->li(); $this->li();
// TRANS: Field label for dropdown to choose site theme.
$this->out->dropdown('theme', _('Site theme'), $this->out->dropdown('theme', _('Site theme'),
// TRANS: Title for field label for dropdown to choose site theme.
$themes, _('Theme for the site.'), $themes, _('Theme for the site.'),
false, $this->value('theme')); false, $this->value('theme'));
$this->unli(); $this->unli();
if (common_config('theme_upload', 'enabled')) { if (common_config('theme_upload', 'enabled')) {
$this->li(); $this->li();
// TRANS: Field label for uploading a cutom theme.
$this->out->element('label', array('for' => 'design_upload_theme'), _('Custom theme')); $this->out->element('label', array('for' => 'design_upload_theme'), _('Custom theme'));
$this->out->element('input', array('id' => 'design_upload_theme', $this->out->element('input', array('id' => 'design_upload_theme',
'name' => 'design_upload_theme', 'name' => 'design_upload_theme',
'type' => 'file')); 'type' => 'file'));
// TRANS: Form instructions for uploading a cutom StatusNet theme.
$this->out->element('p', 'form_guide', _('You can upload a custom StatusNet theme as a .ZIP archive.')); $this->out->element('p', 'form_guide', _('You can upload a custom StatusNet theme as a .ZIP archive.'));
$this->unli(); $this->unli();
} }
@ -509,22 +511,25 @@ class DesignAdminPanelForm extends AdminForm
$this->out->elementStart('fieldset', array('id' => $this->out->elementStart('fieldset', array('id' =>
'settings_design_background-image')); 'settings_design_background-image'));
// TRANS: Fieldset legend for theme background image.
$this->out->element('legend', null, _('Change background image')); $this->out->element('legend', null, _('Change background image'));
$this->out->elementStart('ul', 'form_data'); $this->out->elementStart('ul', 'form_data');
$this->li(); $this->li();
$this->out->element('input', array('name' => 'MAX_FILE_SIZE',
'type' => 'hidden',
'id' => 'MAX_FILE_SIZE',
'value' => ImageFile::maxFileSizeInt()));
$this->out->element('label', array('for' => 'design_background-image_file'), $this->out->element('label', array('for' => 'design_background-image_file'),
// TRANS: Field label for background image on theme designer page.
_('Background')); _('Background'));
$this->out->element('input', array('name' => 'design_background-image_file', $this->out->element('input', array('name' => 'design_background-image_file',
'type' => 'file', 'type' => 'file',
'id' => 'design_background-image_file')); 'id' => 'design_background-image_file'));
$this->out->element('p', 'form_guide', $this->out->element('p', 'form_guide',
// TRANS: Form guide for background image upload form on theme designer page.
sprintf(_('You can upload a background image for the site. ' . sprintf(_('You can upload a background image for the site. ' .
'The maximum file size is %1$s.'), ImageFile::maxFileSize())); 'The maximum file size is %1$s.'), ImageFile::maxFileSize()));
$this->out->element('input', array('name' => 'MAX_FILE_SIZE',
'type' => 'hidden',
'id' => 'MAX_FILE_SIZE',
'value' => ImageFile::maxFileSizeInt()));
$this->unli(); $this->unli();
if (!empty($design->backgroundimage)) { if (!empty($design->backgroundimage)) {
@ -568,11 +573,13 @@ class DesignAdminPanelForm extends AdminForm
'class' => 'radio'), 'class' => 'radio'),
// TRANS: Used as radio button label to not add a background image. // TRANS: Used as radio button label to not add a background image.
_('Off')); _('Off'));
// TRANS: Form guide for turning background image on or off on theme designer page.
$this->out->element('p', 'form_guide', _('Turn background image on or off.')); $this->out->element('p', 'form_guide', _('Turn background image on or off.'));
$this->unli(); $this->unli();
$this->li(); $this->li();
$this->out->checkbox('design_background-image_repeat', $this->out->checkbox('design_background-image_repeat',
// TRANS: Checkbox label to title background image on theme designer page.
_('Tile background image'), _('Tile background image'),
($design->disposition & BACKGROUND_TILE) ? true : false); ($design->disposition & BACKGROUND_TILE) ? true : false);
$this->unli(); $this->unli();
@ -587,7 +594,8 @@ class DesignAdminPanelForm extends AdminForm
$design = $this->out->design; $design = $this->out->design;
$this->out->elementStart('fieldset', array('id' => 'settings_design_color')); $this->out->elementStart('fieldset', array('id' => 'settings_design_color'));
$this->out->element('legend', null, _('Change colours')); // TRANS: Fieldset legend for theme colors.
$this->out->element('legend', null, _('Change colors'));
$this->out->elementStart('ul', 'form_data'); $this->out->elementStart('ul', 'form_data');
@ -597,6 +605,7 @@ class DesignAdminPanelForm extends AdminForm
$bgcolor = new WebColor($design->backgroundcolor); $bgcolor = new WebColor($design->backgroundcolor);
$this->li(); $this->li();
// TRANS: Field label for background color selector.
$this->out->element('label', array('for' => 'swatch-1'), _('Background')); $this->out->element('label', array('for' => 'swatch-1'), _('Background'));
$this->out->element('input', array('name' => 'design_background', $this->out->element('input', array('name' => 'design_background',
'type' => 'text', 'type' => 'text',
@ -610,6 +619,7 @@ class DesignAdminPanelForm extends AdminForm
$ccolor = new WebColor($design->contentcolor); $ccolor = new WebColor($design->contentcolor);
$this->li(); $this->li();
// TRANS: Field label for content color selector.
$this->out->element('label', array('for' => 'swatch-2'), _('Content')); $this->out->element('label', array('for' => 'swatch-2'), _('Content'));
$this->out->element('input', array('name' => 'design_content', $this->out->element('input', array('name' => 'design_content',
'type' => 'text', 'type' => 'text',
@ -623,6 +633,7 @@ class DesignAdminPanelForm extends AdminForm
$sbcolor = new WebColor($design->sidebarcolor); $sbcolor = new WebColor($design->sidebarcolor);
$this->li(); $this->li();
// TRANS: Field label for sidebar color selector.
$this->out->element('label', array('for' => 'swatch-3'), _('Sidebar')); $this->out->element('label', array('for' => 'swatch-3'), _('Sidebar'));
$this->out->element('input', array('name' => 'design_sidebar', $this->out->element('input', array('name' => 'design_sidebar',
'type' => 'text', 'type' => 'text',
@ -636,6 +647,7 @@ class DesignAdminPanelForm extends AdminForm
$tcolor = new WebColor($design->textcolor); $tcolor = new WebColor($design->textcolor);
$this->li(); $this->li();
// TRANS: Field label for text color selector.
$this->out->element('label', array('for' => 'swatch-4'), _('Text')); $this->out->element('label', array('for' => 'swatch-4'), _('Text'));
$this->out->element('input', array('name' => 'design_text', $this->out->element('input', array('name' => 'design_text',
'type' => 'text', 'type' => 'text',
@ -649,6 +661,7 @@ class DesignAdminPanelForm extends AdminForm
$lcolor = new WebColor($design->linkcolor); $lcolor = new WebColor($design->linkcolor);
$this->li(); $this->li();
// TRANS: Field label for link color selector.
$this->out->element('label', array('for' => 'swatch-5'), _('Links')); $this->out->element('label', array('for' => 'swatch-5'), _('Links'));
$this->out->element('input', array('name' => 'design_links', $this->out->element('input', array('name' => 'design_links',
'type' => 'text', 'type' => 'text',
@ -674,10 +687,12 @@ class DesignAdminPanelForm extends AdminForm
{ {
if (common_config('custom_css', 'enabled')) { if (common_config('custom_css', 'enabled')) {
$this->out->elementStart('fieldset', array('id' => 'settings_design_advanced')); $this->out->elementStart('fieldset', array('id' => 'settings_design_advanced'));
// TRANS: Fieldset legend for advanced theme design settings.
$this->out->element('legend', null, _('Advanced')); $this->out->element('legend', null, _('Advanced'));
$this->out->elementStart('ul', 'form_data'); $this->out->elementStart('ul', 'form_data');
$this->li(); $this->li();
// TRANS: Field label for custom CSS.
$this->out->element('label', array('for' => 'css'), _('Custom CSS')); $this->out->element('label', array('for' => 'css'), _('Custom CSS'));
$this->out->element('textarea', array('name' => 'css', $this->out->element('textarea', array('name' => 'css',
'id' => 'css', 'id' => 'css',
@ -699,17 +714,25 @@ class DesignAdminPanelForm extends AdminForm
function formActions() function formActions()
{ {
$this->out->submit('defaults', _('Use defaults'), 'submit form_action-default', // TRANS: Button text for resetting theme settings.
$this->out->submit('defaults', _m('BUTTON','Use defaults'), 'submit form_action-default',
// TRANS: Title for button for resetting theme settings.
'defaults', _('Restore default designs')); 'defaults', _('Restore default designs'));
$this->out->element('input', array('id' => 'settings_design_reset', $this->out->element('input', array('id' => 'settings_design_reset',
'type' => 'reset', 'type' => 'reset',
// TRANS: Button text for resetting theme settings.
'value' => 'Reset', 'value' => 'Reset',
'class' => 'submit form_action-primary', 'class' => 'submit form_action-primary',
// TRANS: Title for button for resetting theme settings.
'title' => _('Reset back to default'))); 'title' => _('Reset back to default')));
$this->out->submit('save', _('Save'), 'submit form_action-secondary', $this->out->submit('save',
'save', _('Save design')); // TRANS: Button text for saving theme settings.
_m('BUTTON','Save'),
'submit form_action-secondary',
'save',
// TRANS: Title for button for saving theme settings.
_('Save design'));
} }
} }

View File

@ -1,5 +1,4 @@
<?php <?php
/** /**
* Disfavor action. * Disfavor action.
* *
@ -58,6 +57,7 @@ class DisfavorAction extends Action
{ {
parent::handle($args); parent::handle($args);
if (!common_logged_in()) { if (!common_logged_in()) {
// TRANS: Client error displayed when trying to remove a favorite while not logged in.
$this->clientError(_('Not logged in.')); $this->clientError(_('Not logged in.'));
return; return;
} }
@ -71,6 +71,7 @@ class DisfavorAction extends Action
$notice = Notice::staticGet($id); $notice = Notice::staticGet($id);
$token = $this->trimmed('token-'.$notice->id); $token = $this->trimmed('token-'.$notice->id);
if (!$token || $token != common_session_token()) { if (!$token || $token != common_session_token()) {
// TRANS: Client error displayed when the session token does not match or is not given.
$this->clientError(_('There was a problem with your session token. Try again, please.')); $this->clientError(_('There was a problem with your session token. Try again, please.'));
return; return;
} }
@ -78,12 +79,14 @@ class DisfavorAction extends Action
$fave->user_id = $user->id; $fave->user_id = $user->id;
$fave->notice_id = $notice->id; $fave->notice_id = $notice->id;
if (!$fave->find(true)) { if (!$fave->find(true)) {
// TRANS: Client error displayed when trying to remove favorite status for a notice that is not a favorite.
$this->clientError(_('This notice is not a favorite!')); $this->clientError(_('This notice is not a favorite!'));
return; return;
} }
$result = $fave->delete(); $result = $fave->delete();
if (!$result) { if (!$result) {
common_log_db_error($fave, 'DELETE', __FILE__); common_log_db_error($fave, 'DELETE', __FILE__);
// TRANS: Server error displayed when removing a favorite from the database fails.
$this->serverError(_('Could not delete favorite.')); $this->serverError(_('Could not delete favorite.'));
return; return;
} }
@ -91,6 +94,7 @@ class DisfavorAction extends Action
if ($this->boolean('ajax')) { if ($this->boolean('ajax')) {
$this->startHTML('text/xml;charset=utf-8'); $this->startHTML('text/xml;charset=utf-8');
$this->elementStart('head'); $this->elementStart('head');
// TRANS: Title for page on which favorites can be added.
$this->element('title', null, _('Add to favorites')); $this->element('title', null, _('Add to favorites'));
$this->elementEnd('head'); $this->elementEnd('head');
$this->elementStart('body'); $this->elementStart('body');
@ -105,4 +109,3 @@ class DisfavorAction extends Action
} }
} }
} }

View File

@ -1,5 +1,4 @@
<?php <?php
/** /**
* Documentation action. * Documentation action.
* *
@ -83,7 +82,6 @@ class DocAction extends Action
* *
* @return void * @return void
*/ */
function showPageTitle() function showPageTitle()
{ {
$this->element('h1', array('class' => 'entry-title'), $this->title()); $this->element('h1', array('class' => 'entry-title'), $this->title());
@ -96,7 +94,6 @@ class DocAction extends Action
* *
* @return void. * @return void.
*/ */
function showContentBlock() function showContentBlock()
{ {
$this->elementStart('div', array('id' => 'content', 'class' => 'hentry')); $this->elementStart('div', array('id' => 'content', 'class' => 'hentry'));
@ -117,7 +114,6 @@ class DocAction extends Action
* *
* @return void * @return void
*/ */
function showContent() function showContent()
{ {
$this->raw($this->output); $this->raw($this->output);
@ -142,7 +138,6 @@ class DocAction extends Action
* *
* @return boolean read-only flag (false) * @return boolean read-only flag (false)
*/ */
function isReadOnly($args) function isReadOnly($args)
{ {
return true; return true;
@ -155,7 +150,9 @@ class DocAction extends Action
$this->filename = $this->getFilename(); $this->filename = $this->getFilename();
if (empty($this->filename)) { if (empty($this->filename)) {
throw new ClientException(sprintf(_('No such document "%s"'), $this->title), 404); // TRANS: Client exception thrown when requesting a document from the documentation that does not exist.
// TRANS: %s is the non-existing document.
throw new ClientException(sprintf(_('No such document "%s".'), $this->title), 404);
} }
$c = file_get_contents($this->filename); $c = file_get_contents($this->filename);

View File

@ -185,7 +185,7 @@ class EditApplicationAction extends OwnerDesignAction
return; return;
} elseif (mb_strlen($name) > 255) { } elseif (mb_strlen($name) > 255) {
// TRANS: Validation error shown when providing too long a name in the "Edit application" form. // TRANS: Validation error shown when providing too long a name in the "Edit application" form.
$this->showForm(_('Name is too long (max 255 characters).')); $this->showForm(_('Name is too long (maximum 255 characters).'));
return; return;
} else if ($this->nameExists($name)) { } else if ($this->nameExists($name)) {
// TRANS: Validation error shown when providing a name for an application that already exists in the "Edit application" form. // TRANS: Validation error shown when providing a name for an application that already exists in the "Edit application" form.
@ -198,6 +198,7 @@ class EditApplicationAction extends OwnerDesignAction
} elseif (Oauth_application::descriptionTooLong($description)) { } elseif (Oauth_application::descriptionTooLong($description)) {
$this->showForm(sprintf( $this->showForm(sprintf(
// TRANS: Validation error shown when providing too long a description in the "Edit application" form. // TRANS: Validation error shown when providing too long a description in the "Edit application" form.
// TRANS: %d is the maximum number of allowed characters.
_m('Description is too long (maximum %d character).', _m('Description is too long (maximum %d character).',
'Description is too long (maximum %d characters).', 'Description is too long (maximum %d characters).',
Oauth_application::maxDesc()), Oauth_application::maxDesc()),
@ -223,6 +224,7 @@ class EditApplicationAction extends OwnerDesignAction
$this->showForm(_('Organization is too long (maximum 255 characters).')); $this->showForm(_('Organization is too long (maximum 255 characters).'));
return; return;
} elseif (empty($homepage)) { } elseif (empty($homepage)) {
// TRANS: Form validation error show when an organisation name has not been provided in the edit application form.
$this->showForm(_('Organization homepage is required.')); $this->showForm(_('Organization homepage is required.'));
return; return;
} elseif ((mb_strlen($homepage) > 0) } elseif ((mb_strlen($homepage) > 0)

View File

@ -45,14 +45,13 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class EditgroupAction extends GroupDesignAction class EditgroupAction extends GroupDesignAction
{ {
var $msg; var $msg;
function title() function title()
{ {
// TRANS: Title for form to edit a group. %s is a group nickname.
return sprintf(_('Edit %s group'), $this->group->nickname); return sprintf(_('Edit %s group'), $this->group->nickname);
} }
@ -65,6 +64,7 @@ class EditgroupAction extends GroupDesignAction
parent::prepare($args); parent::prepare($args);
if (!common_logged_in()) { if (!common_logged_in()) {
// TRANS: Client error displayed trying to edit a group while not logged in.
$this->clientError(_('You must be logged in to create a group.')); $this->clientError(_('You must be logged in to create a group.'));
return false; return false;
} }
@ -81,6 +81,7 @@ class EditgroupAction extends GroupDesignAction
} }
if (!$nickname) { if (!$nickname) {
// TRANS: Client error displayed trying to edit a group while not proving a nickname for the group to edit.
$this->clientError(_('No nickname.'), 404); $this->clientError(_('No nickname.'), 404);
return false; return false;
} }
@ -97,6 +98,7 @@ class EditgroupAction extends GroupDesignAction
} }
if (!$this->group) { if (!$this->group) {
// TRANS: Client error displayed trying to edit a non-existing group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -104,6 +106,7 @@ class EditgroupAction extends GroupDesignAction
$cur = common_current_user(); $cur = common_current_user();
if (!$cur->isAdmin($this->group)) { if (!$cur->isAdmin($this->group)) {
// TRANS: Client error displayed trying to edit a group while not being a group admin.
$this->clientError(_('You must be an admin to edit the group.'), 403); $this->clientError(_('You must be an admin to edit the group.'), 403);
return false; return false;
} }
@ -120,7 +123,6 @@ class EditgroupAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
@ -155,6 +157,7 @@ class EditgroupAction extends GroupDesignAction
$this->element('p', 'error', $this->msg); $this->element('p', 'error', $this->msg);
} else { } else {
$this->element('p', 'instructions', $this->element('p', 'instructions',
// TRANS: Form instructions for group edit form.
_('Use this form to edit the group.')); _('Use this form to edit the group.'));
} }
} }
@ -169,114 +172,132 @@ class EditgroupAction extends GroupDesignAction
{ {
$cur = common_current_user(); $cur = common_current_user();
if (!$cur->isAdmin($this->group)) { if (!$cur->isAdmin($this->group)) {
// TRANS: Client error displayed trying to edit a group while not being a group admin.
$this->clientError(_('You must be an admin to edit the group.'), 403); $this->clientError(_('You must be an admin to edit the group.'), 403);
return; return;
} }
$nickname = common_canonical_nickname($this->trimmed('nickname')); if (Event::handle('StartGroupSaveForm', array($this))) {
$fullname = $this->trimmed('fullname');
$homepage = $this->trimmed('homepage');
$description = $this->trimmed('description');
$location = $this->trimmed('location');
$aliasstring = $this->trimmed('aliases');
if (!Validate::string($nickname, array('min_length' => 1, $nickname = Nickname::normalize($this->trimmed('nickname'));
'max_length' => 64, $fullname = $this->trimmed('fullname');
'format' => NICKNAME_FMT))) { $homepage = $this->trimmed('homepage');
$this->showForm(_('Nickname must have only lowercase letters '. $description = $this->trimmed('description');
'and numbers and no spaces.')); $location = $this->trimmed('location');
return; $aliasstring = $this->trimmed('aliases');
} else if ($this->nicknameExists($nickname)) {
$this->showForm(_('Nickname already in use. Try another one.'));
return;
} else if (!User_group::allowedNickname($nickname)) {
$this->showForm(_('Not a valid nickname.'));
return;
} else if (!is_null($homepage) && (strlen($homepage) > 0) &&
!Validate::uri($homepage,
array('allowed_schemes' =>
array('http', 'https')))) {
$this->showForm(_('Homepage is not a valid URL.'));
return;
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
$this->showForm(_('Full name is too long (maximum 255 characters).'));
return;
} else if (User_group::descriptionTooLong($description)) {
$this->showForm(sprintf(_('Description is too long (max %d chars).'), User_group::maxDescription()));
return;
} else if (!is_null($location) && mb_strlen($location) > 255) {
$this->showForm(_('Location is too long (maximum 255 characters).'));
return;
}
if (!empty($aliasstring)) { if ($this->nicknameExists($nickname)) {
$aliases = array_map('common_canonical_nickname', array_unique(preg_split('/[\s,]+/', $aliasstring))); // TRANS: Group edit form validation error.
} else { $this->showForm(_('Nickname already in use. Try another one.'));
$aliases = array(); return;
} } else if (!User_group::allowedNickname($nickname)) {
// TRANS: Group edit form validation error.
if (count($aliases) > common_config('group', 'maxaliases')) { $this->showForm(_('Not a valid nickname.'));
$this->showForm(sprintf(_('Too many aliases! Maximum %d.'), return;
common_config('group', 'maxaliases'))); } else if (!is_null($homepage) && (strlen($homepage) > 0) &&
return; !Validate::uri($homepage,
} array('allowed_schemes' =>
array('http', 'https')))) {
foreach ($aliases as $alias) { // TRANS: Group edit form validation error.
if (!Validate::string($alias, array('min_length' => 1, $this->showForm(_('Homepage is not a valid URL.'));
'max_length' => 64, return;
'format' => NICKNAME_FMT))) { } else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
$this->showForm(sprintf(_('Invalid alias: "%s"'), $alias)); // TRANS: Group edit form validation error.
$this->showForm(_('Full name is too long (maximum 255 characters).'));
return;
} else if (User_group::descriptionTooLong($description)) {
$this->showForm(sprintf(
// TRANS: Group edit form validation error.
_m('Description is too long (maximum %d character).',
'Description is too long (maximum %d characters).',
User_group::maxDescription()),
User_group::maxDescription()));
return;
} else if (!is_null($location) && mb_strlen($location) > 255) {
// TRANS: Group edit form validation error.
$this->showForm(_('Location is too long (maximum 255 characters).'));
return; return;
} }
if ($this->nicknameExists($alias)) {
$this->showForm(sprintf(_('Alias "%s" already in use. Try another one.'), if (!empty($aliasstring)) {
$alias)); $aliases = array_map('common_canonical_nickname', array_unique(preg_split('/[\s,]+/', $aliasstring)));
} else {
$aliases = array();
}
if (count($aliases) > common_config('group', 'maxaliases')) {
// TRANS: Group edit form validation error.
// TRANS: %d is the maximum number of allowed aliases.
$this->showForm(sprintf(_m('Too many aliases! Maximum %d allowed.',
'Too many aliases! Maximum %d allowed.',
common_config('group', 'maxaliases')),
common_config('group', 'maxaliases')));
return; return;
} }
// XXX assumes alphanum nicknames
if (strcmp($alias, $nickname) == 0) { foreach ($aliases as $alias) {
$this->showForm(_('Alias can\'t be the same as nickname.')); if (!Nickname::isValid($alias)) {
return; // TRANS: Group edit form validation error.
$this->showForm(sprintf(_('Invalid alias: "%s"'), $alias));
return;
}
if ($this->nicknameExists($alias)) {
// TRANS: Group edit form validation error.
$this->showForm(sprintf(_('Alias "%s" already in use. Try another one.'),
$alias));
return;
}
// XXX assumes alphanum nicknames
if (strcmp($alias, $nickname) == 0) {
// TRANS: Group edit form validation error.
$this->showForm(_('Alias can\'t be the same as nickname.'));
return;
}
} }
$this->group->query('BEGIN');
$orig = clone($this->group);
$this->group->nickname = $nickname;
$this->group->fullname = $fullname;
$this->group->homepage = $homepage;
$this->group->description = $description;
$this->group->location = $location;
$this->group->mainpage = common_local_url('showgroup', array('nickname' => $nickname));
$result = $this->group->update($orig);
if (!$result) {
common_log_db_error($this->group, 'UPDATE', __FILE__);
// TRANS: Server error displayed when editing a group fails.
$this->serverError(_('Could not update group.'));
}
$result = $this->group->setAliases($aliases);
if (!$result) {
// TRANS: Server error displayed when group aliases could not be added.
$this->serverError(_('Could not create aliases.'));
}
if ($nickname != $orig->nickname) {
common_log(LOG_INFO, "Saving local group info.");
$local = Local_group::staticGet('group_id', $this->group->id);
$local->setNickname($nickname);
}
$this->group->query('COMMIT');
Event::handle('EndGroupSaveForm', array($this));
} }
$this->group->query('BEGIN');
$orig = clone($this->group);
$this->group->nickname = $nickname;
$this->group->fullname = $fullname;
$this->group->homepage = $homepage;
$this->group->description = $description;
$this->group->location = $location;
$this->group->mainpage = common_local_url('showgroup', array('nickname' => $nickname));
$result = $this->group->update($orig);
if (!$result) {
common_log_db_error($this->group, 'UPDATE', __FILE__);
$this->serverError(_('Could not update group.'));
}
$result = $this->group->setAliases($aliases);
if (!$result) {
$this->serverError(_('Could not create aliases.'));
}
if ($nickname != $orig->nickname) {
common_log(LOG_INFO, "Saving local group info.");
$local = Local_group::staticGet('group_id', $this->group->id);
$local->setNickname($nickname);
}
$this->group->query('COMMIT');
if ($this->group->nickname != $orig->nickname) { if ($this->group->nickname != $orig->nickname) {
common_redirect(common_local_url('editgroup', common_redirect(common_local_url('editgroup',
array('nickname' => $nickname)), array('nickname' => $nickname)),
303); 303);
} else { } else {
// TRANS: Group edit form success message.
$this->showForm(_('Options saved.')); $this->showForm(_('Options saved.'));
} }
} }
@ -300,4 +321,3 @@ class EditgroupAction extends GroupDesignAction
return false; return false;
} }
} }

View File

@ -46,7 +46,6 @@ require_once INSTALLDIR.'/lib/accountsettingsaction.php';
* *
* @see Widget * @see Widget
*/ */
class EmailsettingsAction extends AccountSettingsAction class EmailsettingsAction extends AccountSettingsAction
{ {
/** /**
@ -54,7 +53,6 @@ class EmailsettingsAction extends AccountSettingsAction
* *
* @return string Title of the page * @return string Title of the page
*/ */
function title() function title()
{ {
// TRANS: Title for e-mail settings. // TRANS: Title for e-mail settings.
@ -66,7 +64,6 @@ class EmailsettingsAction extends AccountSettingsAction
* *
* @return instructions for use * @return instructions for use
*/ */
function getInstructions() function getInstructions()
{ {
// XXX: For consistency of parameters in messages, this should be a // XXX: For consistency of parameters in messages, this should be a
@ -79,6 +76,7 @@ class EmailsettingsAction extends AccountSettingsAction
function showScripts() function showScripts()
{ {
parent::showScripts(); parent::showScripts();
$this->script('emailsettings.js');
$this->autofocus('email'); $this->autofocus('email');
} }
@ -90,7 +88,6 @@ class EmailsettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function showContent() function showContent()
{ {
$user = common_current_user(); $user = common_current_user();
@ -117,8 +114,8 @@ class EmailsettingsAction extends AccountSettingsAction
$confirm = $this->getConfirmation(); $confirm = $this->getConfirmation();
if ($confirm) { if ($confirm) {
$this->element('p', array('id' => 'form_unconfirmed'), $confirm->address); $this->element('p', array('id' => 'form_unconfirmed'), $confirm->address);
// TRANS: Form note in e-mail settings form.
$this->element('p', array('class' => 'form_note'), $this->element('p', array('class' => 'form_note'),
// TRANS: Form note in e-mail settings form.
_('Awaiting confirmation on this address. '. _('Awaiting confirmation on this address. '.
'Check your inbox (and spam box!) for a message '. 'Check your inbox (and spam box!) for a message '.
'with further instructions.')); 'with further instructions.'));
@ -149,10 +146,30 @@ class EmailsettingsAction extends AccountSettingsAction
$this->elementStart('fieldset', array('id' => 'settings_email_incoming')); $this->elementStart('fieldset', array('id' => 'settings_email_incoming'));
// TRANS: Form legend for incoming e-mail settings form. // TRANS: Form legend for incoming e-mail settings form.
$this->element('legend', null, _('Incoming email')); $this->element('legend', null, _('Incoming email'));
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
$this->checkbox('emailpost',
// TRANS: Checkbox label in e-mail preferences form.
_('I want to post notices by email.'),
$user->emailpost);
$this->elementEnd('li');
$this->elementEnd('ul');
// Our stylesheets make the form_data list items all floats, which
// creates lots of problems with trying to wrap divs around things.
// This should force a break before the next section, which needs
// to be separate so we can disable the things in it when the
// checkbox is off.
$this->elementStart('div', array('style' => 'clear: both'));
$this->elementEnd('div');
$this->elementStart('div', array('id' => 'emailincoming'));
if ($user->incomingemail) { if ($user->incomingemail) {
$this->elementStart('p'); $this->elementStart('p');
$this->element('span', 'address', $user->incomingemail); $this->element('span', 'address', $user->incomingemail);
// XXX: Looks a little awkward in the UI. // @todo XXX: Looks a little awkward in the UI.
// Something like "xxxx@identi.ca Send email ..". Needs improvement. // Something like "xxxx@identi.ca Send email ..". Needs improvement.
$this->element('span', 'input_instructions', $this->element('span', 'input_instructions',
// TRANS: Form instructions for incoming e-mail form in e-mail settings. // TRANS: Form instructions for incoming e-mail form in e-mail settings.
@ -163,13 +180,22 @@ class EmailsettingsAction extends AccountSettingsAction
} }
$this->elementStart('p'); $this->elementStart('p');
$this->element('span', 'input_instructions', if ($user->incomingemail) {
// TRANS: Instructions for incoming e-mail address input form. // TRANS: Instructions for incoming e-mail address input form, when an address has already been assigned.
_('Make a new email address for posting to; '. $msg = _('Make a new email address for posting to; '.
'cancels the old one.')); 'cancels the old one.');
} else {
// TRANS: Instructions for incoming e-mail address input form.
$msg = _('To send notices via email, we need to create a unique email address for you on this server:');
}
$this->element('span', 'input_instructions', $msg);
$this->elementEnd('p'); $this->elementEnd('p');
// TRANS: Button label for adding an e-mail address to send notices from. // TRANS: Button label for adding an e-mail address to send notices from.
$this->submit('newincoming', _m('BUTTON','New')); $this->submit('newincoming', _m('BUTTON','New'));
$this->elementEnd('div'); // div#emailincoming
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
} }
@ -178,51 +204,47 @@ class EmailsettingsAction extends AccountSettingsAction
$this->element('legend', null, _('Email preferences')); $this->element('legend', null, _('Email preferences'));
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li');
$this->checkbox('emailnotifysub', if (Event::handle('StartEmailFormData', array($this))) {
// TRANS: Checkbox label in e-mail preferences form. $this->elementStart('li');
_('Send me notices of new subscriptions through email.'), $this->checkbox('emailnotifysub',
$user->emailnotifysub); // TRANS: Checkbox label in e-mail preferences form.
$this->elementEnd('li'); _('Send me notices of new subscriptions through email.'),
$this->elementStart('li'); $user->emailnotifysub);
$this->checkbox('emailnotifyfav', $this->elementEnd('li');
// TRANS: Checkbox label in e-mail preferences form. $this->elementStart('li');
_('Send me email when someone '. $this->checkbox('emailnotifyfav',
'adds my notice as a favorite.'), // TRANS: Checkbox label in e-mail preferences form.
$user->emailnotifyfav); _('Send me email when someone '.
$this->elementEnd('li'); 'adds my notice as a favorite.'),
$this->elementStart('li'); $user->emailnotifyfav);
$this->checkbox('emailnotifymsg', $this->elementEnd('li');
// TRANS: Checkbox label in e-mail preferences form. $this->elementStart('li');
_('Send me email when someone sends me a private message.'), $this->checkbox('emailnotifymsg',
$user->emailnotifymsg); // TRANS: Checkbox label in e-mail preferences form.
$this->elementEnd('li'); _('Send me email when someone sends me a private message.'),
$this->elementStart('li'); $user->emailnotifymsg);
$this->checkbox('emailnotifyattn', $this->elementEnd('li');
// TRANS: Checkbox label in e-mail preferences form. $this->elementStart('li');
_('Send me email when someone sends me an "@-reply".'), $this->checkbox('emailnotifyattn',
$user->emailnotifyattn); // TRANS: Checkbox label in e-mail preferences form.
$this->elementEnd('li'); _('Send me email when someone sends me an "@-reply".'),
$this->elementStart('li'); $user->emailnotifyattn);
$this->checkbox('emailnotifynudge', $this->elementEnd('li');
// TRANS: Checkbox label in e-mail preferences form. $this->elementStart('li');
_('Allow friends to nudge me and send me an email.'), $this->checkbox('emailnotifynudge',
$user->emailnotifynudge); // TRANS: Checkbox label in e-mail preferences form.
$this->elementEnd('li'); _('Allow friends to nudge me and send me an email.'),
if (common_config('emailpost', 'enabled')) { $user->emailnotifynudge);
$this->elementStart('li'); $this->elementEnd('li');
$this->checkbox('emailpost', $this->elementStart('li');
// TRANS: Checkbox label in e-mail preferences form. $this->checkbox('emailmicroid',
_('I want to post notices by email.'), // TRANS: Checkbox label in e-mail preferences form.
$user->emailpost); _('Publish a MicroID for my email address.'),
$this->elementEnd('li'); $user->emailmicroid);
} $this->elementEnd('li');
$this->elementStart('li'); Event::handle('EndEmailFormData', array($this));
$this->checkbox('emailmicroid', }
// TRANS: Checkbox label in e-mail preferences form.
_('Publish a MicroID for my email address.'),
$user->emailmicroid);
$this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
// TRANS: Button label to save e-mail preferences. // TRANS: Button label to save e-mail preferences.
$this->submit('save', _m('BUTTON','Save')); $this->submit('save', _m('BUTTON','Save'));
@ -236,7 +258,6 @@ class EmailsettingsAction extends AccountSettingsAction
* *
* @return Confirm_address Email address confirmation for user, or null * @return Confirm_address Email address confirmation for user, or null
*/ */
function getConfirmation() function getConfirmation()
{ {
$user = common_current_user(); $user = common_current_user();
@ -262,7 +283,6 @@ class EmailsettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function handlePost() function handlePost()
{ {
// CSRF protection // CSRF protection
@ -296,46 +316,50 @@ class EmailsettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function savePreferences() function savePreferences()
{ {
$emailnotifysub = $this->boolean('emailnotifysub'); $user = common_current_user();
$emailnotifyfav = $this->boolean('emailnotifyfav');
$emailnotifymsg = $this->boolean('emailnotifymsg');
$emailnotifynudge = $this->boolean('emailnotifynudge');
$emailnotifyattn = $this->boolean('emailnotifyattn');
$emailmicroid = $this->boolean('emailmicroid');
$emailpost = $this->boolean('emailpost');
$user = common_current_user(); if (Event::handle('StartEmailSaveForm', array($this, &$user))) {
assert(!is_null($user)); // should already be checked $emailnotifysub = $this->boolean('emailnotifysub');
$emailnotifyfav = $this->boolean('emailnotifyfav');
$emailnotifymsg = $this->boolean('emailnotifymsg');
$emailnotifynudge = $this->boolean('emailnotifynudge');
$emailnotifyattn = $this->boolean('emailnotifyattn');
$emailmicroid = $this->boolean('emailmicroid');
$emailpost = $this->boolean('emailpost');
$user->query('BEGIN'); assert(!is_null($user)); // should already be checked
$original = clone($user); $user->query('BEGIN');
$user->emailnotifysub = $emailnotifysub; $original = clone($user);
$user->emailnotifyfav = $emailnotifyfav;
$user->emailnotifymsg = $emailnotifymsg;
$user->emailnotifynudge = $emailnotifynudge;
$user->emailnotifyattn = $emailnotifyattn;
$user->emailmicroid = $emailmicroid;
$user->emailpost = $emailpost;
$result = $user->update($original); $user->emailnotifysub = $emailnotifysub;
$user->emailnotifyfav = $emailnotifyfav;
$user->emailnotifymsg = $emailnotifymsg;
$user->emailnotifynudge = $emailnotifynudge;
$user->emailnotifyattn = $emailnotifyattn;
$user->emailmicroid = $emailmicroid;
$user->emailpost = $emailpost;
if ($result === false) { $result = $user->update($original);
common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error updating e-mail preferences.
$this->serverError(_('Couldn\'t update user.'));
return;
}
$user->query('COMMIT'); if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error updating e-mail preferences.
$this->serverError(_('Could not update user.'));
return;
}
// TRANS: Confirmation message for successful e-mail preferences save. $user->query('COMMIT');
$this->showForm(_('Email preferences saved.'), true);
Event::handle('EndEmailSaveForm', array($this));
// TRANS: Confirmation message for successful e-mail preferences save.
$this->showForm(_('Email preferences saved.'), true);
}
} }
/** /**
@ -343,7 +367,6 @@ class EmailsettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function addAddress() function addAddress()
{ {
$user = common_current_user(); $user = common_current_user();
@ -362,7 +385,7 @@ class EmailsettingsAction extends AccountSettingsAction
if (!$email) { if (!$email) {
// TRANS: Message given saving e-mail address that cannot be normalised. // TRANS: Message given saving e-mail address that cannot be normalised.
$this->showForm(_('Cannot normalize that email address')); $this->showForm(_('Cannot normalize that email address.'));
return; return;
} }
if (!Validate::email($email, common_config('email', 'check_domain'))) { if (!Validate::email($email, common_config('email', 'check_domain'))) {
@ -392,7 +415,7 @@ class EmailsettingsAction extends AccountSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($confirm, 'INSERT', __FILE__); common_log_db_error($confirm, 'INSERT', __FILE__);
// TRANS: Server error thrown on database error adding e-mail confirmation code. // TRANS: Server error thrown on database error adding e-mail confirmation code.
$this->serverError(_('Couldn\'t insert confirmation code.')); $this->serverError(_('Could not insert confirmation code.'));
return; return;
} }
@ -411,7 +434,6 @@ class EmailsettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function cancelConfirmation() function cancelConfirmation()
{ {
$email = $this->arg('email'); $email = $this->arg('email');
@ -434,7 +456,7 @@ class EmailsettingsAction extends AccountSettingsAction
if (!$result) { if (!$result) {
common_log_db_error($confirm, 'DELETE', __FILE__); common_log_db_error($confirm, 'DELETE', __FILE__);
// TRANS: Server error thrown on database error canceling e-mail address confirmation. // TRANS: Server error thrown on database error canceling e-mail address confirmation.
$this->serverError(_('Couldn\'t delete email confirmation.')); $this->serverError(_('Could not delete email confirmation.'));
return; return;
} }
@ -447,7 +469,6 @@ class EmailsettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function removeAddress() function removeAddress()
{ {
$user = common_current_user(); $user = common_current_user();
@ -474,7 +495,7 @@ class EmailsettingsAction extends AccountSettingsAction
if (!$result) { if (!$result) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error removing a registered e-mail address. // TRANS: Server error thrown on database error removing a registered e-mail address.
$this->serverError(_('Couldn\'t update user.')); $this->serverError(_('Could not update user.'));
return; return;
} }
$user->query('COMMIT'); $user->query('COMMIT');
@ -488,12 +509,12 @@ class EmailsettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function removeIncoming() function removeIncoming()
{ {
$user = common_current_user(); $user = common_current_user();
if (!$user->incomingemail) { if (!$user->incomingemail) {
// TRANS: Form validation error displayed when trying to remove an incoming e-mail address while no address has been set.
$this->showForm(_('No incoming email address.')); $this->showForm(_('No incoming email address.'));
return; return;
} }
@ -501,11 +522,12 @@ class EmailsettingsAction extends AccountSettingsAction
$orig = clone($user); $orig = clone($user);
$user->incomingemail = null; $user->incomingemail = null;
$user->emailpost = 0;
if (!$user->updateKeys($orig)) { if (!$user->updateKeys($orig)) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error removing incoming e-mail address. // TRANS: Server error thrown on database error removing incoming e-mail address.
$this->serverError(_("Couldn't update user record.")); $this->serverError(_("Could not update user record."));
} }
// TRANS: Message given after successfully removing an incoming e-mail address. // TRANS: Message given after successfully removing an incoming e-mail address.
@ -517,7 +539,6 @@ class EmailsettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function newIncoming() function newIncoming()
{ {
$user = common_current_user(); $user = common_current_user();
@ -525,11 +546,12 @@ class EmailsettingsAction extends AccountSettingsAction
$orig = clone($user); $orig = clone($user);
$user->incomingemail = mail_new_incoming_address(); $user->incomingemail = mail_new_incoming_address();
$user->emailpost = 1;
if (!$user->updateKeys($orig)) { if (!$user->updateKeys($orig)) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error adding incoming e-mail address. // TRANS: Server error thrown on database error adding incoming e-mail address.
$this->serverError(_("Couldn't update user record.")); $this->serverError(_("Could not update user record."));
} }
// TRANS: Message given after successfully adding an incoming e-mail address. // TRANS: Message given after successfully adding an incoming e-mail address.

View File

@ -1,5 +1,4 @@
<?php <?php
/** /**
* Favor action. * Favor action.
* *
@ -59,6 +58,7 @@ class FavorAction extends Action
{ {
parent::handle($args); parent::handle($args);
if (!common_logged_in()) { if (!common_logged_in()) {
// TRANS: Client error displayed when trying to mark a notice as favorite without being logged in.
$this->clientError(_('Not logged in.')); $this->clientError(_('Not logged in.'));
return; return;
} }
@ -76,11 +76,13 @@ class FavorAction extends Action
return; return;
} }
if ($user->hasFave($notice)) { if ($user->hasFave($notice)) {
// TRANS: Client error displayed when trying to mark a notice as favorite that already is a favorite.
$this->clientError(_('This notice is already a favorite!')); $this->clientError(_('This notice is already a favorite!'));
return; return;
} }
$fave = Fave::addNew($user->getProfile(), $notice); $fave = Fave::addNew($user->getProfile(), $notice);
if (!$fave) { if (!$fave) {
// TRANS: Server error displayed when trying to mark a notice as favorite fails in the database.
$this->serverError(_('Could not create favorite.')); $this->serverError(_('Could not create favorite.'));
return; return;
} }
@ -89,6 +91,7 @@ class FavorAction extends Action
if ($this->boolean('ajax')) { if ($this->boolean('ajax')) {
$this->startHTML('text/xml;charset=utf-8'); $this->startHTML('text/xml;charset=utf-8');
$this->elementStart('head'); $this->elementStart('head');
// TRANS: Page title for page on which favorite notices can be unfavourited.
$this->element('title', null, _('Disfavor favorite')); $this->element('title', null, _('Disfavor favorite'));
$this->elementEnd('head'); $this->elementEnd('head');
$this->elementStart('body'); $this->elementStart('body');
@ -123,4 +126,3 @@ class FavorAction extends Action
} }
} }
} }

View File

@ -48,7 +48,6 @@ require_once INSTALLDIR.'/lib/noticelist.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class FavoritedAction extends Action class FavoritedAction extends Action
{ {
var $page = null; var $page = null;
@ -62,8 +61,11 @@ class FavoritedAction extends Action
function title() function title()
{ {
if ($this->page == 1) { if ($this->page == 1) {
// TRANS: Page title for first page of favorited notices.
return _('Popular notices'); return _('Popular notices');
} else { } else {
// TRANS: Page title for all but first page of favorited notices.
// TRANS: %d is the page number being displayed.
return sprintf(_('Popular notices, page %d'), $this->page); return sprintf(_('Popular notices, page %d'), $this->page);
} }
} }
@ -73,9 +75,9 @@ class FavoritedAction extends Action
* *
* @return instructions for use * @return instructions for use
*/ */
function getInstructions() function getInstructions()
{ {
// TRANS: Description on page displaying favorited notices.
return _('The most popular notices on the site right now.'); return _('The most popular notices on the site right now.');
} }
@ -84,7 +86,6 @@ class FavoritedAction extends Action
* *
* @return boolean true * @return boolean true
*/ */
function isReadOnly($args) function isReadOnly($args)
{ {
return true; return true;
@ -99,7 +100,6 @@ class FavoritedAction extends Action
* *
* @todo move queries from showContent() to here * @todo move queries from showContent() to here
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
@ -119,7 +119,6 @@ class FavoritedAction extends Action
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
@ -134,7 +133,6 @@ class FavoritedAction extends Action
* *
* @return void * @return void
*/ */
function showPageNotice() function showPageNotice()
{ {
$instr = $this->getInstructions(); $instr = $this->getInstructions();
@ -147,12 +145,16 @@ class FavoritedAction extends Action
function showEmptyList() function showEmptyList()
{ {
// TRANS: Text displayed instead of a list when a site does not yet have any favourited notices.
$message = _('Favorite notices appear on this page but no one has favorited one yet.') . ' '; $message = _('Favorite notices appear on this page but no one has favorited one yet.') . ' ';
if (common_logged_in()) { if (common_logged_in()) {
// TRANS: Additional text displayed instead of a list when a site does not yet have any favourited notices for logged in users.
$message .= _('Be the first to add a notice to your favorites by clicking the fave button next to any notice you like.'); $message .= _('Be the first to add a notice to your favorites by clicking the fave button next to any notice you like.');
} }
else { else {
// TRANS: Additional text displayed instead of a list when a site does not yet have any favourited notices for not logged in users.
// TRANS: %%action.register%% is a registration link. "[link text](link)" is Mark Down. Do not change the formatting.
$message .= _('Why not [register an account](%%action.register%%) and be the first to add a notice to your favorites!'); $message .= _('Why not [register an account](%%action.register%%) and be the first to add a notice to your favorites!');
} }
@ -168,7 +170,6 @@ class FavoritedAction extends Action
* *
* @return void * @return void
*/ */
function showLocalNav() function showLocalNav()
{ {
$nav = new PublicGroupNav($this); $nav = new PublicGroupNav($this);
@ -182,7 +183,6 @@ class FavoritedAction extends Action
* *
* @return void * @return void
*/ */
function showContent() function showContent()
{ {
$pop = new Popularity(); $pop = new Popularity();

View File

@ -1,5 +1,4 @@
<?php <?php
/** /**
* RSS feed for user favorites action class. * RSS feed for user favorites action class.
* *
@ -50,7 +49,6 @@ require_once INSTALLDIR.'/lib/rssaction.php';
*/ */
class FavoritesrssAction extends Rss10Action class FavoritesrssAction extends Rss10Action
{ {
/** The user whose favorites to display */ /** The user whose favorites to display */
var $user = null; var $user = null;
@ -62,7 +60,6 @@ class FavoritesrssAction extends Rss10Action
* *
* @return boolean success * @return boolean success
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
@ -71,6 +68,7 @@ class FavoritesrssAction extends Rss10Action
$this->user = User::staticGet('nickname', $nickname); $this->user = User::staticGet('nickname', $nickname);
if (!$this->user) { if (!$this->user) {
// TRANS: Client error displayed when trying to get the RSS feed with favorites of a user that does not exist.
$this->clientError(_('No such user.')); $this->clientError(_('No such user.'));
return false; return false;
} else { } else {
@ -108,10 +106,14 @@ class FavoritesrssAction extends Rss10Action
$c = array('url' => common_local_url('favoritesrss', $c = array('url' => common_local_url('favoritesrss',
array('nickname' => array('nickname' =>
$user->nickname)), $user->nickname)),
// TRANS: Title of RSS feed with favourite notices of a user.
// TRANS: %s is a user's nickname.
'title' => sprintf(_("%s's favorite notices"), $user->nickname), 'title' => sprintf(_("%s's favorite notices"), $user->nickname),
'link' => common_local_url('showfavorites', 'link' => common_local_url('showfavorites',
array('nickname' => array('nickname' =>
$user->nickname)), $user->nickname)),
// TRANS: Desciption of RSS feed with favourite notices of a user.
// TRANS: %1$s is a user's nickname, %2$s is the name of the StatusNet site.
'description' => sprintf(_('Updates favored by %1$s on %2$s!'), 'description' => sprintf(_('Updates favored by %1$s on %2$s!'),
$user->nickname, common_config('site', 'name'))); $user->nickname, common_config('site', 'name')));
return $c; return $c;

View File

@ -45,7 +45,6 @@ require_once INSTALLDIR.'/lib/publicgroupnav.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class FeaturedAction extends Action class FeaturedAction extends Action
{ {
var $page = null; var $page = null;
@ -66,8 +65,11 @@ class FeaturedAction extends Action
function title() function title()
{ {
if ($this->page == 1) { if ($this->page == 1) {
// TRANS: Page title for first page of featured users.
return _('Featured users'); return _('Featured users');
} else { } else {
// TRANS: Page title for all but first page of featured users.
// TRANS: %d is the page number being displayed.
return sprintf(_('Featured users, page %d'), $this->page); return sprintf(_('Featured users, page %d'), $this->page);
} }
} }
@ -96,7 +98,8 @@ class FeaturedAction extends Action
function getInstructions() function getInstructions()
{ {
return sprintf(_('A selection of some great users on %s'), // TRANS: Description on page displaying featured users.
return sprintf(_('A selection of some great users on %s.'),
common_config('site', 'name')); common_config('site', 'name'));
} }

View File

@ -21,6 +21,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once(INSTALLDIR.'/actions/shownotice.php'); require_once(INSTALLDIR.'/actions/shownotice.php');
// @todo FIXME: Add documentation.
class FileAction extends Action class FileAction extends Action
{ {
var $id = null; var $id = null;
@ -31,14 +32,17 @@ class FileAction extends Action
parent::prepare($args); parent::prepare($args);
$this->id = $this->trimmed('notice'); $this->id = $this->trimmed('notice');
if (empty($this->id)) { if (empty($this->id)) {
// TRANS: Client error displayed when no notice ID was given trying do display a file.
$this->clientError(_('No notice ID.')); $this->clientError(_('No notice ID.'));
} }
$notice = Notice::staticGet('id', $this->id); $notice = Notice::staticGet('id', $this->id);
if (empty($notice)) { if (empty($notice)) {
// TRANS: Client error displayed when an invalid notice ID was given trying do display a file.
$this->clientError(_('No notice.')); $this->clientError(_('No notice.'));
} }
$atts = $notice->attachments(); $atts = $notice->attachments();
if (empty($atts)) { if (empty($atts)) {
// TRANS: Client error displayed when trying do display a file for a notice without a file attachement.
$this->clientError(_('No attachments.')); $this->clientError(_('No attachments.'));
} }
foreach ($atts as $att) { foreach ($atts as $att) {
@ -48,6 +52,9 @@ class FileAction extends Action
} }
} }
if (empty($this->filerec)) { if (empty($this->filerec)) {
// XXX: Is this translation hint correct? If yes, please remove comment, if no, please correct and remove comment.
// TRANS: Client error displayed when trying do display a file for a notice with file attachements
// TRANS: that could not be found.
$this->clientError(_('No uploaded attachments.')); $this->clientError(_('No uploaded attachments.'));
} }
return true; return true;
@ -62,11 +69,8 @@ class FileAction extends Action
* *
* @return boolean true * @return boolean true
*/ */
function isReadOnly($args) function isReadOnly($args)
{ {
return true; return true;
} }
} }

View File

@ -48,7 +48,6 @@ require_once INSTALLDIR.'/lib/omb.php';
*/ */
class FinishremotesubscribeAction extends Action class FinishremotesubscribeAction extends Action
{ {
/** /**
* Class handler. * Class handler.
* *
@ -56,7 +55,7 @@ class FinishremotesubscribeAction extends Action
* *
* @return nothing * @return nothing
* *
**/ */
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
@ -66,6 +65,7 @@ class FinishremotesubscribeAction extends Action
$service = unserialize($_SESSION['oauth_authorization_request']); $service = unserialize($_SESSION['oauth_authorization_request']);
if (!$service) { if (!$service) {
// TRANS: Client error displayed when subscribing to a remote profile and an unexpected response is received.
$this->clientError(_('Not expecting this response!')); $this->clientError(_('Not expecting this response!'));
return; return;
} }
@ -77,6 +77,7 @@ class FinishremotesubscribeAction extends Action
$user = User::staticGet('uri', $service->getListeneeURI()); $user = User::staticGet('uri', $service->getListeneeURI());
if (!$user) { if (!$user) {
// TRANS: Client error displayed when subscribing to a remote profile that does not exist.
$this->clientError(_('User being listened to does not exist.')); $this->clientError(_('User being listened to does not exist.'));
return; return;
} }
@ -84,6 +85,7 @@ class FinishremotesubscribeAction extends Action
$other = User::staticGet('uri', $service->getListenerURI()); $other = User::staticGet('uri', $service->getListenerURI());
if ($other) { if ($other) {
// TRANS: Client error displayed when subscribing to a remote profile that is a local profile.
$this->clientError(_('You can use the local subscription!')); $this->clientError(_('You can use the local subscription!'));
return; return;
} }
@ -96,6 +98,7 @@ class FinishremotesubscribeAction extends Action
$profile = Profile::staticGet($remote->id); $profile = Profile::staticGet($remote->id);
if ($user->hasBlocked($profile)) { if ($user->hasBlocked($profile)) {
// TRANS: Client error displayed when subscribing to a remote profile that is blocked form subscribing to.
$this->clientError(_('That user has blocked you from subscribing.')); $this->clientError(_('That user has blocked you from subscribing.'));
return; return;
} }
@ -107,14 +110,17 @@ class FinishremotesubscribeAction extends Action
} catch (OAuthException $e) { } catch (OAuthException $e) {
if ($e->getMessage() == 'The authorized token does not equal the ' . if ($e->getMessage() == 'The authorized token does not equal the ' .
'submitted token.') { 'submitted token.') {
// TRANS: Client error displayed when subscribing to a remote profile without providing an authorised token.
$this->clientError(_('You are not authorized.')); $this->clientError(_('You are not authorized.'));
return; return;
} else { } else {
// TRANS: Client error displayed when subscribing to a remote profile and conversion of the request token to access token fails.
$this->clientError(_('Could not convert request token to ' . $this->clientError(_('Could not convert request token to ' .
'access token.')); 'access token.'));
return; return;
} }
} catch (OMB_RemoteServiceException $e) { } catch (OMB_RemoteServiceException $e) {
// TRANS: Client error displayed when subscribing to a remote profile fails because of an unsupported version of the OMB protocol.
$this->clientError(_('Remote service uses unknown version of ' . $this->clientError(_('Remote service uses unknown version of ' .
'OMB protocol.')); 'OMB protocol.'));
return; return;
@ -135,6 +141,7 @@ class FinishremotesubscribeAction extends Action
$service->getServiceURI(OMB_ENDPOINT_UPDATEPROFILE); $service->getServiceURI(OMB_ENDPOINT_UPDATEPROFILE);
if (!$remote->update($orig_remote)) { if (!$remote->update($orig_remote)) {
// TRANS: Server error displayed when subscribing to a remote profile fails because the remote profile could not be updated.
$this->serverError(_('Error updating remote profile.')); $this->serverError(_('Error updating remote profile.'));
return; return;
} }

View File

@ -23,6 +23,7 @@ define('LISTENER', 1);
define('LISTENEE', -1); define('LISTENEE', -1);
define('BOTH', 0); define('BOTH', 0);
// @todo XXX: Documentation missing.
class FoafAction extends Action class FoafAction extends Action
{ {
function isReadOnly($args) function isReadOnly($args)
@ -37,6 +38,7 @@ class FoafAction extends Action
$nickname_arg = $this->arg('nickname'); $nickname_arg = $this->arg('nickname');
if (empty($nickname_arg)) { if (empty($nickname_arg)) {
// TRANS: Client error displayed when requesting Friends of a Friend feed without providing a user nickname.
$this->clientError(_('No such user.'), 404); $this->clientError(_('No such user.'), 404);
return false; return false;
} }
@ -55,6 +57,7 @@ class FoafAction extends Action
$this->user = User::staticGet('nickname', $this->nickname); $this->user = User::staticGet('nickname', $this->nickname);
if (!$this->user) { if (!$this->user) {
// TRANS: Client error displayed when requesting Friends of a Friend feed for an object that is not a user.
$this->clientError(_('No such user.'), 404); $this->clientError(_('No such user.'), 404);
return false; return false;
} }
@ -62,6 +65,7 @@ class FoafAction extends Action
$this->profile = $this->user->getProfile(); $this->profile = $this->user->getProfile();
if (!$this->profile) { if (!$this->profile) {
// TRANS: Server error displayed when requesting Friends of a Friend feed for a user for which the profile could not be found.
$this->serverError(_('User has no profile.'), 500); $this->serverError(_('User has no profile.'), 500);
return false; return false;
} }
@ -110,7 +114,7 @@ class FoafAction extends Action
if ($this->profile->bio) { if ($this->profile->bio) {
$this->element('bio:olb', null, $this->profile->bio); $this->element('bio:olb', null, $this->profile->bio);
} }
$location = $this->profile->getLocation(); $location = $this->profile->getLocation();
if ($location) { if ($location) {
$attr = array(); $attr = array();
@ -118,7 +122,7 @@ class FoafAction extends Action
$attr['rdf:about'] = $location->getRdfURL(); $attr['rdf:about'] = $location->getRdfURL();
} }
$location_name = $location->getName(); $location_name = $location->getName();
$this->elementStart('based_near'); $this->elementStart('based_near');
$this->elementStart('geo:SpatialThing', $attr); $this->elementStart('geo:SpatialThing', $attr);
if ($location_name) { if ($location_name) {
@ -193,7 +197,7 @@ class FoafAction extends Action
$this->element('knows', array('rdf:resource' => $uri)); $this->element('knows', array('rdf:resource' => $uri));
} }
} }
$this->elementEnd('Agent'); $this->elementEnd('Agent');
@ -239,18 +243,17 @@ class FoafAction extends Action
/** /**
* Output FOAF <account> bit for the given profile. * Output FOAF <account> bit for the given profile.
* *
* @param Profile $profile * @param Profile $profile
* @param mixed $service Root URL of this StatusNet instance for a local * @param mixed $service Root URL of this StatusNet instance for a local
* user, otherwise null. * user, otherwise null.
* @param mixed $useruri URI string for the referenced profile.. * @param mixed $useruri URI string for the referenced profile..
* @param boolean $fetchSubscriptions Should we load and list all their subscriptions? * @param boolean $fetchSubscriptions Should we load and list all their subscriptions?
* @param boolean $isSubscriber if not fetching subs, we can still mark the user as following the current page. * @param boolean $isSubscriber if not fetching subs, we can still mark the user as following the current page.
* *
* @return array if $fetchSubscribers is set, return a list of info on those * @return array if $fetchSubscribers is set, return a list of info on those
* subscriptions. * subscriptions.
*/ */
function showMicrobloggingAccount($profile, $service=null, $useruri=null, $fetchSubscriptions=false, $isSubscriber=false) function showMicrobloggingAccount($profile, $service=null, $useruri=null, $fetchSubscriptions=false, $isSubscriber=false)
{ {
$attr = array(); $attr = array();

View File

@ -27,6 +27,7 @@
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
// @todo XXX: Documentation missing.
class FoafGroupAction extends Action class FoafGroupAction extends Action
{ {
function isReadOnly($args) function isReadOnly($args)
@ -41,6 +42,7 @@ class FoafGroupAction extends Action
$nickname_arg = $this->arg('nickname'); $nickname_arg = $this->arg('nickname');
if (empty($nickname_arg)) { if (empty($nickname_arg)) {
// TRANS: Client error displayed when requesting Friends of a Friend feed without providing a group nickname.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -59,6 +61,7 @@ class FoafGroupAction extends Action
$local = Local_group::staticGet('nickname', $this->nickname); $local = Local_group::staticGet('nickname', $this->nickname);
if (!$local) { if (!$local) {
// TRANS: Client error displayed when requesting Friends of a Friend feed for a non-local group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -66,6 +69,7 @@ class FoafGroupAction extends Action
$this->group = User_group::staticGet('id', $local->group_id); $this->group = User_group::staticGet('id', $local->group_id);
if (!$this->group) { if (!$this->group) {
// TRANS: Client error displayed when requesting Friends of a Friend feed for a nickname that is not a group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }

View File

@ -68,7 +68,7 @@ class GeocodeAction extends Action
* *
* @return nothing * @return nothing
* *
**/ */
function handle($args) function handle($args)
{ {
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
@ -89,7 +89,6 @@ class GeocodeAction extends Action
* *
* @return boolean true * @return boolean true
*/ */
function isReadOnly($args) function isReadOnly($args)
{ {
return true; return true;

View File

@ -47,13 +47,11 @@ require_once 'MIME/Type.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class GetfileAction extends Action class GetfileAction extends Action
{ {
/** /**
* Path of file to return * Path of file to return
*/ */
var $path = null; var $path = null;
/** /**
@ -63,7 +61,6 @@ class GetfileAction extends Action
* *
* @return success flag * @return success flag
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
@ -76,10 +73,12 @@ class GetfileAction extends Action
} }
if (empty($path) or !file_exists($path)) { if (empty($path) or !file_exists($path)) {
// TRANS: Client error displayed when requesting a non-existent file.
$this->clientError(_('No such file.'), 404); $this->clientError(_('No such file.'), 404);
return false; return false;
} }
if (!is_readable($path)) { if (!is_readable($path)) {
// TRANS: Client error displayed when requesting a file without having read access to it.
$this->clientError(_('Cannot read file.'), 403); $this->clientError(_('Cannot read file.'), 403);
return false; return false;
} }
@ -93,7 +92,6 @@ class GetfileAction extends Action
* *
* @return boolean true * @return boolean true
*/ */
function isReadOnly($args) function isReadOnly($args)
{ {
return true; return true;
@ -104,7 +102,6 @@ class GetfileAction extends Action
* *
* @return int last-modified date as unix timestamp * @return int last-modified date as unix timestamp
*/ */
function lastModified() function lastModified()
{ {
if (common_config('site', 'use_x_sendfile')) { if (common_config('site', 'use_x_sendfile')) {
@ -122,7 +119,6 @@ class GetfileAction extends Action
* *
* @return string etag http header * @return string etag http header
*/ */
function etag() function etag()
{ {
if (common_config('site', 'use_x_sendfile')) { if (common_config('site', 'use_x_sendfile')) {
@ -151,7 +147,6 @@ class GetfileAction extends Action
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
// undo headers set by PHP sessions // undo headers set by PHP sessions

View File

@ -2,7 +2,7 @@
/** /**
* StatusNet, the distributed open-source microblogging tool * StatusNet, the distributed open-source microblogging tool
* *
* Action class to sandbox an abusive user * Action class to grant user roles.
* *
* PHP version 5 * PHP version 5
* *
@ -32,7 +32,7 @@ if (!defined('STATUSNET')) {
} }
/** /**
* Sandbox a user. * Assign role to user.
* *
* @category Action * @category Action
* @package StatusNet * @package StatusNet
@ -40,7 +40,6 @@ if (!defined('STATUSNET')) {
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */
class GrantRoleAction extends ProfileFormAction class GrantRoleAction extends ProfileFormAction
{ {
/** /**
@ -50,19 +49,20 @@ class GrantRoleAction extends ProfileFormAction
* *
* @return boolean success flag * @return boolean success flag
*/ */
function prepare($args) function prepare($args)
{ {
if (!parent::prepare($args)) { if (!parent::prepare($args)) {
return false; return false;
} }
$this->role = $this->arg('role'); $this->role = $this->arg('role');
if (!Profile_role::isValid($this->role)) { if (!Profile_role::isValid($this->role)) {
// TRANS: Client error displayed when trying to assign an invalid role to a user.
$this->clientError(_('Invalid role.')); $this->clientError(_('Invalid role.'));
return false; return false;
} }
if (!Profile_role::isSettable($this->role)) { if (!Profile_role::isSettable($this->role)) {
// TRANS: Client error displayed when trying to assign an reserved role to a user.
$this->clientError(_('This role is reserved and cannot be set.')); $this->clientError(_('This role is reserved and cannot be set.'));
return false; return false;
} }
@ -72,6 +72,7 @@ class GrantRoleAction extends ProfileFormAction
assert(!empty($cur)); // checked by parent assert(!empty($cur)); // checked by parent
if (!$cur->hasRight(Right::GRANTROLE)) { if (!$cur->hasRight(Right::GRANTROLE)) {
// TRANS: Client error displayed when trying to assign a role to a user while not being allowed to set roles.
$this->clientError(_('You cannot grant user roles on this site.')); $this->clientError(_('You cannot grant user roles on this site.'));
return false; return false;
} }
@ -79,6 +80,7 @@ class GrantRoleAction extends ProfileFormAction
assert(!empty($this->profile)); // checked by parent assert(!empty($this->profile)); // checked by parent
if ($this->profile->hasRole($this->role)) { if ($this->profile->hasRole($this->role)) {
// TRANS: Client error displayed when trying to assign a role to a user that already has that role.
$this->clientError(_('User already has this role.')); $this->clientError(_('User already has this role.'));
return false; return false;
} }
@ -91,7 +93,6 @@ class GrantRoleAction extends ProfileFormAction
* *
* @return void * @return void
*/ */
function handlePost() function handlePost()
{ {
$this->profile->grantRole($this->role); $this->profile->grantRole($this->role);

View File

@ -40,7 +40,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */
class GroupblockAction extends RedirectingAction class GroupblockAction extends RedirectingAction
{ {
var $profile = null; var $profile = null;
@ -53,11 +52,11 @@ class GroupblockAction extends RedirectingAction
* *
* @return boolean success flag * @return boolean success flag
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
if (!common_logged_in()) { if (!common_logged_in()) {
// TRANS: Client error displayed trying to block a user from a group while not logged in.
$this->clientError(_('Not logged in.')); $this->clientError(_('Not logged in.'));
return false; return false;
} }
@ -68,35 +67,42 @@ class GroupblockAction extends RedirectingAction
} }
$id = $this->trimmed('blockto'); $id = $this->trimmed('blockto');
if (empty($id)) { if (empty($id)) {
// TRANS: Client error displayed trying to block a user from a group while not specifying a to be blocked user profile.
$this->clientError(_('No profile specified.')); $this->clientError(_('No profile specified.'));
return false; return false;
} }
$this->profile = Profile::staticGet('id', $id); $this->profile = Profile::staticGet('id', $id);
if (empty($this->profile)) { if (empty($this->profile)) {
// TRANS: Client error displayed trying to block a user from a group while specifying a non-existing profile.
$this->clientError(_('No profile with that ID.')); $this->clientError(_('No profile with that ID.'));
return false; return false;
} }
$group_id = $this->trimmed('blockgroup'); $group_id = $this->trimmed('blockgroup');
if (empty($group_id)) { if (empty($group_id)) {
// TRANS: Client error displayed trying to block a user from a group while not specifying a group to block a profile from.
$this->clientError(_('No group specified.')); $this->clientError(_('No group specified.'));
return false; return false;
} }
$this->group = User_group::staticGet('id', $group_id); $this->group = User_group::staticGet('id', $group_id);
if (empty($this->group)) { if (empty($this->group)) {
// TRANS: Client error displayed trying to block a user from a group while specifying a non-existing group.
$this->clientError(_('No such group.')); $this->clientError(_('No such group.'));
return false; return false;
} }
$user = common_current_user(); $user = common_current_user();
if (!$user->isAdmin($this->group)) { if (!$user->isAdmin($this->group)) {
// TRANS: Client error displayed trying to block a user from a group while not being an admin user.
$this->clientError(_('Only an admin can block group members.'), 401); $this->clientError(_('Only an admin can block group members.'), 401);
return false; return false;
} }
if (Group_block::isBlocked($this->group, $this->profile)) { if (Group_block::isBlocked($this->group, $this->profile)) {
// TRANS: Client error displayed trying to block a user from a group while user is already blocked from the given group.
$this->clientError(_('User is already blocked from group.')); $this->clientError(_('User is already blocked from group.'));
return false; return false;
} }
// XXX: could have proactive blocks, but we don't have UI for it. // XXX: could have proactive blocks, but we don't have UI for it.
if (!$this->profile->isMember($this->group)) { if (!$this->profile->isMember($this->group)) {
// TRANS: Client error displayed trying to block a user from a group while user is not a member of given group.
$this->clientError(_('User is not a member of group.')); $this->clientError(_('User is not a member of group.'));
return false; return false;
} }
@ -131,6 +137,7 @@ class GroupblockAction extends RedirectingAction
} }
function title() { function title() {
// TRANS: Title for block user from group page.
return _('Block user from group'); return _('Block user from group');
} }
@ -145,7 +152,6 @@ class GroupblockAction extends RedirectingAction
* *
* @return void * @return void
*/ */
function areYouSureForm() function areYouSureForm()
{ {
$id = $this->profile->id; $id = $this->profile->id;
@ -155,8 +161,11 @@ class GroupblockAction extends RedirectingAction
'action' => common_local_url('groupblock'))); 'action' => common_local_url('groupblock')));
$this->elementStart('fieldset'); $this->elementStart('fieldset');
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
// TRANS: Fieldset legend for block user from group form.
$this->element('legend', _('Block user')); $this->element('legend', _('Block user'));
$this->element('p', null, $this->element('p', null,
// TRANS: Explanatory text for block user from group form before setting the block.
// TRANS: %1$s is that to be blocked user, %2$s is the group the user will be blocked from.
sprintf(_('Are you sure you want to block user "%1$s" from the group "%2$s"? '. sprintf(_('Are you sure you want to block user "%1$s" from the group "%2$s"? '.
'They will be removed from the group, unable to post, and '. 'They will be removed from the group, unable to post, and '.
'unable to subscribe to the group in the future.'), 'unable to subscribe to the group in the future.'),
@ -196,24 +205,24 @@ class GroupblockAction extends RedirectingAction
* *
* @return void * @return void
*/ */
function blockProfile() function blockProfile()
{ {
$block = Group_block::blockProfile($this->group, $this->profile, $block = Group_block::blockProfile($this->group, $this->profile,
common_current_user()); common_current_user());
if (empty($block)) { if (empty($block)) {
// TRANS: Server error displayed when trying to block a user from a group fails because of an application error.
$this->serverError(_("Database error blocking user from group.")); $this->serverError(_("Database error blocking user from group."));
return false; return false;
} }
$this->returnToPrevious(); $this->returnToPrevious();
} }
/** /**
* If we reached this form without returnto arguments, default to * If we reached this form without returnto arguments, default to
* the top of the group's member list. * the top of the group's member list.
* *
* @return string URL * @return string URL
*/ */
function defaultReturnTo() function defaultReturnTo()
@ -227,6 +236,4 @@ class GroupblockAction extends RedirectingAction
parent::showScripts(); parent::showScripts();
$this->autofocus('form_action-yes'); $this->autofocus('form_action-yes');
} }
} }

View File

@ -47,7 +47,6 @@ require_once INSTALLDIR.'/lib/feedlist.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class GroupbyidAction extends Action class GroupbyidAction extends Action
{ {
/** group we're viewing. */ /** group we're viewing. */
@ -58,7 +57,6 @@ class GroupbyidAction extends Action
* *
* @return boolean true * @return boolean true
*/ */
function isReadOnly($args) function isReadOnly($args)
{ {
return true; return true;
@ -71,6 +69,7 @@ class GroupbyidAction extends Action
$id = $this->arg('id'); $id = $this->arg('id');
if (!$id) { if (!$id) {
// TRANS: Client error displayed referring to a group's permalink without providing a group ID.
$this->clientError(_('No ID.')); $this->clientError(_('No ID.'));
return false; return false;
} }
@ -80,6 +79,7 @@ class GroupbyidAction extends Action
$this->group = User_group::staticGet('id', $id); $this->group = User_group::staticGet('id', $id);
if (!$this->group) { if (!$this->group) {
// TRANS: Client error displayed referring to a group's permalink for a non-existing group ID.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -95,9 +95,8 @@ class GroupbyidAction extends Action
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
common_redirect($this->group->homeUrl(), 303); common_redirect($this->group->homeUrl(), 303);
} }
} }

View File

@ -2,7 +2,7 @@
/** /**
* StatusNet, the distributed open-source microblogging tool * StatusNet, the distributed open-source microblogging tool
* *
* Change user password * Saves a design for a given group.
* *
* PHP version 5 * PHP version 5
* *
@ -46,7 +46,6 @@ require_once INSTALLDIR . '/lib/designsettings.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class GroupDesignSettingsAction extends DesignSettingsAction class GroupDesignSettingsAction extends DesignSettingsAction
{ {
var $group = null; var $group = null;
@ -59,12 +58,12 @@ class GroupDesignSettingsAction extends DesignSettingsAction
* *
* @return boolean true * @return boolean true
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
if (!common_logged_in()) { if (!common_logged_in()) {
// TRANS: Client error displayed trying to change group design settings while not logged in.
$this->clientError(_('You must be logged in to edit a group.')); $this->clientError(_('You must be logged in to edit a group.'));
return false; return false;
} }
@ -81,6 +80,7 @@ class GroupDesignSettingsAction extends DesignSettingsAction
} }
if (!$nickname) { if (!$nickname) {
// TRANS: Client error displayed trying to change group design settings without providing a group nickname.
$this->clientError(_('No nickname.'), 404); $this->clientError(_('No nickname.'), 404);
return false; return false;
} }
@ -97,6 +97,7 @@ class GroupDesignSettingsAction extends DesignSettingsAction
} }
if (!$this->group) { if (!$this->group) {
// TRANS: Client error displayed trying to change group design settings while providing a nickname for a non-existing group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -104,6 +105,7 @@ class GroupDesignSettingsAction extends DesignSettingsAction
$cur = common_current_user(); $cur = common_current_user();
if (!$cur->isAdmin($this->group)) { if (!$cur->isAdmin($this->group)) {
// TRANS: Client error displayed trying to change group design settings without being a (group) admin.
$this->clientError(_('You must be an admin to edit the group.'), 403); $this->clientError(_('You must be an admin to edit the group.'), 403);
return false; return false;
} }
@ -122,7 +124,6 @@ class GroupDesignSettingsAction extends DesignSettingsAction
* *
* @return Design a design object to use * @return Design a design object to use
*/ */
function getDesign() function getDesign()
{ {
@ -141,6 +142,7 @@ class GroupDesignSettingsAction extends DesignSettingsAction
function title() function title()
{ {
// TRANS: Title group design settings page.
return _('Group design'); return _('Group design');
} }
@ -149,9 +151,9 @@ class GroupDesignSettingsAction extends DesignSettingsAction
* *
* @return instructions for use * @return instructions for use
*/ */
function getInstructions() function getInstructions()
{ {
// TRANS: Instructions for group design settings page.
return _('Customize the way your group looks ' . return _('Customize the way your group looks ' .
'with a background image and a colour palette of your choice.'); 'with a background image and a colour palette of your choice.');
} }
@ -161,7 +163,6 @@ class GroupDesignSettingsAction extends DesignSettingsAction
* *
* @return nothing * @return nothing
*/ */
function showLocalNav() function showLocalNav()
{ {
$nav = new GroupNav($this, $this->group); $nav = new GroupNav($this, $this->group);
@ -173,7 +174,6 @@ class GroupDesignSettingsAction extends DesignSettingsAction
* *
* @return Design * @return Design
*/ */
function getWorkingDesign() function getWorkingDesign()
{ {
$design = null; $design = null;
@ -192,7 +192,6 @@ class GroupDesignSettingsAction extends DesignSettingsAction
* *
* @return void * @return void
*/ */
function showContent() function showContent()
{ {
$design = $this->getWorkingDesign(); $design = $this->getWorkingDesign();
@ -209,17 +208,14 @@ class GroupDesignSettingsAction extends DesignSettingsAction
* *
* @return void * @return void
*/ */
function saveDesign() function saveDesign()
{ {
try { try {
$bgcolor = new WebColor($this->trimmed('design_background')); $bgcolor = new WebColor($this->trimmed('design_background'));
$ccolor = new WebColor($this->trimmed('design_content')); $ccolor = new WebColor($this->trimmed('design_content'));
$sbcolor = new WebColor($this->trimmed('design_sidebar')); $sbcolor = new WebColor($this->trimmed('design_sidebar'));
$tcolor = new WebColor($this->trimmed('design_text')); $tcolor = new WebColor($this->trimmed('design_text'));
$lcolor = new WebColor($this->trimmed('design_links')); $lcolor = new WebColor($this->trimmed('design_links'));
} catch (WebColorException $e) { } catch (WebColorException $e) {
$this->showForm($e->getMessage()); $this->showForm($e->getMessage());
return; return;
@ -246,7 +242,6 @@ class GroupDesignSettingsAction extends DesignSettingsAction
$design = $this->group->getDesign(); $design = $this->group->getDesign();
if (!empty($design)) { if (!empty($design)) {
// update design // update design
$original = clone($design); $original = clone($design);
@ -263,12 +258,11 @@ class GroupDesignSettingsAction extends DesignSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($design, 'UPDATE', __FILE__); common_log_db_error($design, 'UPDATE', __FILE__);
$this->showForm(_('Couldn\'t update your design.')); // TRANS: Form validation error displayed when group design settings could not be updated because of an application issue.
$this->showForm(_('Unable to update your design settings.'));
return; return;
} }
} else { } else {
$this->group->query('BEGIN'); $this->group->query('BEGIN');
// save new design // save new design
@ -287,6 +281,7 @@ class GroupDesignSettingsAction extends DesignSettingsAction
if (empty($id)) { if (empty($id)) {
common_log_db_error($id, 'INSERT', __FILE__); common_log_db_error($id, 'INSERT', __FILE__);
// TRANS: Form validation error displayed when group design settings could not be saved because of an application issue.
$this->showForm(_('Unable to save your design settings.')); $this->showForm(_('Unable to save your design settings.'));
return; return;
} }
@ -297,18 +292,18 @@ class GroupDesignSettingsAction extends DesignSettingsAction
if (empty($result)) { if (empty($result)) {
common_log_db_error($original, 'UPDATE', __FILE__); common_log_db_error($original, 'UPDATE', __FILE__);
// TRANS: Form validation error displayed when group design settings could not be saved because of an application issue.
$this->showForm(_('Unable to save your design settings.')); $this->showForm(_('Unable to save your design settings.'));
$this->group->query('ROLLBACK'); $this->group->query('ROLLBACK');
return; return;
} }
$this->group->query('COMMIT'); $this->group->query('COMMIT');
} }
$this->saveBackgroundImage($design); $this->saveBackgroundImage($design);
// TRANS: Form text to confirm saved group design settings.
$this->showForm(_('Design preferences saved.'), true); $this->showForm(_('Design preferences saved.'), true);
} }
} }

View File

@ -49,7 +49,6 @@ define('MAX_ORIGINAL', 480);
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class GrouplogoAction extends GroupDesignAction class GrouplogoAction extends GroupDesignAction
{ {
var $mode = null; var $mode = null;
@ -61,12 +60,12 @@ class GrouplogoAction extends GroupDesignAction
/** /**
* Prepare to run * Prepare to run
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
if (!common_logged_in()) { if (!common_logged_in()) {
// TRANS: Client error displayed when trying to create a group while not logged in.
$this->clientError(_('You must be logged in to create a group.')); $this->clientError(_('You must be logged in to create a group.'));
return false; return false;
} }
@ -83,6 +82,7 @@ class GrouplogoAction extends GroupDesignAction
} }
if (!$nickname) { if (!$nickname) {
// TRANS: Client error displayed when trying to change group logo settings without providing a nickname.
$this->clientError(_('No nickname.'), 404); $this->clientError(_('No nickname.'), 404);
return false; return false;
} }
@ -99,6 +99,7 @@ class GrouplogoAction extends GroupDesignAction
} }
if (!$this->group) { if (!$this->group) {
// TRANS: Client error displayed when trying to update logo settings for a non-existing group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -106,6 +107,7 @@ class GrouplogoAction extends GroupDesignAction
$cur = common_current_user(); $cur = common_current_user();
if (!$cur->isAdmin($this->group)) { if (!$cur->isAdmin($this->group)) {
// TRANS: Client error displayed when trying to change group logo settings while not being a group admin.
$this->clientError(_('You must be an admin to edit the group.'), 403); $this->clientError(_('You must be an admin to edit the group.'), 403);
return false; return false;
} }
@ -136,9 +138,9 @@ class GrouplogoAction extends GroupDesignAction
* *
* @return string Title of the page * @return string Title of the page
*/ */
function title() function title()
{ {
// TRANS: Title for group logo settings page.
return _('Group logo'); return _('Group logo');
} }
@ -147,9 +149,10 @@ class GrouplogoAction extends GroupDesignAction
* *
* @return instructions for use * @return instructions for use
*/ */
function getInstructions() function getInstructions()
{ {
// TRANS: Instructions for group logo page.
// TRANS: %s is the maximum file size for that site.
return sprintf(_('You can upload a logo image for your group. The maximum file size is %s.'), ImageFile::maxFileSize()); return sprintf(_('You can upload a logo image for your group. The maximum file size is %s.'), ImageFile::maxFileSize());
} }
@ -160,7 +163,6 @@ class GrouplogoAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function showContent() function showContent()
{ {
if ($this->mode == 'crop') { if ($this->mode == 'crop') {
@ -178,6 +180,7 @@ class GrouplogoAction extends GroupDesignAction
if (!$profile) { if (!$profile) {
common_log_db_error($user, 'SELECT', __FILE__); common_log_db_error($user, 'SELECT', __FILE__);
// TRANS: Server error displayed coming across a request from a user without a profile.
$this->serverError(_('User without matching profile.')); $this->serverError(_('User without matching profile.'));
return; return;
} }
@ -192,6 +195,7 @@ class GrouplogoAction extends GroupDesignAction
common_local_url('grouplogo', common_local_url('grouplogo',
array('nickname' => $this->group->nickname)))); array('nickname' => $this->group->nickname))));
$this->elementStart('fieldset'); $this->elementStart('fieldset');
// TRANS: Group logo form legend.
$this->element('legend', null, _('Group logo')); $this->element('legend', null, _('Group logo'));
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
@ -199,6 +203,7 @@ class GrouplogoAction extends GroupDesignAction
if ($original) { if ($original) {
$this->elementStart('li', array('id' => 'avatar_original', $this->elementStart('li', array('id' => 'avatar_original',
'class' => 'avatar_view')); 'class' => 'avatar_view'));
// TRANS: Uploaded original file in group logo form.
$this->element('h2', null, _("Original")); $this->element('h2', null, _("Original"));
$this->elementStart('div', array('id'=>'avatar_original_view')); $this->elementStart('div', array('id'=>'avatar_original_view'));
$this->element('img', array('src' => $this->group->original_logo, $this->element('img', array('src' => $this->group->original_logo,
@ -210,6 +215,7 @@ class GrouplogoAction extends GroupDesignAction
if ($this->group->homepage_logo) { if ($this->group->homepage_logo) {
$this->elementStart('li', array('id' => 'avatar_preview', $this->elementStart('li', array('id' => 'avatar_preview',
'class' => 'avatar_view')); 'class' => 'avatar_view'));
// TRANS: Header for preview of to be displayed group logo.
$this->element('h2', null, _("Preview")); $this->element('h2', null, _("Preview"));
$this->elementStart('div', array('id'=>'avatar_preview_view')); $this->elementStart('div', array('id'=>'avatar_preview_view'));
$this->element('img', array('src' => $this->group->homepage_logo, $this->element('img', array('src' => $this->group->homepage_logo,
@ -221,25 +227,25 @@ class GrouplogoAction extends GroupDesignAction
} }
$this->elementStart('li', array ('id' => 'settings_attach')); $this->elementStart('li', array ('id' => 'settings_attach'));
$this->element('input', array('name' => 'avatarfile',
'type' => 'file',
'id' => 'avatarfile'));
$this->element('input', array('name' => 'MAX_FILE_SIZE', $this->element('input', array('name' => 'MAX_FILE_SIZE',
'type' => 'hidden', 'type' => 'hidden',
'id' => 'MAX_FILE_SIZE', 'id' => 'MAX_FILE_SIZE',
'value' => ImageFile::maxFileSizeInt())); 'value' => ImageFile::maxFileSizeInt()));
$this->element('input', array('name' => 'avatarfile',
'type' => 'file',
'id' => 'avatarfile'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->elementStart('ul', 'form_actions'); $this->elementStart('ul', 'form_actions');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Submit button for uploading a group logo.
$this->submit('upload', _('Upload')); $this->submit('upload', _('Upload'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }
function showCropForm() function showCropForm()
@ -251,6 +257,7 @@ class GrouplogoAction extends GroupDesignAction
common_local_url('grouplogo', common_local_url('grouplogo',
array('nickname' => $this->group->nickname)))); array('nickname' => $this->group->nickname))));
$this->elementStart('fieldset'); $this->elementStart('fieldset');
// TRANS: Legend for group logo settings fieldset.
$this->element('legend', null, _('Avatar settings')); $this->element('legend', null, _('Avatar settings'));
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
@ -259,6 +266,7 @@ class GrouplogoAction extends GroupDesignAction
$this->elementStart('li', $this->elementStart('li',
array('id' => 'avatar_original', array('id' => 'avatar_original',
'class' => 'avatar_view')); 'class' => 'avatar_view'));
// TRANS: Header for originally uploaded file before a crop on the group logo page.
$this->element('h2', null, _("Original")); $this->element('h2', null, _("Original"));
$this->elementStart('div', array('id'=>'avatar_original_view')); $this->elementStart('div', array('id'=>'avatar_original_view'));
$this->element('img', array('src' => Avatar::url($this->filedata['filename']), $this->element('img', array('src' => Avatar::url($this->filedata['filename']),
@ -271,6 +279,7 @@ class GrouplogoAction extends GroupDesignAction
$this->elementStart('li', $this->elementStart('li',
array('id' => 'avatar_preview', array('id' => 'avatar_preview',
'class' => 'avatar_view')); 'class' => 'avatar_view'));
// TRANS: Header for the cropped group logo on the group logo page.
$this->element('h2', null, _("Preview")); $this->element('h2', null, _("Preview"));
$this->elementStart('div', array('id'=>'avatar_preview_view')); $this->elementStart('div', array('id'=>'avatar_preview_view'));
$this->element('img', array('src' => Avatar::url($this->filedata['filename']), $this->element('img', array('src' => Avatar::url($this->filedata['filename']),
@ -286,13 +295,13 @@ class GrouplogoAction extends GroupDesignAction
'id' => $crop_info)); 'id' => $crop_info));
} }
// TRANS: Button text for cropping an uploaded group logo.
$this->submit('crop', _('Crop')); $this->submit('crop', _('Crop'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }
/** /**
@ -302,13 +311,13 @@ class GrouplogoAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function handlePost() function handlePost()
{ {
// CSRF protection // CSRF protection
$token = $this->trimmed('token'); $token = $this->trimmed('token');
if (!$token || $token != common_session_token()) { if (!$token || $token != common_session_token()) {
// TRANS: Form validation error message.
$this->show_form(_('There was a problem with your session token. '. $this->show_form(_('There was a problem with your session token. '.
'Try again, please.')); 'Try again, please.'));
return; return;
@ -319,6 +328,7 @@ class GrouplogoAction extends GroupDesignAction
} else if ($this->arg('crop')) { } else if ($this->arg('crop')) {
$this->cropLogo(); $this->cropLogo();
} else { } else {
// TRANS: Form validation error message when an unsupported argument is used.
$this->showForm(_('Unexpected form submission.')); $this->showForm(_('Unexpected form submission.'));
} }
} }
@ -331,7 +341,6 @@ class GrouplogoAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function uploadLogo() function uploadLogo()
{ {
try { try {
@ -341,20 +350,21 @@ class GrouplogoAction extends GroupDesignAction
return; return;
} }
$type = $imagefile->preferredType();
$filename = Avatar::filename($this->group->id, $filename = Avatar::filename($this->group->id,
image_type_to_extension($imagefile->type), image_type_to_extension($type),
null, null,
'group-temp-'.common_timestamp()); 'group-temp-'.common_timestamp());
$filepath = Avatar::path($filename); $filepath = Avatar::path($filename);
move_uploaded_file($imagefile->filepath, $filepath); $imagefile->copyTo($filepath);
$filedata = array('filename' => $filename, $filedata = array('filename' => $filename,
'filepath' => $filepath, 'filepath' => $filepath,
'width' => $imagefile->width, 'width' => $imagefile->width,
'height' => $imagefile->height, 'height' => $imagefile->height,
'type' => $imagefile->type); 'type' => $type);
$_SESSION['FILEDATA'] = $filedata; $_SESSION['FILEDATA'] = $filedata;
@ -362,6 +372,7 @@ class GrouplogoAction extends GroupDesignAction
$this->mode = 'crop'; $this->mode = 'crop';
// TRANS: Form instructions on the group logo page.
$this->showForm(_('Pick a square area of the image to be the logo.'), $this->showForm(_('Pick a square area of the image to be the logo.'),
true); true);
} }
@ -371,12 +382,12 @@ class GrouplogoAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function cropLogo() function cropLogo()
{ {
$filedata = $_SESSION['FILEDATA']; $filedata = $_SESSION['FILEDATA'];
if (!$filedata) { if (!$filedata) {
// TRANS: Server error displayed trying to crop an uploaded group logo that is no longer present.
$this->serverError(_('Lost our file data.')); $this->serverError(_('Lost our file data.'));
return; return;
} }
@ -396,8 +407,10 @@ class GrouplogoAction extends GroupDesignAction
@unlink($filedata['filepath']); @unlink($filedata['filepath']);
unset($_SESSION['FILEDATA']); unset($_SESSION['FILEDATA']);
$this->mode = 'upload'; $this->mode = 'upload';
// TRANS: Form success message after updating a group logo.
$this->showForm(_('Logo updated.'), true); $this->showForm(_('Logo updated.'), true);
} else { } else {
// TRANS: Form failure message after failing to update a group logo.
$this->showForm(_('Failed updating logo.')); $this->showForm(_('Failed updating logo.'));
} }
} }
@ -422,7 +435,6 @@ class GrouplogoAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function showStylesheets() function showStylesheets()
{ {
parent::showStylesheets(); parent::showStylesheets();
@ -434,7 +446,6 @@ class GrouplogoAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function showScripts() function showScripts()
{ {
parent::showScripts(); parent::showScripts();

View File

@ -43,7 +43,6 @@ require_once INSTALLDIR.'/lib/publicgroupnav.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class GroupmembersAction extends GroupDesignAction class GroupmembersAction extends GroupDesignAction
{ {
var $page = null; var $page = null;
@ -73,6 +72,7 @@ class GroupmembersAction extends GroupDesignAction
} }
if (!$nickname) { if (!$nickname) {
// TRANS: Client error displayed when trying to view group members without providing a group nickname.
$this->clientError(_('No nickname.'), 404); $this->clientError(_('No nickname.'), 404);
return false; return false;
} }
@ -80,6 +80,7 @@ class GroupmembersAction extends GroupDesignAction
$local = Local_group::staticGet('nickname', $nickname); $local = Local_group::staticGet('nickname', $nickname);
if (!$local) { if (!$local) {
// TRANS: Client error displayed when trying to view group members for a non-existing group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -87,6 +88,7 @@ class GroupmembersAction extends GroupDesignAction
$this->group = User_group::staticGet('id', $local->group_id); $this->group = User_group::staticGet('id', $local->group_id);
if (!$this->group) { if (!$this->group) {
// TRANS: Client error displayed when trying to view group members for an object that is not a group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -119,6 +121,7 @@ class GroupmembersAction extends GroupDesignAction
function showPageNotice() function showPageNotice()
{ {
$this->element('p', 'instructions', $this->element('p', 'instructions',
// TRANS: Page notice for group members page.
_('A list of the users in this group.')); _('A list of the users in this group.'));
} }
@ -182,7 +185,8 @@ class GroupMemberListItem extends ProfileListItem
{ {
parent::showFullName(); parent::showFullName();
if ($this->profile->isAdmin($this->group)) { if ($this->profile->isAdmin($this->group)) {
$this->out->text(' '); $this->out->text(' '); // for separating the classes.
// TRANS: Indicator in group members list that this user is a group administrator.
$this->out->element('span', 'role', _('Admin')); $this->out->element('span', 'role', _('Admin'));
} }
} }
@ -254,7 +258,7 @@ class GroupMemberListItem extends ProfileListItem
/** /**
* Fetch necessary return-to arguments for the profile forms * Fetch necessary return-to arguments for the profile forms
* to return to this list when they're done. * to return to this list when they're done.
* *
* @return array * @return array
*/ */
protected function returnToArgs() protected function returnToArgs()
@ -281,7 +285,6 @@ class GroupMemberListItem extends ProfileListItem
* *
* @see BlockForm * @see BlockForm
*/ */
class GroupBlockForm extends Form class GroupBlockForm extends Form
{ {
/** /**
@ -310,7 +313,6 @@ class GroupBlockForm extends Form
* @param User_group $group group to block user from * @param User_group $group group to block user from
* @param array $args return-to args * @param array $args return-to args
*/ */
function __construct($out=null, $profile=null, $group=null, $args=null) function __construct($out=null, $profile=null, $group=null, $args=null)
{ {
parent::__construct($out); parent::__construct($out);
@ -325,7 +327,6 @@ class GroupBlockForm extends Form
* *
* @return int ID of the form * @return int ID of the form
*/ */
function id() function id()
{ {
// This should be unique for the page. // This should be unique for the page.
@ -337,7 +338,6 @@ class GroupBlockForm extends Form
* *
* @return string class of the form * @return string class of the form
*/ */
function formClass() function formClass()
{ {
return 'form_group_block'; return 'form_group_block';
@ -348,7 +348,6 @@ class GroupBlockForm extends Form
* *
* @return string URL of the action * @return string URL of the action
*/ */
function action() function action()
{ {
return common_local_url('groupblock'); return common_local_url('groupblock');
@ -361,6 +360,7 @@ class GroupBlockForm extends Form
*/ */
function formLegend() function formLegend()
{ {
// TRANS: Form legend for form to block user from a group.
$this->out->element('legend', null, _('Block user from group')); $this->out->element('legend', null, _('Block user from group'));
} }
@ -369,7 +369,6 @@ class GroupBlockForm extends Form
* *
* @return void * @return void
*/ */
function formData() function formData()
{ {
$this->out->hidden('blockto-' . $this->profile->id, $this->out->hidden('blockto-' . $this->profile->id,
@ -390,7 +389,6 @@ class GroupBlockForm extends Form
* *
* @return void * @return void
*/ */
function formActions() function formActions()
{ {
$this->out->submit( $this->out->submit(
@ -414,25 +412,21 @@ class GroupBlockForm extends Form
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class MakeAdminForm extends Form class MakeAdminForm extends Form
{ {
/** /**
* Profile of user to block * Profile of user to block
*/ */
var $profile = null; var $profile = null;
/** /**
* Group to block the user from * Group to block the user from
*/ */
var $group = null; var $group = null;
/** /**
* Return-to args * Return-to args
*/ */
var $args = null; var $args = null;
/** /**
@ -443,7 +437,6 @@ class MakeAdminForm extends Form
* @param User_group $group group to block user from * @param User_group $group group to block user from
* @param array $args return-to args * @param array $args return-to args
*/ */
function __construct($out=null, $profile=null, $group=null, $args=null) function __construct($out=null, $profile=null, $group=null, $args=null)
{ {
parent::__construct($out); parent::__construct($out);
@ -458,7 +451,6 @@ class MakeAdminForm extends Form
* *
* @return int ID of the form * @return int ID of the form
*/ */
function id() function id()
{ {
// This should be unique for the page. // This should be unique for the page.
@ -470,7 +462,6 @@ class MakeAdminForm extends Form
* *
* @return string class of the form * @return string class of the form
*/ */
function formClass() function formClass()
{ {
return 'form_make_admin'; return 'form_make_admin';
@ -481,7 +472,6 @@ class MakeAdminForm extends Form
* *
* @return string URL of the action * @return string URL of the action
*/ */
function action() function action()
{ {
return common_local_url('makeadmin', array('nickname' => $this->group->nickname)); return common_local_url('makeadmin', array('nickname' => $this->group->nickname));
@ -492,9 +482,9 @@ class MakeAdminForm extends Form
* *
* @return void * @return void
*/ */
function formLegend() function formLegend()
{ {
// TRANS: Form legend for form to make a user a group admin.
$this->out->element('legend', null, _('Make user an admin of the group')); $this->out->element('legend', null, _('Make user an admin of the group'));
} }
@ -503,7 +493,6 @@ class MakeAdminForm extends Form
* *
* @return void * @return void
*/ */
function formData() function formData()
{ {
$this->out->hidden('profileid-' . $this->profile->id, $this->out->hidden('profileid-' . $this->profile->id,
@ -524,7 +513,6 @@ class MakeAdminForm extends Form
* *
* @return void * @return void
*/ */
function formActions() function formActions()
{ {
$this->out->submit( $this->out->submit(

View File

@ -45,7 +45,6 @@ define('MEMBERS_PER_SECTION', 27);
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class groupRssAction extends Rss10Action class groupRssAction extends Rss10Action
{ {
/** group we're viewing. */ /** group we're viewing. */
@ -56,7 +55,6 @@ class groupRssAction extends Rss10Action
* *
* @return boolean true * @return boolean true
*/ */
function isReadOnly($args) function isReadOnly($args)
{ {
return true; return true;
@ -71,7 +69,6 @@ class groupRssAction extends Rss10Action
* *
* @return boolean success flag * @return boolean success flag
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
@ -88,6 +85,7 @@ class groupRssAction extends Rss10Action
} }
if (!$nickname) { if (!$nickname) {
// TRANS: Client error displayed when requesting a group RSS feed without providing a group nickname.
$this->clientError(_('No nickname.'), 404); $this->clientError(_('No nickname.'), 404);
return false; return false;
} }
@ -95,6 +93,7 @@ class groupRssAction extends Rss10Action
$local = Local_group::staticGet('nickname', $nickname); $local = Local_group::staticGet('nickname', $nickname);
if (!$local) { if (!$local) {
// TRANS: Client error displayed when requesting a group RSS feed for group that does not exist.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -102,6 +101,7 @@ class groupRssAction extends Rss10Action
$this->group = User_group::staticGet('id', $local->group_id); $this->group = User_group::staticGet('id', $local->group_id);
if (!$this->group) { if (!$this->group) {
// TRANS: Client error displayed when requesting a group RSS feed for an object that is not a group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -112,7 +112,6 @@ class groupRssAction extends Rss10Action
function getNotices($limit=0) function getNotices($limit=0)
{ {
$group = $this->group; $group = $this->group;
if (is_null($group)) { if (is_null($group)) {

View File

@ -45,7 +45,6 @@ require_once INSTALLDIR.'/lib/grouplist.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class GroupsAction extends Action class GroupsAction extends Action
{ {
var $page = null; var $page = null;
@ -59,9 +58,12 @@ class GroupsAction extends Action
function title() function title()
{ {
if ($this->page == 1) { if ($this->page == 1) {
return _("Groups"); // TRANS: Title for first page of the groups list.
return _m('TITLE',"Groups");
} else { } else {
return sprintf(_("Groups, page %d"), $this->page); // TRANS: Title for all but the first page of the groups list.
// TRANS: %d is the page number.
return sprintf(_m('TITLE',"Groups, page %d"), $this->page);
} }
} }
@ -87,12 +89,15 @@ class GroupsAction extends Action
function showPageNotice() function showPageNotice()
{ {
$notice = $notice =
// TRANS: Page notice of group list. %%%%site.name%%%% is the StatusNet site name,
// TRANS: %%%%action.groupsearch%%%% and %%%%action.newgroup%%%% are URLs. Do not change them.
// TRANS: This message contains Markdown links in the form [link text](link).
sprintf(_('%%%%site.name%%%% groups let you find and talk with ' . sprintf(_('%%%%site.name%%%% groups let you find and talk with ' .
'people of similar interests. After you join a group ' . 'people of similar interests. After you join a group ' .
'you can send messages to all other members using the ' . 'you can send messages to all other members using the ' .
'syntax "!groupname". Don\'t see a group you like? Try ' . 'syntax "!groupname". Don\'t see a group you like? Try ' .
'[searching for one](%%%%action.groupsearch%%%%) or ' . '[searching for one](%%%%action.groupsearch%%%%) or ' .
'[start your own!](%%%%action.newgroup%%%%)')); '[start your own](%%%%action.newgroup%%%%)!'));
$this->elementStart('div', 'instructions'); $this->elementStart('div', 'instructions');
$this->raw(common_markup_to_html($notice)); $this->raw(common_markup_to_html($notice));
$this->elementEnd('div'); $this->elementEnd('div');
@ -104,6 +109,7 @@ class GroupsAction extends Action
$this->elementStart('p', array('id' => 'new_group')); $this->elementStart('p', array('id' => 'new_group'));
$this->element('a', array('href' => common_local_url('newgroup'), $this->element('a', array('href' => common_local_url('newgroup'),
'class' => 'more'), 'class' => 'more'),
// TRANS: Link to create a new group on the group list page.
_('Create a new group')); _('Create a new group'));
$this->elementEnd('p'); $this->elementEnd('p');
} }

View File

@ -49,12 +49,14 @@ class GroupsearchAction extends SearchAction
{ {
function getInstructions() function getInstructions()
{ {
// TRANS: Instructions for page where groups can be searched. %%site.name%% is the name of the StatusNet site.
return _('Search for groups on %%site.name%% by their name, location, or description. ' . return _('Search for groups on %%site.name%% by their name, location, or description. ' .
'Separate the terms by spaces; they must be 3 characters or more.'); 'Separate the terms by spaces; they must be 3 characters or more.');
} }
function title() function title()
{ {
// TRANS: Title for page where groups can be searched.
return _('Group search'); return _('Group search');
} }
@ -76,12 +78,17 @@ class GroupsearchAction extends SearchAction
$this->pagination($page > 1, $cnt > GROUPS_PER_PAGE, $this->pagination($page > 1, $cnt > GROUPS_PER_PAGE,
$page, 'groupsearch', array('q' => $q)); $page, 'groupsearch', array('q' => $q));
} else { } else {
// TRANS: Text on page where groups can be searched if no results were found for a query.
$this->element('p', 'error', _('No results.')); $this->element('p', 'error', _('No results.'));
$this->searchSuggestions($q); $this->searchSuggestions($q);
if (common_logged_in()) { if (common_logged_in()) {
$message = _('If you can\'t find the group you\'re looking for, you can [create it](%%action.newgroup%%) yourself.'); // TRANS: Additional text on page where groups can be searched if no results were found for a query for a logged in user.
// TRANS: This message contains Markdown links in the form [link text](link).
$message = _('If you cannot find the group you\'re looking for, you can [create it](%%action.newgroup%%) yourself.');
} }
else { else {
// TRANS: Additional text on page where groups can be searched if no results were found for a query for a not logged in user.
// TRANS: This message contains Markdown links in the form [link text](link).
$message = _('Why not [register an account](%%action.register%%) and [create the group](%%action.newgroup%%) yourself!'); $message = _('Why not [register an account](%%action.register%%) and [create the group](%%action.newgroup%%) yourself!');
} }
$this->elementStart('div', 'guide'); $this->elementStart('div', 'guide');
@ -116,4 +123,3 @@ class GroupSearchResults extends GroupList
return preg_replace($this->pattern, '<strong>\\1</strong>', htmlspecialchars($text)); return preg_replace($this->pattern, '<strong>\\1</strong>', htmlspecialchars($text));
} }
} }

View File

@ -32,7 +32,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
} }
/** /**
* Unlock a user from a group * Unblock a user from a group
* *
* @category Action * @category Action
* @package StatusNet * @package StatusNet
@ -40,7 +40,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */
class GroupunblockAction extends Action class GroupunblockAction extends Action
{ {
var $profile = null; var $profile = null;
@ -53,11 +52,11 @@ class GroupunblockAction extends Action
* *
* @return boolean success flag * @return boolean success flag
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
if (!common_logged_in()) { if (!common_logged_in()) {
// TRANS: Client error displayed when trying to unblock a user from a group while not logged in.
$this->clientError(_('Not logged in.')); $this->clientError(_('Not logged in.'));
return false; return false;
} }
@ -68,30 +67,36 @@ class GroupunblockAction extends Action
} }
$id = $this->trimmed('unblockto'); $id = $this->trimmed('unblockto');
if (empty($id)) { if (empty($id)) {
// TRANS: Client error displayed when trying to unblock a user from a group without providing a profile.
$this->clientError(_('No profile specified.')); $this->clientError(_('No profile specified.'));
return false; return false;
} }
$this->profile = Profile::staticGet('id', $id); $this->profile = Profile::staticGet('id', $id);
if (empty($this->profile)) { if (empty($this->profile)) {
// TRANS: Client error displayed when trying to unblock a user from a group without providing an existing profile.
$this->clientError(_('No profile with that ID.')); $this->clientError(_('No profile with that ID.'));
return false; return false;
} }
$group_id = $this->trimmed('unblockgroup'); $group_id = $this->trimmed('unblockgroup');
if (empty($group_id)) { if (empty($group_id)) {
// TRANS: Client error displayed when trying to unblock a user from a group without providing a group.
$this->clientError(_('No group specified.')); $this->clientError(_('No group specified.'));
return false; return false;
} }
$this->group = User_group::staticGet('id', $group_id); $this->group = User_group::staticGet('id', $group_id);
if (empty($this->group)) { if (empty($this->group)) {
// TRANS: Client error displayed when trying to unblock a user from a non-existing group.
$this->clientError(_('No such group.')); $this->clientError(_('No such group.'));
return false; return false;
} }
$user = common_current_user(); $user = common_current_user();
if (!$user->isAdmin($this->group)) { if (!$user->isAdmin($this->group)) {
// TRANS: Client error displayed when trying to unblock a user from a group without being an administrator for the group.
$this->clientError(_('Only an admin can unblock group members.'), 401); $this->clientError(_('Only an admin can unblock group members.'), 401);
return false; return false;
} }
if (!Group_block::isBlocked($this->group, $this->profile)) { if (!Group_block::isBlocked($this->group, $this->profile)) {
// TRANS: Client error displayed when trying to unblock a non-blocked user from a group.
$this->clientError(_('User is not blocked from group.')); $this->clientError(_('User is not blocked from group.'));
return false; return false;
} }
@ -105,7 +110,6 @@ class GroupunblockAction extends Action
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
@ -119,12 +123,12 @@ class GroupunblockAction extends Action
* *
* @return void * @return void
*/ */
function unblockProfile() function unblockProfile()
{ {
$result = Group_block::unblockProfile($this->group, $this->profile); $result = Group_block::unblockProfile($this->group, $this->profile);
if (!$result) { if (!$result) {
// TRANS: Server error displayed when unblocking a user from a group fails because of an unknown error.
$this->serverError(_('Error removing the block.')); $this->serverError(_('Error removing the block.'));
return; return;
} }
@ -146,4 +150,3 @@ class GroupunblockAction extends Action
} }
} }
} }

View File

@ -40,7 +40,6 @@ if (!defined('STATUSNET')) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */
class HcardAction extends Action class HcardAction extends Action
{ {
var $user; var $user;
@ -64,6 +63,7 @@ class HcardAction extends Action
$this->user = User::staticGet('nickname', $nickname); $this->user = User::staticGet('nickname', $nickname);
if (!$this->user) { if (!$this->user) {
// TRANS: Client error displayed when trying to get a user hCard for a non-existing user.
$this->clientError(_('No such user.'), 404); $this->clientError(_('No such user.'), 404);
return false; return false;
} }
@ -71,6 +71,7 @@ class HcardAction extends Action
$this->profile = $this->user->getProfile(); $this->profile = $this->user->getProfile();
if (!$this->profile) { if (!$this->profile) {
// TRANS: Server error displayed when trying to get a user hCard for a user without a profile.
$this->serverError(_('User has no profile.')); $this->serverError(_('User has no profile.'));
return false; return false;
} }
@ -117,4 +118,4 @@ class ShortUserProfile extends UserProfile
{ {
return; return;
} }
} }

View File

@ -18,29 +18,46 @@
*/ */
/** /**
* @package OStatusPlugin * @category Action
* @package StatusNet
* @maintainer James Walker <james@status.net> * @maintainer James Walker <james@status.net>
* @author Craig Andrews <candrews@integralblue.com>
*/ */
if (!defined('STATUSNET')) { if (!defined('STATUSNET')) {
exit(1); exit(1);
} }
// @todo XXX: Add documentation.
class HostMetaAction extends Action class HostMetaAction extends Action
{ {
/**
* Is read only?
*
* @return boolean true
*/
function isReadOnly()
{
return true;
}
function handle() function handle()
{ {
parent::handle(); parent::handle();
$domain = common_config('site', 'server'); $domain = common_config('site', 'server');
$url = common_local_url('userxrd');
$url.= '?uri={uri}';
$xrd = new XRD(); $xrd = new XRD();
$xrd->host = $domain; $xrd->host = $domain;
$xrd->links[] = array('rel' => Discovery::LRDD_REL,
'template' => $url, if(Event::handle('StartHostMetaLinks', array(&$xrd->links))) {
'title' => array('Resource Descriptor')); $url = common_local_url('userxrd');
$url.= '?uri={uri}';
$xrd->links[] = array('rel' => Discovery::LRDD_REL,
'template' => $url,
'title' => array('Resource Descriptor'));
Event::handle('EndHostMetaLinks', array(&$xrd->links));
}
header('Content-type: application/xrd+xml'); header('Content-type: application/xrd+xml');
print $xrd->toXML(); print $xrd->toXML();

View File

@ -45,7 +45,6 @@ require_once INSTALLDIR.'/lib/jabber.php';
* *
* @see SettingsAction * @see SettingsAction
*/ */
class ImsettingsAction extends ConnectSettingsAction class ImsettingsAction extends ConnectSettingsAction
{ {
/** /**
@ -53,10 +52,9 @@ class ImsettingsAction extends ConnectSettingsAction
* *
* @return string Title of the page * @return string Title of the page
*/ */
function title() function title()
{ {
// TRANS: Title for instance messaging settings. // TRANS: Title for Instant Messaging settings.
return _('IM settings'); return _('IM settings');
} }
@ -65,14 +63,13 @@ class ImsettingsAction extends ConnectSettingsAction
* *
* @return instructions for use * @return instructions for use
*/ */
function getInstructions() function getInstructions()
{ {
// TRANS: Instant messaging settings page instructions. // TRANS: Instant messaging settings page instructions.
// TRANS: [instant messages] is link text, "(%%doc.im%%)" is the link. // TRANS: [instant messages] is link text, "(%%doc.im%%)" is the link.
// TRANS: the order and formatting of link text and link should remain unchanged. // TRANS: the order and formatting of link text and link should remain unchanged.
return _('You can send and receive notices through '. return _('You can send and receive notices through '.
'Jabber/GTalk [instant messages](%%doc.im%%). '. 'Jabber/Google Talk [instant messages](%%doc.im%%). '.
'Configure your address and settings below.'); 'Configure your address and settings below.');
} }
@ -85,12 +82,11 @@ class ImsettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function showContent() function showContent()
{ {
if (!common_config('xmpp', 'enabled')) { if (!common_config('xmpp', 'enabled')) {
$this->element('div', array('class' => 'error'), $this->element('div', array('class' => 'error'),
// TRANS: Message given in the IM settings if XMPP is not enabled on the site. // TRANS: Message given in the Instant Messaging settings if XMPP is not enabled on the site.
_('IM is not available.')); _('IM is not available.'));
return; return;
} }
@ -102,88 +98,88 @@ class ImsettingsAction extends ConnectSettingsAction
'action' => 'action' =>
common_local_url('imsettings'))); common_local_url('imsettings')));
$this->elementStart('fieldset', array('id' => 'settings_im_address')); $this->elementStart('fieldset', array('id' => 'settings_im_address'));
// TRANS: Form legend for IM settings form. // TRANS: Form legend for Instant Messaging settings form.
$this->element('legend', null, _('IM address')); $this->element('legend', null, _('IM address'));
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
if ($user->jabber) { if ($user->jabber) {
$this->element('p', 'form_confirmed', $user->jabber); $this->element('p', 'form_confirmed', $user->jabber);
// TRANS: Form note in IM settings form. // TRANS: Form note in Instant Messaging settings form.
$this->element('p', 'form_note', $this->element('p', 'form_note',
_('Current confirmed Jabber/GTalk address.')); _('Current confirmed Jabber/Google Talk address.'));
$this->hidden('jabber', $user->jabber); $this->hidden('jabber', $user->jabber);
// TRANS: Button label to remove a confirmed IM address. // TRANS: Button label to remove a confirmed Instant Messaging address.
$this->submit('remove', _m('BUTTON','Remove')); $this->submit('remove', _m('BUTTON','Remove'));
} else { } else {
$confirm = $this->getConfirmation(); $confirm = $this->getConfirmation();
if ($confirm) { if ($confirm) {
$this->element('p', 'form_unconfirmed', $confirm->address); $this->element('p', 'form_unconfirmed', $confirm->address);
$this->element('p', 'form_note', $this->element('p', 'form_note',
// TRANS: Form note in IM settings form. // TRANS: Form note in Instant Messaging settings form.
// TRANS: %s is the IM address set for the site. // TRANS: %s is the Instant Messaging address set for the site.
sprintf(_('Awaiting confirmation on this address. '. sprintf(_('Awaiting confirmation on this address. '.
'Check your Jabber/GTalk account for a '. 'Check your Jabber/Google Talk account for a '.
'message with further instructions. '. 'message with further instructions. '.
'(Did you add %s to your buddy list?)'), '(Did you add %s to your buddy list?)'),
jabber_daemon_address())); jabber_daemon_address()));
$this->hidden('jabber', $confirm->address); $this->hidden('jabber', $confirm->address);
// TRANS: Button label to cancel an IM address confirmation procedure. // TRANS: Button label to cancel an Instant Messaging address confirmation procedure.
$this->submit('cancel', _m('BUTTON','Cancel')); $this->submit('cancel', _m('BUTTON','Cancel'));
} else { } else {
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Field label for IM address input in IM settings form. // TRANS: Field label for Instant Messaging address input in Instant Messaging settings form.
$this->input('jabber', _('IM address'), $this->input('jabber', _('IM address'),
($this->arg('jabber')) ? $this->arg('jabber') : null, ($this->arg('jabber')) ? $this->arg('jabber') : null,
// TRANS: IM address input field instructions in IM settings form. // TRANS: IM address input field instructions in Instant Messaging settings form.
// TRANS: %s is the IM address set for the site. // TRANS: %s is the Instant Messaging address set for the site.
// TRANS: Do not translate "example.org". It is one of the domain names reserved for use in examples by // TRANS: Do not translate "example.org". It is one of the domain names reserved for use in examples by
// TRANS: http://www.rfc-editor.org/rfc/rfc2606.txt. Any other domain may be owned by a legitimate // TRANS: http://www.rfc-editor.org/rfc/rfc2606.txt. Any other domain may be owned by a legitimate
// TRANS: person or organization. // TRANS: person or organization.
sprintf(_('Jabber or GTalk address, '. sprintf(_('Jabber or Google Talk address, '.
'like "UserName@example.org". '. 'like "UserName@example.org". '.
'First, make sure to add %s to your '. 'First, make sure to add %s to your '.
'buddy list in your IM client or on GTalk.'), 'buddy list in your IM client or on Google Talk.'),
jabber_daemon_address())); jabber_daemon_address()));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
// TRANS: Button label for adding an IM address in IM settings form. // TRANS: Button label for adding an Instant Messaging address in Instant Messaging settings form.
$this->submit('add', _m('BUTTON','Add')); $this->submit('add', _m('BUTTON','Add'));
} }
} }
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementStart('fieldset', array('id' => 'settings_im_preferences')); $this->elementStart('fieldset', array('id' => 'settings_im_preferences'));
// TRANS: Form legend for IM preferences form. // TRANS: Form legend for Instant Messaging preferences form.
$this->element('legend', null, _('IM preferences')); $this->element('legend', null, _('IM preferences'));
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('jabbernotify', $this->checkbox('jabbernotify',
// TRANS: Checkbox label in IM preferences form. // TRANS: Checkbox label in Instant Messaging preferences form.
_('Send me notices through Jabber/GTalk.'), _('Send me notices through Jabber/Google Talk.'),
$user->jabbernotify); $user->jabbernotify);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('updatefrompresence', $this->checkbox('updatefrompresence',
// TRANS: Checkbox label in IM preferences form. // TRANS: Checkbox label in Instant Messaging preferences form.
_('Post a notice when my Jabber/GTalk status changes.'), _('Post a notice when my Jabber/Google Talk status changes.'),
$user->updatefrompresence); $user->updatefrompresence);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('jabberreplies', $this->checkbox('jabberreplies',
// TRANS: Checkbox label in IM preferences form. // TRANS: Checkbox label in Instant Messaging preferences form.
_('Send me replies through Jabber/GTalk '. _('Send me replies through Jabber/Google Talk '.
'from people I\'m not subscribed to.'), 'from people I\'m not subscribed to.'),
$user->jabberreplies); $user->jabberreplies);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('jabbermicroid', $this->checkbox('jabbermicroid',
// TRANS: Checkbox label in IM preferences form. // TRANS: Checkbox label in Instant Messaging preferences form.
_('Publish a MicroID for my Jabber/GTalk address.'), _('Publish a MicroID for my Jabber/Google Talk address.'),
$user->jabbermicroid); $user->jabbermicroid);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
// TRANS: Button label to save IM preferences. // TRANS: Button label to save Instant Messaging preferences.
$this->submit('save', _m('BUTTON','Save')); $this->submit('save', _m('BUTTON','Save'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
@ -194,7 +190,6 @@ class ImsettingsAction extends ConnectSettingsAction
* *
* @return Confirm_address address object for this user * @return Confirm_address address object for this user
*/ */
function getConfirmation() function getConfirmation()
{ {
$user = common_current_user(); $user = common_current_user();
@ -221,7 +216,6 @@ class ImsettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function handlePost() function handlePost()
{ {
// CSRF protection // CSRF protection
@ -241,7 +235,7 @@ class ImsettingsAction extends ConnectSettingsAction
} else if ($this->arg('remove')) { } else if ($this->arg('remove')) {
$this->removeAddress(); $this->removeAddress();
} else { } else {
// TRANS: Message given submitting a form with an unknown action in IM settings. // TRANS: Message given submitting a form with an unknown action in Instant Messaging settings.
$this->showForm(_('Unexpected form submission.')); $this->showForm(_('Unexpected form submission.'));
} }
} }
@ -254,7 +248,6 @@ class ImsettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function savePreferences() function savePreferences()
{ {
$jabbernotify = $this->boolean('jabbernotify'); $jabbernotify = $this->boolean('jabbernotify');
@ -279,14 +272,14 @@ class ImsettingsAction extends ConnectSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error updating IM preferences. // TRANS: Server error thrown on database error updating Instant Messaging preferences.
$this->serverError(_('Couldn\'t update user.')); $this->serverError(_('Could not update user.'));
return; return;
} }
$user->query('COMMIT'); $user->query('COMMIT');
// TRANS: Confirmation message for successful IM preferences save. // TRANS: Confirmation message for successful Instant Messaging preferences save.
$this->showForm(_('Preferences saved.'), true); $this->showForm(_('Preferences saved.'), true);
} }
@ -298,7 +291,6 @@ class ImsettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function addAddress() function addAddress()
{ {
$user = common_current_user(); $user = common_current_user();
@ -308,7 +300,7 @@ class ImsettingsAction extends ConnectSettingsAction
// Some validation // Some validation
if (!$jabber) { if (!$jabber) {
// TRANS: Message given saving IM address without having provided one. // TRANS: Message given saving Instant Messaging address without having provided one.
$this->showForm(_('No Jabber ID.')); $this->showForm(_('No Jabber ID.'));
return; return;
} }
@ -316,20 +308,20 @@ class ImsettingsAction extends ConnectSettingsAction
$jabber = jabber_normalize_jid($jabber); $jabber = jabber_normalize_jid($jabber);
if (!$jabber) { if (!$jabber) {
// TRANS: Message given saving IM address that cannot be normalised. // TRANS: Message given saving Instant Messaging address that cannot be normalised.
$this->showForm(_('Cannot normalize that Jabber ID')); $this->showForm(_('Cannot normalize that Jabber ID.'));
return; return;
} }
if (!jabber_valid_base_jid($jabber, common_config('email', 'domain_check'))) { if (!jabber_valid_base_jid($jabber, common_config('email', 'domain_check'))) {
// TRANS: Message given saving IM address that not valid. // TRANS: Message given saving Instant Messaging address that not valid.
$this->showForm(_('Not a valid Jabber ID')); $this->showForm(_('Not a valid Jabber ID.'));
return; return;
} else if ($user->jabber == $jabber) { } else if ($user->jabber == $jabber) {
// TRANS: Message given saving IM address that is already set. // TRANS: Message given saving Instant Messaging address that is already set.
$this->showForm(_('That is already your Jabber ID.')); $this->showForm(_('That is already your Jabber ID.'));
return; return;
} else if ($this->jabberExists($jabber)) { } else if ($this->jabberExists($jabber)) {
// TRANS: Message given saving IM address that is already set for another user. // TRANS: Message given saving Instant Messaging address that is already set for another user.
$this->showForm(_('Jabber ID already belongs to another user.')); $this->showForm(_('Jabber ID already belongs to another user.'));
return; return;
} }
@ -347,8 +339,8 @@ class ImsettingsAction extends ConnectSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($confirm, 'INSERT', __FILE__); common_log_db_error($confirm, 'INSERT', __FILE__);
// TRANS: Server error thrown on database error adding IM confirmation code. // TRANS: Server error thrown on database error adding Instant Messaging confirmation code.
$this->serverError(_('Couldn\'t insert confirmation code.')); $this->serverError(_('Could not insert confirmation code.'));
return; return;
} }
@ -356,8 +348,8 @@ class ImsettingsAction extends ConnectSettingsAction
$user->nickname, $user->nickname,
$jabber); $jabber);
// TRANS: Message given saving valid IM address that is to be confirmed. // TRANS: Message given saving valid Instant Messaging address that is to be confirmed.
// TRANS: %s is the IM address set for the site. // TRANS: %s is the Instant Messaging address set for the site.
$msg = sprintf(_('A confirmation code was sent '. $msg = sprintf(_('A confirmation code was sent '.
'to the IM address you added. '. 'to the IM address you added. '.
'You must approve %s for '. 'You must approve %s for '.
@ -374,7 +366,6 @@ class ImsettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function cancelConfirmation() function cancelConfirmation()
{ {
$jabber = $this->arg('jabber'); $jabber = $this->arg('jabber');
@ -382,12 +373,12 @@ class ImsettingsAction extends ConnectSettingsAction
$confirm = $this->getConfirmation(); $confirm = $this->getConfirmation();
if (!$confirm) { if (!$confirm) {
// TRANS: Message given canceling IM address confirmation that is not pending. // TRANS: Message given canceling Instant Messaging address confirmation that is not pending.
$this->showForm(_('No pending confirmation to cancel.')); $this->showForm(_('No pending confirmation to cancel.'));
return; return;
} }
if ($confirm->address != $jabber) { if ($confirm->address != $jabber) {
// TRANS: Message given canceling IM address confirmation for the wrong IM address. // TRANS: Message given canceling Instant Messaging address confirmation for the wrong IM address.
$this->showForm(_('That is the wrong IM address.')); $this->showForm(_('That is the wrong IM address.'));
return; return;
} }
@ -396,12 +387,12 @@ class ImsettingsAction extends ConnectSettingsAction
if (!$result) { if (!$result) {
common_log_db_error($confirm, 'DELETE', __FILE__); common_log_db_error($confirm, 'DELETE', __FILE__);
// TRANS: Server error thrown on database error canceling IM address confirmation. // TRANS: Server error thrown on database error canceling Instant Messaging address confirmation.
$this->serverError(_('Couldn\'t delete IM confirmation.')); $this->serverError(_('Could not delete IM confirmation.'));
return; return;
} }
// TRANS: Message given after successfully canceling IM address confirmation. // TRANS: Message given after successfully canceling Instant Messaging address confirmation.
$this->showForm(_('IM confirmation cancelled.'), true); $this->showForm(_('IM confirmation cancelled.'), true);
} }
@ -412,7 +403,6 @@ class ImsettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function removeAddress() function removeAddress()
{ {
$user = common_current_user(); $user = common_current_user();
@ -422,7 +412,7 @@ class ImsettingsAction extends ConnectSettingsAction
// Maybe an old tab open...? // Maybe an old tab open...?
if ($user->jabber != $jabber) { if ($user->jabber != $jabber) {
// TRANS: Message given trying to remove an IM address that is not // TRANS: Message given trying to remove an Instant Messaging address that is not
// TRANS: registered for the active user. // TRANS: registered for the active user.
$this->showForm(_('That is not your Jabber ID.')); $this->showForm(_('That is not your Jabber ID.'));
return; return;
@ -438,15 +428,15 @@ class ImsettingsAction extends ConnectSettingsAction
if (!$result) { if (!$result) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error removing a registered IM address. // TRANS: Server error thrown on database error removing a registered Instant Messaging address.
$this->serverError(_('Couldn\'t update user.')); $this->serverError(_('Could not update user.'));
return; return;
} }
$user->query('COMMIT'); $user->query('COMMIT');
// XXX: unsubscribe to the old address // XXX: unsubscribe to the old address
// TRANS: Message given after successfully removing a registered IM address. // TRANS: Message given after successfully removing a registered Instant Messaging address.
$this->showForm(_('The IM address was removed.'), true); $this->showForm(_('The IM address was removed.'), true);
} }
@ -459,7 +449,6 @@ class ImsettingsAction extends ConnectSettingsAction
* *
* @return boolean whether the Jabber ID exists * @return boolean whether the Jabber ID exists
*/ */
function jabberExists($jabber) function jabberExists($jabber)
{ {
$user = common_current_user(); $user = common_current_user();

View File

@ -43,7 +43,6 @@ require_once INSTALLDIR.'/lib/mailbox.php';
* @link http://status.net/ * @link http://status.net/
* @see MailboxAction * @see MailboxAction
*/ */
class InboxAction extends MailboxAction class InboxAction extends MailboxAction
{ {
@ -52,13 +51,16 @@ class InboxAction extends MailboxAction
* *
* @return string page title * @return string page title
*/ */
function title() function title()
{ {
if ($this->page > 1) { if ($this->page > 1) {
// TRANS: Title for all but the first page of the inbox page.
// TRANS: %1$s is the user's nickname, %2$s is the page number.
return sprintf(_('Inbox for %1$s - page %2$d'), $this->user->nickname, return sprintf(_('Inbox for %1$s - page %2$d'), $this->user->nickname,
$this->page); $this->page);
} else { } else {
// TRANS: Title for the first page of the inbox page.
// TRANS: %s is the user's nickname.
return sprintf(_('Inbox for %s'), $this->user->nickname); return sprintf(_('Inbox for %s'), $this->user->nickname);
} }
} }
@ -72,7 +74,6 @@ class InboxAction extends MailboxAction
* *
* @see MailboxAction::getMessages() * @see MailboxAction::getMessages()
*/ */
function getMessages() function getMessages()
{ {
$message = new Message(); $message = new Message();
@ -89,19 +90,9 @@ class InboxAction extends MailboxAction
} }
} }
/** function getMessageList($message)
* Returns the profile we want to show with the message
*
* For inboxes, we show the sender; for outboxes, the recipient.
*
* @param Message $message The message to get the profile for
*
* @return Profile The profile that matches the message
*/
function getMessageProfile($message)
{ {
return $message->getFrom(); return new InboxMessageList($this, $message);
} }
/** /**
@ -109,9 +100,30 @@ class InboxAction extends MailboxAction
* *
* @return string localised instructions for using the page * @return string localised instructions for using the page
*/ */
function getInstructions() function getInstructions()
{ {
// TRANS: Instructions for user inbox page.
return _('This is your inbox, which lists your incoming private messages.'); return _('This is your inbox, which lists your incoming private messages.');
} }
} }
class InboxMessageList extends MessageList
{
function newItem($message)
{
return new InboxMessageListItem($this->out, $message);
}
}
class InboxMessageListItem extends MessageListItem
{
/**
* Returns the profile we want to show with the message
*
* @return Profile The profile that matches the message
*/
function getMessageProfile()
{
return $this->message->getFrom();
}
}

View File

@ -19,6 +19,7 @@
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
// @todo XXX: Add documentation.
class InviteAction extends CurrentUserDesignAction class InviteAction extends CurrentUserDesignAction
{ {
var $mode = null; var $mode = null;
@ -142,7 +143,7 @@ class InviteAction extends CurrentUserDesignAction
$this->elementStart('ul'); $this->elementStart('ul');
foreach ($this->already as $other) { foreach ($this->already as $other) {
// TRANS: Used as list item for already subscribed users (%1$s is nickname, %2$s is e-mail address). // TRANS: Used as list item for already subscribed users (%1$s is nickname, %2$s is e-mail address).
$this->element('li', null, sprintf(_('%1$s (%2$s)'), $other->nickname, $other->email)); $this->element('li', null, sprintf(_m('INVITE','%1$s (%2$s)'), $other->nickname, $other->email));
} }
$this->elementEnd('ul'); $this->elementEnd('ul');
} }
@ -156,7 +157,7 @@ class InviteAction extends CurrentUserDesignAction
$this->elementStart('ul'); $this->elementStart('ul');
foreach ($this->subbed as $other) { foreach ($this->subbed as $other) {
// TRANS: Used as list item for already registered people (%1$s is nickname, %2$s is e-mail address). // TRANS: Used as list item for already registered people (%1$s is nickname, %2$s is e-mail address).
$this->element('li', null, sprintf(_('%1$s (%2$s)'), $other->nickname, $other->email)); $this->element('li', null, sprintf(_m('INVITE','%1$s (%2$s)'), $other->nickname, $other->email));
} }
$this->elementEnd('ul'); $this->elementEnd('ul');
} }
@ -217,7 +218,7 @@ class InviteAction extends CurrentUserDesignAction
$this->textarea('addresses', _('Email addresses'), $this->textarea('addresses', _('Email addresses'),
$this->trimmed('addresses'), $this->trimmed('addresses'),
// TRANS: Tooltip for field label for a list of e-mail addresses. // TRANS: Tooltip for field label for a list of e-mail addresses.
_('Addresses of friends to invite (one per line)')); _('Addresses of friends to invite (one per line).'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Field label for a personal message to send to invitees. // TRANS: Field label for a personal message to send to invitees.

View File

@ -43,7 +43,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class JoingroupAction extends Action class JoingroupAction extends Action
{ {
var $group = null; var $group = null;
@ -51,12 +50,12 @@ class JoingroupAction extends Action
/** /**
* Prepare to run * Prepare to run
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
if (!common_logged_in()) { if (!common_logged_in()) {
// TRANS: Client error displayed when trying to join a group while not logged in.
$this->clientError(_('You must be logged in to join a group.')); $this->clientError(_('You must be logged in to join a group.'));
return false; return false;
} }
@ -79,17 +78,20 @@ class JoingroupAction extends Action
$local = Local_group::staticGet('nickname', $nickname); $local = Local_group::staticGet('nickname', $nickname);
if (!$local) { if (!$local) {
// TRANS: Client error displayed when trying to join a non-local group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
$this->group = User_group::staticGet('id', $local->group_id); $this->group = User_group::staticGet('id', $local->group_id);
} else { } else {
// TRANS: Client error displayed when trying to join a group without providing a group name or group ID.
$this->clientError(_('No nickname or ID.'), 404); $this->clientError(_('No nickname or ID.'), 404);
return false; return false;
} }
if (!$this->group) { if (!$this->group) {
// TRANS: Client error displayed when trying to join a non-existing group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -97,11 +99,13 @@ class JoingroupAction extends Action
$cur = common_current_user(); $cur = common_current_user();
if ($cur->isMember($this->group)) { if ($cur->isMember($this->group)) {
// TRANS: Client error displayed when trying to join a group while already a member.
$this->clientError(_('You are already a member of that group.'), 403); $this->clientError(_('You are already a member of that group.'), 403);
return false; return false;
} }
if (Group_block::isBlocked($this->group, $cur->getProfile())) { if (Group_block::isBlocked($this->group, $cur->getProfile())) {
// TRANS: Client error displayed when trying to join a group while being blocked form joining it.
$this->clientError(_('You have been blocked from that group by the admin.'), 403); $this->clientError(_('You have been blocked from that group by the admin.'), 403);
return false; return false;
} }
@ -118,7 +122,6 @@ class JoingroupAction extends Action
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
@ -131,6 +134,8 @@ class JoingroupAction extends Action
Event::handle('EndJoinGroup', array($this->group, $cur)); Event::handle('EndJoinGroup', array($this->group, $cur));
} }
} catch (Exception $e) { } catch (Exception $e) {
// TRANS: Server error displayed when joining a group failed in the database.
// TRANS: %1$s is the joining user's nickname, $2$s is the group nickname for which the join failed.
$this->serverError(sprintf(_('Could not join user %1$s to group %2$s.'), $this->serverError(sprintf(_('Could not join user %1$s to group %2$s.'),
$cur->nickname, $this->group->nickname)); $cur->nickname, $this->group->nickname));
} }
@ -138,7 +143,8 @@ class JoingroupAction extends Action
if ($this->boolean('ajax')) { if ($this->boolean('ajax')) {
$this->startHTML('text/xml;charset=utf-8'); $this->startHTML('text/xml;charset=utf-8');
$this->elementStart('head'); $this->elementStart('head');
$this->element('title', null, sprintf(_('%1$s joined group %2$s'), // TRANS: Title for join group page after joining.
$this->element('title', null, sprintf(_m('TITLE','%1$s joined group %2$s'),
$cur->nickname, $cur->nickname,
$this->group->nickname)); $this->group->nickname));
$this->elementEnd('head'); $this->elementEnd('head');
@ -153,4 +159,4 @@ class JoingroupAction extends Action
303); 303);
} }
} }
} }

View File

@ -43,7 +43,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class LeavegroupAction extends Action class LeavegroupAction extends Action
{ {
var $group = null; var $group = null;
@ -51,12 +50,12 @@ class LeavegroupAction extends Action
/** /**
* Prepare to run * Prepare to run
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
if (!common_logged_in()) { if (!common_logged_in()) {
// TRANS: Client error displayed when trying to leave a group while not logged in.
$this->clientError(_('You must be logged in to leave a group.')); $this->clientError(_('You must be logged in to leave a group.'));
return false; return false;
} }
@ -79,17 +78,20 @@ class LeavegroupAction extends Action
$local = Local_group::staticGet('nickname', $nickname); $local = Local_group::staticGet('nickname', $nickname);
if (!$local) { if (!$local) {
// TRANS: Client error displayed when trying to leave a non-local group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
$this->group = User_group::staticGet('id', $local->group_id); $this->group = User_group::staticGet('id', $local->group_id);
} else { } else {
// TRANS: Client error displayed when trying to leave a group without providing a group name or group ID.
$this->clientError(_('No nickname or ID.'), 404); $this->clientError(_('No nickname or ID.'), 404);
return false; return false;
} }
if (!$this->group) { if (!$this->group) {
// TRANS: Client error displayed when trying to leave a non-existing group.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -97,6 +99,7 @@ class LeavegroupAction extends Action
$cur = common_current_user(); $cur = common_current_user();
if (!$cur->isMember($this->group)) { if (!$cur->isMember($this->group)) {
// TRANS: Client error displayed when trying to join a group while already a member.
$this->clientError(_('You are not a member of that group.'), 403); $this->clientError(_('You are not a member of that group.'), 403);
return false; return false;
} }
@ -113,7 +116,6 @@ class LeavegroupAction extends Action
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
@ -126,6 +128,8 @@ class LeavegroupAction extends Action
Event::handle('EndLeaveGroup', array($this->group, $cur)); Event::handle('EndLeaveGroup', array($this->group, $cur));
} }
} catch (Exception $e) { } catch (Exception $e) {
// TRANS: Server error displayed when leaving a group failed in the database.
// TRANS: %1$s is the leaving user's nickname, $2$s is the group nickname for which the leave failed.
$this->serverError(sprintf(_('Could not remove user %1$s from group %2$s.'), $this->serverError(sprintf(_('Could not remove user %1$s from group %2$s.'),
$cur->nickname, $this->group->nickname)); $cur->nickname, $this->group->nickname));
return; return;
@ -134,7 +138,8 @@ class LeavegroupAction extends Action
if ($this->boolean('ajax')) { if ($this->boolean('ajax')) {
$this->startHTML('text/xml;charset=utf-8'); $this->startHTML('text/xml;charset=utf-8');
$this->elementStart('head'); $this->elementStart('head');
$this->element('title', null, sprintf(_('%1$s left group %2$s'), // TRANS: Title for leave group page after leaving.
$this->element('title', null, sprintf(_m('TITLE','%1$s left group %2$s'),
$cur->nickname, $cur->nickname,
$this->group->nickname)); $this->group->nickname));
$this->elementEnd('head'); $this->elementEnd('head');

View File

@ -40,7 +40,6 @@ if (!defined('STATUSNET')) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class LicenseadminpanelAction extends AdminPanelAction class LicenseadminpanelAction extends AdminPanelAction
{ {
@ -61,7 +60,6 @@ class LicenseadminpanelAction extends AdminPanelAction
* *
* @return string instructions * @return string instructions
*/ */
function getInstructions() function getInstructions()
{ {
return _('License for this StatusNet site'); return _('License for this StatusNet site');
@ -72,7 +70,6 @@ class LicenseadminpanelAction extends AdminPanelAction
* *
* @return void * @return void
*/ */
function showForm() function showForm()
{ {
$form = new LicenseAdminPanelForm($this); $form = new LicenseAdminPanelForm($this);
@ -85,7 +82,6 @@ class LicenseadminpanelAction extends AdminPanelAction
* *
* @return void * @return void
*/ */
function saveSettings() function saveSettings()
{ {
static $settings = array( static $settings = array(
@ -128,7 +124,6 @@ class LicenseadminpanelAction extends AdminPanelAction
* *
* @return nothing * @return nothing
*/ */
function validate(&$values) function validate(&$values)
{ {
// Validate license type (shouldn't have to do it, but just in case) // Validate license type (shouldn't have to do it, but just in case)
@ -153,7 +148,7 @@ class LicenseadminpanelAction extends AdminPanelAction
// Make sure the license title is not too long // Make sure the license title is not too long
if (mb_strlen($values['license']['type']) > 255) { if (mb_strlen($values['license']['type']) > 255) {
$this->clientError( $this->clientError(
_("Invalid license title. Max length is 255 characters.") _('Invalid license title. Maximum length is 255 characters.')
); );
} }
@ -197,7 +192,6 @@ class LicenseAdminPanelForm extends AdminForm
* *
* @return int ID of the form * @return int ID of the form
*/ */
function id() function id()
{ {
return 'licenseadminpanel'; return 'licenseadminpanel';
@ -208,7 +202,6 @@ class LicenseAdminPanelForm extends AdminForm
* *
* @return string class of the form * @return string class of the form
*/ */
function formClass() function formClass()
{ {
return 'form_settings'; return 'form_settings';
@ -312,7 +305,6 @@ class LicenseAdminPanelForm extends AdminForm
* *
* @return void * @return void
*/ */
function formActions() function formActions()
{ {
$this->out->submit( $this->out->submit(

View File

@ -55,7 +55,6 @@ class NewApplicationAction extends OwnerDesignAction
/** /**
* Prepare to run * Prepare to run
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
@ -78,7 +77,6 @@ class NewApplicationAction extends OwnerDesignAction
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
@ -122,6 +120,7 @@ class NewApplicationAction extends OwnerDesignAction
} elseif ($this->arg('save')) { } elseif ($this->arg('save')) {
$this->trySave(); $this->trySave();
} else { } else {
// TRANS: Client error displayed when encountering an unexpected action on form submission.
$this->clientError(_('Unexpected form submission.')); $this->clientError(_('Unexpected form submission.'));
} }
} }
@ -144,6 +143,7 @@ class NewApplicationAction extends OwnerDesignAction
$this->element('p', 'error', $this->msg); $this->element('p', 'error', $this->msg);
} else { } else {
$this->element('p', 'instructions', $this->element('p', 'instructions',
// TRANS: Form instructions for registering a new application.
_('Use this form to register a new application.')); _('Use this form to register a new application.'));
} }
} }
@ -160,15 +160,19 @@ class NewApplicationAction extends OwnerDesignAction
$access_type = $this->arg('default_access_type'); $access_type = $this->arg('default_access_type');
if (empty($name)) { if (empty($name)) {
// TRANS: Validation error shown when not providing a name in the "New application" form.
$this->showForm(_('Name is required.')); $this->showForm(_('Name is required.'));
return; return;
} else if ($this->nameExists($name)) { } else if ($this->nameExists($name)) {
// TRANS: Validation error shown when providing a name for an application that already exists in the "New application" form.
$this->showForm(_('Name already in use. Try another one.')); $this->showForm(_('Name already in use. Try another one.'));
return; return;
} elseif (mb_strlen($name) > 255) { } elseif (mb_strlen($name) > 255) {
$this->showForm(_('Name is too long (maximum 255 chars).')); // TRANS: Validation error shown when providing too long a name in the "New application" form.
$this->showForm(_('Name is too long (maximum 255 characters).'));
return; return;
} elseif (empty($description)) { } elseif (empty($description)) {
// TRANS: Validation error shown when not providing a description in the "New application" form.
$this->showForm(_('Description is required.')); $this->showForm(_('Description is required.'));
return; return;
} elseif (Oauth_application::descriptionTooLong($description)) { } elseif (Oauth_application::descriptionTooLong($description)) {
@ -181,6 +185,7 @@ class NewApplicationAction extends OwnerDesignAction
Oauth_application::maxDesc())); Oauth_application::maxDesc()));
return; return;
} elseif (empty($source_url)) { } elseif (empty($source_url)) {
// TRANS: Validation error shown when not providing a source URL in the "New application" form.
$this->showForm(_('Source URL is required.')); $this->showForm(_('Source URL is required.'));
return; return;
} elseif ((strlen($source_url) > 0) } elseif ((strlen($source_url) > 0)
@ -190,15 +195,19 @@ class NewApplicationAction extends OwnerDesignAction
) )
) )
{ {
// TRANS: Validation error shown when providing an invalid source URL in the "New application" form.
$this->showForm(_('Source URL is not valid.')); $this->showForm(_('Source URL is not valid.'));
return; return;
} elseif (empty($organization)) { } elseif (empty($organization)) {
// TRANS: Validation error shown when not providing an organisation in the "New application" form.
$this->showForm(_('Organization is required.')); $this->showForm(_('Organization is required.'));
return; return;
} elseif (mb_strlen($organization) > 255) { } elseif (mb_strlen($organization) > 255) {
$this->showForm(_('Organization is too long (maximum 255 chars).')); // TRANS: Validation error shown when providing too long an arganisation name in the "Edit application" form.
$this->showForm(_('Organization is too long (maximum 255 characters).'));
return; return;
} elseif (empty($homepage)) { } elseif (empty($homepage)) {
// TRANS: Form validation error show when an organisation name has not been provided in the new application form.
$this->showForm(_('Organization homepage is required.')); $this->showForm(_('Organization homepage is required.'));
return; return;
} elseif ((strlen($homepage) > 0) } elseif ((strlen($homepage) > 0)
@ -208,9 +217,11 @@ class NewApplicationAction extends OwnerDesignAction
) )
) )
{ {
// TRANS: Validation error shown when providing an invalid homepage URL in the "New application" form.
$this->showForm(_('Homepage is not a valid URL.')); $this->showForm(_('Homepage is not a valid URL.'));
return; return;
} elseif (mb_strlen($callback_url) > 255) { } elseif (mb_strlen($callback_url) > 255) {
// TRANS: Validation error shown when providing too long a callback URL in the "New application" form.
$this->showForm(_('Callback is too long.')); $this->showForm(_('Callback is too long.'));
return; return;
} elseif (strlen($callback_url) > 0 } elseif (strlen($callback_url) > 0
@ -220,6 +231,7 @@ class NewApplicationAction extends OwnerDesignAction
) )
) )
{ {
// TRANS: Validation error shown when providing an invalid callback URL in the "New application" form.
$this->showForm(_('Callback URL is not valid.')); $this->showForm(_('Callback URL is not valid.'));
return; return;
} }
@ -263,6 +275,7 @@ class NewApplicationAction extends OwnerDesignAction
if (!$result) { if (!$result) {
common_log_db_error($consumer, 'INSERT', __FILE__); common_log_db_error($consumer, 'INSERT', __FILE__);
// TRANS: Server error displayed when an application could not be registered in the database through the "New application" form.
$this->serverError(_('Could not create application.')); $this->serverError(_('Could not create application.'));
} }
@ -272,6 +285,7 @@ class NewApplicationAction extends OwnerDesignAction
if (!$this->app_id) { if (!$this->app_id) {
common_log_db_error($app, 'INSERT', __FILE__); common_log_db_error($app, 'INSERT', __FILE__);
// TRANS: Server error displayed when an application could not be registered in the database through the "New application" form.
$this->serverError(_('Could not create application.')); $this->serverError(_('Could not create application.'));
$app->query('ROLLBACK'); $app->query('ROLLBACK');
} }
@ -281,7 +295,6 @@ class NewApplicationAction extends OwnerDesignAction
$app->query('COMMIT'); $app->query('COMMIT');
common_redirect(common_local_url('oauthappssettings'), 303); common_redirect(common_local_url('oauthappssettings'), 303);
} }
/** /**
@ -294,12 +307,9 @@ class NewApplicationAction extends OwnerDesignAction
* *
* @return boolean true if the name already exists * @return boolean true if the name already exists
*/ */
function nameExists($name) function nameExists($name)
{ {
$app = Oauth_application::staticGet('name', $name); $app = Oauth_application::staticGet('name', $name);
return !empty($app); return !empty($app);
} }
} }

View File

@ -43,25 +43,25 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class NewgroupAction extends Action class NewgroupAction extends Action
{ {
var $msg; var $msg;
function title() function title()
{ {
// TRANS: Title for form to create a group.
return _('New group'); return _('New group');
} }
/** /**
* Prepare to run * Prepare to run
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
if (!common_logged_in()) { if (!common_logged_in()) {
// TRANS: Client error displayed trying to create a group while not logged in.
$this->clientError(_('You must be logged in to create a group.')); $this->clientError(_('You must be logged in to create a group.'));
return false; return false;
} }
@ -85,7 +85,6 @@ class NewgroupAction extends Action
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
@ -114,107 +113,116 @@ class NewgroupAction extends Action
$this->element('p', 'error', $this->msg); $this->element('p', 'error', $this->msg);
} else { } else {
$this->element('p', 'instructions', $this->element('p', 'instructions',
// TRANS: Form instructions for group create form.
_('Use this form to create a new group.')); _('Use this form to create a new group.'));
} }
} }
function trySave() function trySave()
{ {
$nickname = $this->trimmed('nickname'); if (Event::handle('StartGroupSaveForm', array($this))) {
$fullname = $this->trimmed('fullname'); try {
$homepage = $this->trimmed('homepage'); $nickname = Nickname::normalize($this->trimmed('nickname'));
$description = $this->trimmed('description'); } catch (NicknameException $e) {
$location = $this->trimmed('location'); $this->showForm($e->getMessage());
$aliasstring = $this->trimmed('aliases'); }
$fullname = $this->trimmed('fullname');
$homepage = $this->trimmed('homepage');
$description = $this->trimmed('description');
$location = $this->trimmed('location');
$aliasstring = $this->trimmed('aliases');
if (!Validate::string($nickname, array('min_length' => 1, if ($this->nicknameExists($nickname)) {
'max_length' => 64, // TRANS: Group create form validation error.
'format' => NICKNAME_FMT))) { $this->showForm(_('Nickname already in use. Try another one.'));
$this->showForm(_('Nickname must have only lowercase letters '. return;
'and numbers and no spaces.')); } else if (!User_group::allowedNickname($nickname)) {
return; // TRANS: Group create form validation error.
} else if ($this->nicknameExists($nickname)) { $this->showForm(_('Not a valid nickname.'));
$this->showForm(_('Nickname already in use. Try another one.')); return;
return; } else if (!is_null($homepage) && (strlen($homepage) > 0) &&
} else if (!User_group::allowedNickname($nickname)) { !Validate::uri($homepage,
$this->showForm(_('Not a valid nickname.')); array('allowed_schemes' =>
return; array('http', 'https')))) {
} else if (!is_null($homepage) && (strlen($homepage) > 0) && // TRANS: Group create form validation error.
!Validate::uri($homepage, $this->showForm(_('Homepage is not a valid URL.'));
array('allowed_schemes' => return;
array('http', 'https')))) { } else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
$this->showForm(_('Homepage is not a valid URL.')); // TRANS: Group create form validation error.
return; $this->showForm(_('Full name is too long (maximum 255 characters).'));
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) { return;
$this->showForm(_('Full name is too long (maximum 255 characters).')); } else if (User_group::descriptionTooLong($description)) {
return; // TRANS: Group create form validation error.
} else if (User_group::descriptionTooLong($description)) { // TRANS: %d is the maximum number of allowed characters.
// TRANS: Form validation error creating a new group because the description is too long. $this->showForm(sprintf(_m('Description is too long (maximum %d character).',
// TRANS: %d is the maximum number of allowed characters. 'Description is too long (maximum %d characters).',
$this->showForm(sprintf(_m('Description is too long (maximum %d character).', User_group::maxDescription()),
'Description is too long (maximum %d characters).', User_group::maxDescription()));
User_group::maxDescription()), return;
User_group::maxDescription())); } else if (!is_null($location) && mb_strlen($location) > 255) {
return; // TRANS: Group create form validation error.
} else if (!is_null($location) && mb_strlen($location) > 255) { $this->showForm(_('Location is too long (maximum 255 characters).'));
$this->showForm(_('Location is too long (maximum 255 characters).'));
return;
}
if (!empty($aliasstring)) {
$aliases = array_map('common_canonical_nickname', array_unique(preg_split('/[\s,]+/', $aliasstring)));
} else {
$aliases = array();
}
if (count($aliases) > common_config('group', 'maxaliases')) {
// TRANS: Client error shown when providing too many aliases during group creation.
// TRANS: %d is the maximum number of allowed aliases.
$this->showForm(sprintf(_m('Too many aliases! Maximum %d allowed.',
'Too many aliases! Maximum %d allowed.',
common_config('group', 'maxaliases')),
common_config('group', 'maxaliases')));
return;
}
foreach ($aliases as $alias) {
if (!Validate::string($alias, array('min_length' => 1,
'max_length' => 64,
'format' => NICKNAME_FMT))) {
$this->showForm(sprintf(_('Invalid alias: "%s"'), $alias));
return; return;
} }
if ($this->nicknameExists($alias)) {
$this->showForm(sprintf(_('Alias "%s" already in use. Try another one.'), if (!empty($aliasstring)) {
$alias)); $aliases = array_map('common_canonical_nickname', array_unique(preg_split('/[\s,]+/', $aliasstring)));
} else {
$aliases = array();
}
if (count($aliases) > common_config('group', 'maxaliases')) {
// TRANS: Group create form validation error.
// TRANS: %d is the maximum number of allowed aliases.
$this->showForm(sprintf(_m('Too many aliases! Maximum %d allowed.',
'Too many aliases! Maximum %d allowed.',
common_config('group', 'maxaliases')),
common_config('group', 'maxaliases')));
return; return;
} }
// XXX assumes alphanum nicknames
if (strcmp($alias, $nickname) == 0) { foreach ($aliases as $alias) {
$this->showForm(_('Alias can\'t be the same as nickname.')); if (!Nickname::isValid($alias)) {
return; // TRANS: Group create form validation error.
// TRANS: %s is the invalid alias.
$this->showForm(sprintf(_('Invalid alias: "%s"'), $alias));
return;
}
if ($this->nicknameExists($alias)) {
// TRANS: Group create form validation error. %s is the already used alias.
$this->showForm(sprintf(_('Alias "%s" already in use. Try another one.'),
$alias));
return;
}
// XXX assumes alphanum nicknames
if (strcmp($alias, $nickname) == 0) {
// TRANS: Group create form validation error.
$this->showForm(_('Alias cannot be the same as nickname.'));
return;
}
} }
$cur = common_current_user();
// Checked in prepare() above
assert(!is_null($cur));
$group = User_group::register(array('nickname' => $nickname,
'fullname' => $fullname,
'homepage' => $homepage,
'description' => $description,
'location' => $location,
'aliases' => $aliases,
'userid' => $cur->id,
'local' => true));
$this->group = $group;
Event::handle('EndGroupSaveForm', array($this));
common_redirect($group->homeUrl(), 303);
} }
$mainpage = common_local_url('showgroup', array('nickname' => $nickname));
$cur = common_current_user();
// Checked in prepare() above
assert(!is_null($cur));
$group = User_group::register(array('nickname' => $nickname,
'fullname' => $fullname,
'homepage' => $homepage,
'description' => $description,
'location' => $location,
'aliases' => $aliases,
'userid' => $cur->id,
'mainpage' => $mainpage,
'local' => true));
common_redirect($group->homeUrl(), 303);
} }
function nicknameExists($nickname) function nicknameExists($nickname)
@ -234,4 +242,3 @@ class NewgroupAction extends Action
return false; return false;
} }
} }

View File

@ -144,7 +144,7 @@ class NewmessageAction extends Action
$this->showForm(_('No content!')); $this->showForm(_('No content!'));
return; return;
} else { } else {
$content_shortened = common_shorten_links($this->content); $content_shortened = $user->shortenLinks($this->content);
if (Message::contentTooLong($content_shortened)) { if (Message::contentTooLong($content_shortened)) {
// TRANS: Form validation error displayed when message content is too long. // TRANS: Form validation error displayed when message content is too long.

View File

@ -154,10 +154,13 @@ class NewnoticeAction extends Action
return; return;
} }
$content_shortened = common_shorten_links($content); $content_shortened = $user->shortenLinks($content);
if (Notice::contentTooLong($content_shortened)) { if (Notice::contentTooLong($content_shortened)) {
$this->clientError(sprintf(_('That\'s too long. '. // TRANS: Client error displayed when the parameter "status" is missing.
'Max notice size is %d chars.'), // TRANS: %d is the maximum number of character for a notice.
$this->clientError(sprintf(_m('That\'s too long. Maximum notice size is %d character.',
'That\'s too long. Maximum notice size is %d characters.',
Notice::maxContent()),
Notice::maxContent())); Notice::maxContent()));
} }
@ -178,12 +181,10 @@ class NewnoticeAction extends Action
if (Notice::contentTooLong($content_shortened)) { if (Notice::contentTooLong($content_shortened)) {
$upload->delete(); $upload->delete();
$this->clientError( $this->clientError(sprintf(_m('Maximum notice size is %d character, including attachment URL.',
sprintf( 'Maximum notice size is %d characters, including attachment URL.',
_('Max notice size is %d chars, including attachment URL.'), Notice::maxContent()),
Notice::maxContent() Notice::maxContent()));
)
);
} }
} }

View File

@ -79,11 +79,7 @@ class OembedAction extends Action
if (empty($profile)) { if (empty($profile)) {
$this->serverError(_('Notice has no profile.'), 500); $this->serverError(_('Notice has no profile.'), 500);
} }
if (!empty($profile->fullname)) { $authorname = $profile->getFancyName();
$authorname = $profile->fullname . ' (' . $profile->nickname . ')';
} else {
$authorname = $profile->nickname;
}
$oembed['title'] = sprintf(_('%1$s\'s status on %2$s'), $oembed['title'] = sprintf(_('%1$s\'s status on %2$s'),
$authorname, $authorname,
common_exact_date($notice->created)); common_exact_date($notice->created));
@ -112,10 +108,23 @@ class OembedAction extends Action
$oembed['url']=$file_oembed->url; $oembed['url']=$file_oembed->url;
}else if(substr($attachment->mimetype,0,strlen('image/'))=='image/'){ }else if(substr($attachment->mimetype,0,strlen('image/'))=='image/'){
$oembed['type']='photo'; $oembed['type']='photo';
//TODO set width and height if ($attachment->filename) {
//$oembed['width']= $filepath = File::path($attachment->filename);
//$oembed['height']= $gis = @getimagesize($filepath);
if ($gis) {
$oembed['width'] = $gis[0];
$oembed['height'] = $gis[1];
} else {
// TODO Either throw an error or find a fallback?
}
}
$oembed['url']=$attachment->url; $oembed['url']=$attachment->url;
$thumb = $attachment->getThumbnail();
if ($thumb) {
$oembed['thumbnail_url'] = $thumb->url;
$oembed['thumbnail_width'] = $thumb->width;
$oembed['thumbnail_height'] = $thumb->height;
}
}else{ }else{
$oembed['type']='link'; $oembed['type']='link';
$oembed['url']=common_local_url('attachment', $oembed['url']=common_local_url('attachment',
@ -206,4 +215,15 @@ class OembedAction extends Action
return; return;
} }
/**
* Is this action read-only?
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
return true;
}
} }

View File

@ -46,7 +46,6 @@ require_once INSTALLDIR.'/lib/accountsettingsaction.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class OthersettingsAction extends AccountSettingsAction class OthersettingsAction extends AccountSettingsAction
{ {
/** /**
@ -54,9 +53,9 @@ class OthersettingsAction extends AccountSettingsAction
* *
* @return string Title of the page * @return string Title of the page
*/ */
function title() function title()
{ {
// Page title for a tab in user profile settings.
return _('Other settings'); return _('Other settings');
} }
@ -68,6 +67,7 @@ class OthersettingsAction extends AccountSettingsAction
function getInstructions() function getInstructions()
{ {
// TRANS: Instructions for tab "Other" in user profile settings.
return _('Manage various other options.'); return _('Manage various other options.');
} }
@ -105,6 +105,9 @@ class OthersettingsAction extends AccountSettingsAction
{ {
$services[$name]=$name; $services[$name]=$name;
if($value['freeService']){ if($value['freeService']){
// TRANS: Used as a suffix for free URL shorteners in a dropdown list in the tab "Other" of a
// TRANS: user's profile settings. This message has one space at the beginning. Use your
// TRANS: language's word separator here if it has one (most likely a single space).
$services[$name].=_(' (free service)'); $services[$name].=_(' (free service)');
} }
} }
@ -113,17 +116,22 @@ class OthersettingsAction extends AccountSettingsAction
asort($services); asort($services);
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Label for dropdown with URL shortener services.
$this->dropdown('urlshorteningservice', _('Shorten URLs with'), $this->dropdown('urlshorteningservice', _('Shorten URLs with'),
// TRANS: Tooltip for for dropdown with URL shortener services.
$services, _('Automatic shortening service to use.'), $services, _('Automatic shortening service to use.'),
false, $user->urlshorteningservice); false, $user->urlshorteningservice);
$this->elementEnd('li'); $this->elementEnd('li');
} }
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Label for checkbox.
$this->checkbox('viewdesigns', _('View profile designs'), $this->checkbox('viewdesigns', _('View profile designs'),
// TRANS: Tooltip for checkbox.
$user->viewdesigns, _('Show or hide profile designs.')); $user->viewdesigns, _('Show or hide profile designs.'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->submit('save', _('Save')); // TRANS: Button text for saving "Other settings" in profile.
$this->submit('save', _m('BUTTON','Save'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }
@ -150,7 +158,8 @@ class OthersettingsAction extends AccountSettingsAction
$urlshorteningservice = $this->trimmed('urlshorteningservice'); $urlshorteningservice = $this->trimmed('urlshorteningservice');
if (!is_null($urlshorteningservice) && strlen($urlshorteningservice) > 50) { if (!is_null($urlshorteningservice) && strlen($urlshorteningservice) > 50) {
$this->showForm(_('URL shortening service is too long (max 50 chars).')); // TRANS: Form validation error for form "Other settings" in user profile.
$this->showForm(_('URL shortening service is too long (maximum 50 characters).'));
return; return;
} }
@ -171,7 +180,8 @@ class OthersettingsAction extends AccountSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
$this->serverError(_('Couldn\'t update user.')); // TRANS: Server error displayed when "Other" settings in user profile could not be updated on the server.
$this->serverError(_('Could not update user.'));
return; return;
} }

View File

@ -88,21 +88,9 @@ class OutboxAction extends MailboxAction
} }
} }
/** function getMessageList($message)
* returns the profile we want to show with the message
*
* For outboxes, we show the recipient.
*
* @param Message $message The message to get the profile for
*
* @return Profile The profile of the message recipient
*
* @see MailboxAction::getMessageProfile()
*/
function getMessageProfile($message)
{ {
return $message->getTo(); return new OutboxMessageList($this, $message);
} }
/** /**
@ -116,3 +104,24 @@ class OutboxAction extends MailboxAction
return _('This is your outbox, which lists private messages you have sent.'); return _('This is your outbox, which lists private messages you have sent.');
} }
} }
class OutboxMessageList extends MessageList
{
function newItem($message)
{
return new OutboxMessageListItem($this->out, $message);
}
}
class OutboxMessageListItem extends MessageListItem
{
/**
* Returns the profile we want to show with the message
*
* @return Profile The profile that matches the message
*/
function getMessageProfile()
{
return $this->message->getTo();
}
}

View File

@ -46,7 +46,6 @@ require_once INSTALLDIR.'/lib/accountsettingsaction.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class ProfilesettingsAction extends AccountSettingsAction class ProfilesettingsAction extends AccountSettingsAction
{ {
/** /**
@ -54,7 +53,6 @@ class ProfilesettingsAction extends AccountSettingsAction
* *
* @return string Title of the page * @return string Title of the page
*/ */
function title() function title()
{ {
// TRANS: Page title for profile settings. // TRANS: Page title for profile settings.
@ -66,7 +64,6 @@ class ProfilesettingsAction extends AccountSettingsAction
* *
* @return instructions for use * @return instructions for use
*/ */
function getInstructions() function getInstructions()
{ {
// TRANS: Usage instructions for profile settings. // TRANS: Usage instructions for profile settings.
@ -87,7 +84,6 @@ class ProfilesettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function showContent() function showContent()
{ {
$user = common_current_user(); $user = common_current_user();
@ -212,12 +208,12 @@ class ProfilesettingsAction extends AccountSettingsAction
* *
* @return void * @return void
*/ */
function handlePost() function handlePost()
{ {
// CSRF protection // CSRF protection
$token = $this->trimmed('token'); $token = $this->trimmed('token');
if (!$token || $token != common_session_token()) { if (!$token || $token != common_session_token()) {
// TRANS: Form validation error.
$this->showForm(_('There was a problem with your session token. '. $this->showForm(_('There was a problem with your session token. '.
'Try again, please.')); 'Try again, please.'));
return; return;
@ -225,7 +221,13 @@ class ProfilesettingsAction extends AccountSettingsAction
if (Event::handle('StartProfileSaveForm', array($this))) { if (Event::handle('StartProfileSaveForm', array($this))) {
$nickname = $this->trimmed('nickname'); try {
$nickname = Nickname::normalize($this->trimmed('nickname'));
} catch (NicknameException $e) {
$this->showForm($e->getMessage());
return;
}
$fullname = $this->trimmed('fullname'); $fullname = $this->trimmed('fullname');
$homepage = $this->trimmed('homepage'); $homepage = $this->trimmed('homepage');
$bio = $this->trimmed('bio'); $bio = $this->trimmed('bio');
@ -236,13 +238,7 @@ class ProfilesettingsAction extends AccountSettingsAction
$tagstring = $this->trimmed('tags'); $tagstring = $this->trimmed('tags');
// Some validation // Some validation
if (!Validate::string($nickname, array('min_length' => 1, if (!User::allowed_nickname($nickname)) {
'max_length' => 64,
'format' => NICKNAME_FMT))) {
// TRANS: Validation error in form for profile settings.
$this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.'));
return;
} else if (!User::allowed_nickname($nickname)) {
// TRANS: Validation error in form for profile settings. // TRANS: Validation error in form for profile settings.
$this->showForm(_('Not a valid nickname.')); $this->showForm(_('Not a valid nickname.'));
return; return;
@ -323,7 +319,7 @@ class ProfilesettingsAction extends AccountSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown when user profile settings could not be updated. // TRANS: Server error thrown when user profile settings could not be updated.
$this->serverError(_('Couldn\'t update user.')); $this->serverError(_('Could not update user.'));
return; return;
} else { } else {
// Re-initialize language environment if it changed // Re-initialize language environment if it changed
@ -348,7 +344,7 @@ class ProfilesettingsAction extends AccountSettingsAction
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown when user profile settings could not be updated to // TRANS: Server error thrown when user profile settings could not be updated to
// TRANS: automatically subscribe to any subscriber. // TRANS: automatically subscribe to any subscriber.
$this->serverError(_('Couldn\'t update user for autosubscribe.')); $this->serverError(_('Could not update user for autosubscribe.'));
return; return;
} }
} }
@ -406,7 +402,7 @@ class ProfilesettingsAction extends AccountSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($prefs, ($exists) ? 'UPDATE' : 'INSERT', __FILE__); common_log_db_error($prefs, ($exists) ? 'UPDATE' : 'INSERT', __FILE__);
// TRANS: Server error thrown when user profile location preference settings could not be updated. // TRANS: Server error thrown when user profile location preference settings could not be updated.
$this->serverError(_('Couldn\'t save location prefs.')); $this->serverError(_('Could not save location prefs.'));
return; return;
} }
} }
@ -419,7 +415,7 @@ class ProfilesettingsAction extends AccountSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($profile, 'UPDATE', __FILE__); common_log_db_error($profile, 'UPDATE', __FILE__);
// TRANS: Server error thrown when user profile settings could not be saved. // TRANS: Server error thrown when user profile settings could not be saved.
$this->serverError(_('Couldn\'t save profile.')); $this->serverError(_('Could not save profile.'));
return; return;
} }
@ -428,7 +424,7 @@ class ProfilesettingsAction extends AccountSettingsAction
if (!$result) { if (!$result) {
// TRANS: Server error thrown when user profile settings tags could not be saved. // TRANS: Server error thrown when user profile settings tags could not be saved.
$this->serverError(_('Couldn\'t save tags.')); $this->serverError(_('Could not save tags.'));
return; return;
} }
@ -452,4 +448,45 @@ class ProfilesettingsAction extends AccountSettingsAction
return $other->id != $user->id; return $other->id != $user->id;
} }
} }
function showAside() {
$user = common_current_user();
$this->elementStart('div', array('id' => 'aside_primary',
'class' => 'aside'));
$this->elementStart('div', array('id' => 'account_actions',
'class' => 'section'));
$this->elementStart('ul');
if (Event::handle('StartProfileSettingsActions', array($this))) {
if ($user->hasRight(Right::BACKUPACCOUNT)) {
$this->elementStart('li');
$this->element('a',
array('href' => common_local_url('backupaccount')),
// TRANS: Option in profile settings to create a backup of the account of the currently logged in user.
_('Backup account'));
$this->elementEnd('li');
}
if ($user->hasRight(Right::DELETEACCOUNT)) {
$this->elementStart('li');
$this->element('a',
array('href' => common_local_url('deleteaccount')),
// TRANS: Option in profile settings to delete the account of the currently logged in user.
_('Delete account'));
$this->elementEnd('li');
}
if ($user->hasRight(Right::RESTOREACCOUNT)) {
$this->elementStart('li');
$this->element('a',
array('href' => common_local_url('restoreaccount')),
// TRANS: Option in profile settings to restore the account of the currently logged in user from a backup.
_('Restore account'));
$this->elementEnd('li');
}
Event::handle('EndProfileSettingsActions', array($this));
}
$this->elementEnd('ul');
$this->elementEnd('div');
$this->elementEnd('div');
}
} }

View File

@ -33,6 +33,7 @@ class RecoverpasswordAction extends Action
{ {
parent::handle($args); parent::handle($args);
if (common_logged_in()) { if (common_logged_in()) {
// TRANS: Client error displayed trying to recover password while already logged in.
$this->clientError(_('You are already logged in!')); $this->clientError(_('You are already logged in!'));
return; return;
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') { } else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
@ -41,6 +42,7 @@ class RecoverpasswordAction extends Action
} else if ($this->arg('reset')) { } else if ($this->arg('reset')) {
$this->resetPassword(); $this->resetPassword();
} else { } else {
// TRANS: Client error displayed when unexpected data is posted in the password recovery form.
$this->clientError(_('Unexpected form submission.')); $this->clientError(_('Unexpected form submission.'));
} }
} else { } else {
@ -54,15 +56,16 @@ class RecoverpasswordAction extends Action
function checkCode() function checkCode()
{ {
$code = $this->trimmed('code'); $code = $this->trimmed('code');
$confirm = Confirm_address::staticGet('code', $code); $confirm = Confirm_address::staticGet('code', $code);
if (!$confirm) { if (!$confirm) {
// TRANS: Client error displayed when password recovery code is not correct.
$this->clientError(_('No such recovery code.')); $this->clientError(_('No such recovery code.'));
return; return;
} }
if ($confirm->address_type != 'recover') { if ($confirm->address_type != 'recover') {
// TRANS: Client error displayed when no proper password recovery code was submitted.
$this->clientError(_('Not a recovery code.')); $this->clientError(_('Not a recovery code.'));
return; return;
} }
@ -70,6 +73,7 @@ class RecoverpasswordAction extends Action
$user = User::staticGet($confirm->user_id); $user = User::staticGet($confirm->user_id);
if (!$user) { if (!$user) {
// TRANS: Server error displayed trying to recover password without providing a user.
$this->serverError(_('Recovery code for unknown user.')); $this->serverError(_('Recovery code for unknown user.'));
return; return;
} }
@ -83,6 +87,7 @@ class RecoverpasswordAction extends Action
if (!$result) { if (!$result) {
common_log_db_error($confirm, 'DELETE', __FILE__); common_log_db_error($confirm, 'DELETE', __FILE__);
// TRANS: Server error displayed removing a password recovery code from the database.
$this->serverError(_('Error with confirmation code.')); $this->serverError(_('Error with confirmation code.'));
return; return;
} }
@ -94,6 +99,7 @@ class RecoverpasswordAction extends Action
common_log(LOG_WARNING, common_log(LOG_WARNING,
'Attempted redemption on recovery code ' . 'Attempted redemption on recovery code ' .
'that is ' . $touched . ' seconds old. '); 'that is ' . $touched . ' seconds old. ');
// TRANS: Client error displayed trying to recover password with too old a recovery code.
$this->clientError(_('This confirmation code is too old. ' . $this->clientError(_('This confirmation code is too old. ' .
'Please start again.')); 'Please start again.'));
return; return;
@ -108,6 +114,7 @@ class RecoverpasswordAction extends Action
$result = $user->updateKeys($orig); $result = $user->updateKeys($orig);
if (!$result) { if (!$result) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error displayed when updating a user's e-mail address in the database fails while recovering a password.
$this->serverError(_('Could not update user with confirmed email address.')); $this->serverError(_('Could not update user with confirmed email address.'));
return; return;
} }
@ -149,14 +156,16 @@ class RecoverpasswordAction extends Action
$this->elementStart('div', 'instructions'); $this->elementStart('div', 'instructions');
if ($this->mode == 'recover') { if ($this->mode == 'recover') {
$this->element('p', null, $this->element('p', null,
// TRANS: Page notice for password recovery page.
_('If you have forgotten or lost your' . _('If you have forgotten or lost your' .
' password, you can get a new one sent to' . ' password, you can get a new one sent to' .
' the email address you have stored' . ' the email address you have stored' .
' in your account.')); ' in your account.'));
} else if ($this->mode == 'reset') { } else if ($this->mode == 'reset') {
// TRANS: Page notice for password change page.
$this->element('p', null, $this->element('p', null,
_('You have been identified. Enter a' . _('You have been identified. Enter a' .
' new password below. ')); ' new password below.'));
} }
$this->elementEnd('div'); $this->elementEnd('div');
} }
@ -185,19 +194,24 @@ class RecoverpasswordAction extends Action
'class' => 'form_settings', 'class' => 'form_settings',
'action' => common_local_url('recoverpassword'))); 'action' => common_local_url('recoverpassword')));
$this->elementStart('fieldset'); $this->elementStart('fieldset');
// TRANS: Fieldset legend for password recovery page.
$this->element('legend', null, _('Password recovery')); $this->element('legend', null, _('Password recovery'));
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Field label on password recovery page.
$this->input('nicknameoremail', _('Nickname or email address'), $this->input('nicknameoremail', _('Nickname or email address'),
$this->trimmed('nicknameoremail'), $this->trimmed('nicknameoremail'),
// TRANS: Title for field label on password recovery page.
_('Your nickname on this server, ' . _('Your nickname on this server, ' .
'or your registered email address.')); 'or your registered email address.'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->element('input', array('name' => 'recover', $this->element('input', array('name' => 'recover',
'type' => 'hidden', 'type' => 'hidden',
// TRANS: Field label on password recovery page.
'value' => _('Recover'))); 'value' => _('Recover')));
$this->submit('recover', _('Recover')); // TRANS: Button text on password recovery page.
$this->submit('recover', _m('BUTTON','Recover'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }
@ -205,11 +219,16 @@ class RecoverpasswordAction extends Action
function title() function title()
{ {
switch ($this->mode) { switch ($this->mode) {
// TRANS: Title for password recovery page in password reset mode.
case 'reset': return _('Reset password'); case 'reset': return _('Reset password');
// TRANS: Title for password recovery page in password recover mode.
case 'recover': return _('Recover password'); case 'recover': return _('Recover password');
// TRANS: Title for password recovery page in email sent mode.
case 'sent': return _('Password recovery requested'); case 'sent': return _('Password recovery requested');
// TRANS: Title for password recovery page in password saved mode.
case 'saved': return _('Password saved.'); case 'saved': return _('Password saved.');
default: default:
// TRANS: Title for password recovery page when an unknown action has been specified.
return _('Unknown action'); return _('Unknown action');
} }
} }
@ -228,19 +247,25 @@ class RecoverpasswordAction extends Action
'class' => 'form_settings', 'class' => 'form_settings',
'action' => common_local_url('recoverpassword'))); 'action' => common_local_url('recoverpassword')));
$this->elementStart('fieldset'); $this->elementStart('fieldset');
// TRANS: Fieldset legend for password reset form.
$this->element('legend', null, _('Password change')); $this->element('legend', null, _('Password change'));
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Field label for password reset form.
$this->password('newpassword', _('New password'), $this->password('newpassword', _('New password'),
_('6 or more characters, and don\'t forget it!')); // TRANS: Title for field label for password reset form.
_('6 or more characters, and do not forget it!'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Field label for password reset form where the password has to be typed again.
$this->password('confirm', _('Confirm'), $this->password('confirm', _('Confirm'),
_('Same as password above')); // TRANS: Ttile for field label for password reset form where the password has to be typed again.
_('Same as password above.'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->submit('reset', _('Reset')); // TRANS: Button text for password reset form.
$this->submit('reset', _m('BUTTON','Reset'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }
@ -249,6 +274,7 @@ class RecoverpasswordAction extends Action
{ {
$nore = $this->trimmed('nicknameoremail'); $nore = $this->trimmed('nicknameoremail');
if (!$nore) { if (!$nore) {
// TRANS: Form instructions for password recovery form.
$this->showForm(_('Enter a nickname or email address.')); $this->showForm(_('Enter a nickname or email address.'));
return; return;
} }
@ -279,6 +305,7 @@ class RecoverpasswordAction extends Action
} }
if (!$user) { if (!$user) {
// TRANS: Information on password recovery form if no known username or e-mail address was specified.
$this->showForm(_('No user with that email address or username.')); $this->showForm(_('No user with that email address or username.'));
return; return;
} }
@ -296,6 +323,7 @@ class RecoverpasswordAction extends Action
} }
if (!$user->email && !$confirm_email) { if (!$user->email && !$confirm_email) {
// TRANS: Client error displayed on password recovery form if a user does not have a registered e-mail address.
$this->clientError(_('No registered email address for that user.')); $this->clientError(_('No registered email address for that user.'));
return; return;
} }
@ -310,10 +338,12 @@ class RecoverpasswordAction extends Action
if (!$confirm->insert()) { if (!$confirm->insert()) {
common_log_db_error($confirm, 'INSERT', __FILE__); common_log_db_error($confirm, 'INSERT', __FILE__);
// TRANS: Server error displayed if e-mail address confirmation fails in the database on the password recovery form.
$this->serverError(_('Error saving address confirmation.')); $this->serverError(_('Error saving address confirmation.'));
return; return;
} }
// @todo FIXME: needs i18n.
$body = "Hey, $user->nickname."; $body = "Hey, $user->nickname.";
$body .= "\n\n"; $body .= "\n\n";
$body .= 'Someone just asked for a new password ' . $body .= 'Someone just asked for a new password ' .
@ -332,9 +362,11 @@ class RecoverpasswordAction extends Action
$body .= "\n"; $body .= "\n";
$headers = _mail_prepare_headers('recoverpassword', $user->nickname, $user->nickname); $headers = _mail_prepare_headers('recoverpassword', $user->nickname, $user->nickname);
// TRANS: Subject for password recovery e-mail.
mail_to_user($user, _('Password recovery requested'), $body, $headers, $confirm->address); mail_to_user($user, _('Password recovery requested'), $body, $headers, $confirm->address);
$this->mode = 'sent'; $this->mode = 'sent';
// TRANS: User notification after an e-mail with instructions was sent from the password recovery form.
$this->msg = _('Instructions for recovering your password ' . $this->msg = _('Instructions for recovering your password ' .
'have been sent to the email address registered to your ' . 'have been sent to the email address registered to your ' .
'account.'); 'account.');
@ -347,6 +379,7 @@ class RecoverpasswordAction extends Action
# CSRF protection # CSRF protection
$token = $this->trimmed('token'); $token = $this->trimmed('token');
if (!$token || $token != common_session_token()) { if (!$token || $token != common_session_token()) {
// TRANS: Form validation error message.
$this->showForm(_('There was a problem with your session token. Try again, please.')); $this->showForm(_('There was a problem with your session token. Try again, please.'));
return; return;
} }
@ -354,6 +387,7 @@ class RecoverpasswordAction extends Action
$user = $this->getTempUser(); $user = $this->getTempUser();
if (!$user) { if (!$user) {
// TRANS: Client error displayed when trying to reset as password without providing a user.
$this->clientError(_('Unexpected password reset.')); $this->clientError(_('Unexpected password reset.'));
return; return;
} }
@ -362,10 +396,12 @@ class RecoverpasswordAction extends Action
$confirm = $this->trimmed('confirm'); $confirm = $this->trimmed('confirm');
if (!$newpassword || strlen($newpassword) < 6) { if (!$newpassword || strlen($newpassword) < 6) {
$this->showPasswordForm(_('Password must be 6 chars or more.')); // TRANS: Reset password form validation error message.
$this->showPasswordForm(_('Password must be 6 characters or more.'));
return; return;
} }
if ($newpassword != $confirm) { if ($newpassword != $confirm) {
// TRANS: Reset password form validation error message.
$this->showPasswordForm(_('Password and confirmation do not match.')); $this->showPasswordForm(_('Password and confirmation do not match.'));
return; return;
} }
@ -378,13 +414,15 @@ class RecoverpasswordAction extends Action
if (!$user->update($original)) { if (!$user->update($original)) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
$this->serverError(_('Can\'t save new password.')); // TRANS: Reset password form validation error message.
$this->serverError(_('Cannot save new password.'));
return; return;
} }
$this->clearTempUser(); $this->clearTempUser();
if (!common_set_user($user->nickname)) { if (!common_set_user($user->nickname)) {
// TRANS: Server error displayed when something does wrong with the user object during password reset.
$this->serverError(_('Error setting user.')); $this->serverError(_('Error setting user.'));
return; return;
} }
@ -392,6 +430,7 @@ class RecoverpasswordAction extends Action
common_real_login(true); common_real_login(true);
$this->mode = 'saved'; $this->mode = 'saved';
// TRANS: Success message for user after password reset.
$this->msg = _('New password successfully saved. ' . $this->msg = _('New password successfully saved. ' .
'You are now logged in.'); 'You are now logged in.');
$this->success = true; $this->success = true;

View File

@ -198,7 +198,11 @@ class RegisterAction extends Action
} }
// Input scrubbing // Input scrubbing
$nickname = common_canonical_nickname($nickname); try {
$nickname = Nickname::normalize($nickname);
} catch (NicknameException $e) {
$this->showForm($e->getMessage());
}
$email = common_canonical_email($email); $email = common_canonical_email($email);
if (!$this->boolean('license')) { if (!$this->boolean('license')) {
@ -206,11 +210,6 @@ class RegisterAction extends Action
'agree to the license.')); 'agree to the license.'));
} else if ($email && !Validate::email($email, common_config('email', 'check_domain'))) { } else if ($email && !Validate::email($email, common_config('email', 'check_domain'))) {
$this->showForm(_('Not a valid email address.')); $this->showForm(_('Not a valid email address.'));
} else if (!Validate::string($nickname, array('min_length' => 1,
'max_length' => 64,
'format' => NICKNAME_FMT))) {
$this->showForm(_('Nickname must have only lowercase letters '.
'and numbers and no spaces.'));
} else if ($this->nicknameExists($nickname)) { } else if ($this->nicknameExists($nickname)) {
$this->showForm(_('Nickname already in use. Try another one.')); $this->showForm(_('Nickname already in use. Try another one.'));
} else if (!User::allowed_nickname($nickname)) { } else if (!User::allowed_nickname($nickname)) {
@ -431,16 +430,15 @@ class RegisterAction extends Action
if (Event::handle('StartRegistrationFormData', array($this))) { if (Event::handle('StartRegistrationFormData', array($this))) {
$this->elementStart('li'); $this->elementStart('li');
$this->input('nickname', _('Nickname'), $this->trimmed('nickname'), $this->input('nickname', _('Nickname'), $this->trimmed('nickname'),
_('1-64 lowercase letters or numbers, '. _('1-64 lowercase letters or numbers, no punctuation or spaces.'));
'no punctuation or spaces. Required.'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->password('password', _('Password'), $this->password('password', _('Password'),
_('6 or more characters. Required.')); _('6 or more characters.'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->password('confirm', _('Confirm'), $this->password('confirm', _('Confirm'),
_('Same as password above. Required.')); _('Same as password above.'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
if ($this->invite && $this->invite->address_type == 'email') { if ($this->invite && $this->invite->address_type == 'email') {

View File

@ -44,7 +44,6 @@ require_once INSTALLDIR.'/extlib/libomb/profile.php';
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */
class RemotesubscribeAction extends Action class RemotesubscribeAction extends Action
{ {
var $nickname; var $nickname;
@ -173,14 +172,14 @@ class RemotesubscribeAction extends Action
if ($service->getServiceURI(OAUTH_ENDPOINT_REQUEST) == if ($service->getServiceURI(OAUTH_ENDPOINT_REQUEST) ==
common_local_url('requesttoken') || common_local_url('requesttoken') ||
User::staticGet('uri', $service->getRemoteUserURI())) { User::staticGet('uri', $service->getRemoteUserURI())) {
$this->showForm(_('Thats a local profile! Login to subscribe.')); $this->showForm(_('That is a local profile! Login to subscribe.'));
return; return;
} }
try { try {
$service->requestToken(); $service->requestToken();
} catch (OMB_RemoteServiceException $e) { } catch (OMB_RemoteServiceException $e) {
$this->showForm(_('Couldnt get a request token.')); $this->showForm(_('Could not get a request token.'));
return; return;
} }
@ -204,4 +203,3 @@ class RemotesubscribeAction extends Action
common_redirect($target_url, 303); common_redirect($target_url, 303);
} }
} }
?>

View File

@ -41,7 +41,6 @@ if (!defined('STATUSNET')) {
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */
class RepeatAction extends Action class RepeatAction extends Action
{ {
var $user = null; var $user = null;
@ -73,7 +72,7 @@ class RepeatAction extends Action
} }
if ($this->user->id == $this->notice->profile_id) { if ($this->user->id == $this->notice->profile_id) {
$this->clientError(_("You can't repeat your own notice.")); $this->clientError(_("You cannot repeat your own notice."));
return false; return false;
} }
@ -101,7 +100,6 @@ class RepeatAction extends Action
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
$repeat = $this->notice->repeat($this->user->id, 'web'); $repeat = $this->notice->repeat($this->user->id, 'web');

375
actions/restoreaccount.php Normal file
View File

@ -0,0 +1,375 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* Restore a backup of your own account from the browser
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Account
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
/**
* Restore a backup of your own account from the browser
*
* @category Account
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class RestoreaccountAction extends Action
{
private $success = false;
private $inprogress = false;
/**
* Returns the title of the page
*
* @return string page title
*/
function title()
{
// TRANS: Page title for page where a user account can be restored from backup.
return _("Restore account");
}
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
$cur = common_current_user();
if (empty($cur)) {
// TRANS: Client exception displayed when trying to restore an account while not logged in.
throw new ClientException(_('Only logged-in users can restore their account.'), 403);
}
if (!$cur->hasRight(Right::RESTOREACCOUNT)) {
// TRANS: Client exception displayed when trying to restore an account without having restore rights.
throw new ClientException(_('You may not restore your account.'), 403);
}
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handle($argarray=null)
{
parent::handle($argarray);
if ($this->isPost()) {
$this->restoreAccount();
} else {
$this->showPage();
}
return;
}
/**
* Queue a file for restoration
*
* Uses the UserActivityStream class; may take a long time!
*
* @return void
*/
function restoreAccount()
{
$this->checkSessionToken();
if (!isset($_FILES['restorefile']['error'])) {
// TRANS: Client exception displayed trying to restore an account while something went wrong uploading a file.
throw new ClientException(_('No uploaded file.'));
}
switch ($_FILES['restorefile']['error']) {
case UPLOAD_ERR_OK: // success, jump out
break;
case UPLOAD_ERR_INI_SIZE:
// TRANS: Client exception thrown when an uploaded file is larger than set in php.ini.
throw new ClientException(_('The uploaded file exceeds the ' .
'upload_max_filesize directive in php.ini.'));
return;
case UPLOAD_ERR_FORM_SIZE:
throw new ClientException(
// TRANS: Client exception.
_('The uploaded file exceeds the MAX_FILE_SIZE directive' .
' that was specified in the HTML form.'));
return;
case UPLOAD_ERR_PARTIAL:
@unlink($_FILES['restorefile']['tmp_name']);
// TRANS: Client exception.
throw new ClientException(_('The uploaded file was only' .
' partially uploaded.'));
return;
case UPLOAD_ERR_NO_FILE:
// TRANS: Client exception. No file; probably just a non-AJAX submission.
throw new ClientException(_('No uploaded file.'));
return;
case UPLOAD_ERR_NO_TMP_DIR:
// TRANS: Client exception thrown when a temporary folder is not present to store a file upload.
throw new ClientException(_('Missing a temporary folder.'));
return;
case UPLOAD_ERR_CANT_WRITE:
// TRANS: Client exception thrown when writing to disk is not possible during a file upload operation.
throw new ClientException(_('Failed to write file to disk.'));
return;
case UPLOAD_ERR_EXTENSION:
// TRANS: Client exception thrown when a file upload operation has been stopped by an extension.
throw new ClientException(_('File upload stopped by extension.'));
return;
default:
common_log(LOG_ERR, __METHOD__ . ": Unknown upload error " .
$_FILES['restorefile']['error']);
// TRANS: Client exception thrown when a file upload operation has failed with an unknown reason.
throw new ClientException(_('System error uploading file.'));
return;
}
$filename = $_FILES['restorefile']['tmp_name'];
try {
if (!file_exists($filename)) {
// TRANS: Server exception thrown when an expected file upload could not be found.
throw new ServerException(_("No such file '$filename'."));
}
if (!is_file($filename)) {
// TRANS: Server exception thrown when an expected file upload is not an actual file.
throw new ServerException(_("Not a regular file: '$filename'."));
}
if (!is_readable($filename)) {
// TRANS: Server exception thrown when an expected file upload could not be read.
throw new ServerException(_("File '$filename' not readable."));
}
common_debug(sprintf("Getting backup from file '%s'.", $filename));
$xml = file_get_contents($filename);
// This check is costly but we should probably give
// the user some info ahead of time.
$doc = new DOMDocument();
// Disable PHP warnings so we don't spew low-level XML errors to output...
// would be nice if we can just get exceptions instead.
$old_err = error_reporting();
error_reporting($old_err & ~E_WARNING);
$doc->loadXML($xml);
error_reporting($old_err);
$feed = $doc->documentElement;
if (!$feed ||
$feed->namespaceURI != Activity::ATOM ||
$feed->localName != 'feed') {
// TRANS: Client exception thrown when a feed is not an Atom feed.
throw new ClientException(_("Not an Atom feed."));
}
// Enqueue for processing.
$qm = QueueManager::get();
$qm->enqueue(array(common_current_user(), $xml, false), 'feedimp');
if ($qm instanceof UnQueueManager) {
// No active queuing means we've actually just completed the job!
$this->success = true;
} else {
// We've fed data into background queues, and it's probably still running.
$this->inprogress = true;
}
$this->showPage();
} catch (Exception $e) {
// Delete the file and re-throw
@unlink($_FILES['restorefile']['tmp_name']);
throw $e;
}
}
/**
* Show a little form so that the person can upload a file to restore
*
* @return void
*/
function showContent()
{
if ($this->success) {
$this->element('p', null,
// TRANS: Success message when a feed has been restored.
_('Feed has been restored. Your old posts should now appear in search and your profile page.'));
} else if ($this->inprogress) {
$this->element('p', null,
// TRANS: Message when a feed restore is in progress.
_('Feed will be restored. Please wait a few minutes for results.'));
} else {
$form = new RestoreAccountForm($this);
$form->show();
}
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
return false;
}
/**
* Return last modified, if applicable.
*
* MAY override
*
* @return string last modified http header
*/
function lastModified()
{
// For comparison with If-Last-Modified
// If not applicable, return null
return null;
}
/**
* Return etag, if applicable.
*
* MAY override
*
* @return string etag http header
*/
function etag()
{
return null;
}
}
/**
* A form for backing up the account.
*
* @category Account
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class RestoreAccountForm extends Form
{
function __construct($out=null) {
parent::__construct($out);
$this->enctype = 'multipart/form-data';
}
/**
* Class of the form.
*
* @return string the form's class
*/
function formClass()
{
return 'form_profile_restore';
}
/**
* URL the form posts to
*
* @return string the form's action URL
*/
function action()
{
return common_local_url('restoreaccount');
}
/**
* Output form data
*
* Really, just instructions for doing a backup.
*
* @return void
*/
function formData()
{
$this->out->elementStart('p', 'instructions');
// TRANS: Form instructions for feed restore.
$this->out->raw(_('You can upload a backed-up stream in '.
'<a href="http://activitystrea.ms/">Activity Streams</a> format.'));
$this->out->elementEnd('p');
$this->out->elementStart('ul', 'form_data');
$this->out->elementStart('li', array ('id' => 'settings_attach'));
$this->out->element('input', array('name' => 'restorefile',
'type' => 'file',
'id' => 'restorefile'));
$this->out->elementEnd('li');
$this->out->elementEnd('ul');
}
/**
* Buttons for the form
*
* In this case, a single submit button
*
* @return void
*/
function formActions()
{
$this->out->submit('submit',
// TRANS: Submit button to confirm upload of a user backup file for account restore.
_m('BUTTON', 'Upload'),
'submit',
null,
// TRANS: Title for submit button to confirm upload of a user backup file for account restore.
_('Upload the file'));
}
}

View File

@ -162,6 +162,20 @@ class RsdAction extends Action
'true'); 'true');
$this->elementEnd('settings'); $this->elementEnd('settings');
$this->elementEnd('api'); $this->elementEnd('api');
// Atom API
if (empty($this->user)) {
$service = common_local_url('ApiAtomService');
} else {
$service = common_local_url('ApiAtomService', array('id' => $this->user->nickname));
}
$this->element('api', array('name' => 'Atom',
'preferred' => 'false',
'apiLink' => $service,
'blogID' => $blogID));
Event::handle('EndRsdListApis', array($this, $this->user)); Event::handle('EndRsdListApis', array($this, $this->user));
} }
$this->elementEnd('apis'); $this->elementEnd('apis');

View File

@ -44,7 +44,6 @@ require_once INSTALLDIR.'/lib/feedlist.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class ShowfavoritesAction extends OwnerDesignAction class ShowfavoritesAction extends OwnerDesignAction
{ {
/** User we're getting the faves of */ /** User we're getting the faves of */
@ -57,7 +56,6 @@ class ShowfavoritesAction extends OwnerDesignAction
* *
* @return boolean true * @return boolean true
*/ */
function isReadOnly($args) function isReadOnly($args)
{ {
return true; return true;
@ -70,12 +68,15 @@ class ShowfavoritesAction extends OwnerDesignAction
* *
* @return string title of page * @return string title of page
*/ */
function title() function title()
{ {
if ($this->page == 1) { if ($this->page == 1) {
// TRANS: Title for first page of favourite notices of a user.
// TRANS: %s is the user for whom the favourite notices are displayed.
return sprintf(_('%s\'s favorite notices'), $this->user->nickname); return sprintf(_('%s\'s favorite notices'), $this->user->nickname);
} else { } else {
// TRANS: Title for all but the first page of favourite notices of a user.
// TRANS: %1$s is the user for whom the favourite notices are displayed, %2$d is the page number.
return sprintf(_('%1$s\'s favorite notices, page %2$d'), return sprintf(_('%1$s\'s favorite notices, page %2$d'),
$this->user->nickname, $this->user->nickname,
$this->page); $this->page);
@ -92,7 +93,6 @@ class ShowfavoritesAction extends OwnerDesignAction
* *
* @return boolean success flag * @return boolean success flag
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
@ -102,6 +102,7 @@ class ShowfavoritesAction extends OwnerDesignAction
$this->user = User::staticGet('nickname', $nickname); $this->user = User::staticGet('nickname', $nickname);
if (!$this->user) { if (!$this->user) {
// TRANS: Client error displayed when trying to display favourite notices for a non-existing user.
$this->clientError(_('No such user.')); $this->clientError(_('No such user.'));
return false; return false;
} }
@ -129,6 +130,7 @@ class ShowfavoritesAction extends OwnerDesignAction
} }
if (empty($this->notice)) { if (empty($this->notice)) {
// TRANS: Server error displayed when favourite notices could not be retrieved from the database.
$this->serverError(_('Could not retrieve favorite notices.')); $this->serverError(_('Could not retrieve favorite notices.'));
return; return;
} }
@ -150,7 +152,6 @@ class ShowfavoritesAction extends OwnerDesignAction
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
@ -162,12 +163,12 @@ class ShowfavoritesAction extends OwnerDesignAction
* *
* @return array Feed objects to show * @return array Feed objects to show
*/ */
function getFeeds() function getFeeds()
{ {
return array(new Feed(Feed::RSS1, return array(new Feed(Feed::RSS1,
common_local_url('favoritesrss', common_local_url('favoritesrss',
array('nickname' => $this->user->nickname)), array('nickname' => $this->user->nickname)),
// TRANS: Feed link text. %s is a username.
sprintf(_('Feed for favorites of %s (RSS 1.0)'), sprintf(_('Feed for favorites of %s (RSS 1.0)'),
$this->user->nickname)), $this->user->nickname)),
new Feed(Feed::RSS2, new Feed(Feed::RSS2,
@ -175,6 +176,7 @@ class ShowfavoritesAction extends OwnerDesignAction
array( array(
'id' => $this->user->nickname, 'id' => $this->user->nickname,
'format' => 'rss')), 'format' => 'rss')),
// TRANS: Feed link text. %s is a username.
sprintf(_('Feed for favorites of %s (RSS 2.0)'), sprintf(_('Feed for favorites of %s (RSS 2.0)'),
$this->user->nickname)), $this->user->nickname)),
new Feed(Feed::ATOM, new Feed(Feed::ATOM,
@ -182,6 +184,7 @@ class ShowfavoritesAction extends OwnerDesignAction
array( array(
'id' => $this->user->nickname, 'id' => $this->user->nickname,
'format' => 'atom')), 'format' => 'atom')),
// TRANS: Feed link text. %s is a username.
sprintf(_('Feed for favorites of %s (Atom)'), sprintf(_('Feed for favorites of %s (Atom)'),
$this->user->nickname))); $this->user->nickname)));
} }
@ -191,7 +194,6 @@ class ShowfavoritesAction extends OwnerDesignAction
* *
* @return void * @return void
*/ */
function showLocalNav() function showLocalNav()
{ {
$nav = new PersonalGroupNav($this); $nav = new PersonalGroupNav($this);
@ -203,12 +205,18 @@ class ShowfavoritesAction extends OwnerDesignAction
if (common_logged_in()) { if (common_logged_in()) {
$current_user = common_current_user(); $current_user = common_current_user();
if ($this->user->id === $current_user->id) { if ($this->user->id === $current_user->id) {
// TRANS: Text displayed instead of favourite notices for the current logged in user that has no favourites.
$message = _('You haven\'t chosen any favorite notices yet. Click the fave button on notices you like to bookmark them for later or shed a spotlight on them.'); $message = _('You haven\'t chosen any favorite notices yet. Click the fave button on notices you like to bookmark them for later or shed a spotlight on them.');
} else { } else {
// TRANS: Text displayed instead of favourite notices for a user that has no favourites while logged in.
// TRANS: %s is a username.
$message = sprintf(_('%s hasn\'t added any favorite notices yet. Post something interesting they would add to their favorites :)'), $this->user->nickname); $message = sprintf(_('%s hasn\'t added any favorite notices yet. Post something interesting they would add to their favorites :)'), $this->user->nickname);
} }
} }
else { else {
// TRANS: Text displayed instead of favourite notices for a user that has no favourites while not logged in.
// TRANS: %s is a username, %%%%action.register%%%% is a link to the user registration page.
// TRANS: (link text)[link] is a Mark Down link.
$message = sprintf(_('%s hasn\'t added any favorite notices yet. Why not [register an account](%%%%action.register%%%%) and then post something interesting they would add to their favorites :)'), $this->user->nickname); $message = sprintf(_('%s hasn\'t added any favorite notices yet. Why not [register an account](%%%%action.register%%%%) and then post something interesting they would add to their favorites :)'), $this->user->nickname);
} }
@ -224,7 +232,6 @@ class ShowfavoritesAction extends OwnerDesignAction
* *
* @return void * @return void
*/ */
function showContent() function showContent()
{ {
$nl = new FavoritesNoticeList($this->notice, $this); $nl = new FavoritesNoticeList($this->notice, $this);
@ -240,6 +247,7 @@ class ShowfavoritesAction extends OwnerDesignAction
} }
function showPageNotice() { function showPageNotice() {
// TRANS: Page notice for show favourites page.
$this->element('p', 'instructions', _('This is a way to share what you like.')); $this->element('p', 'instructions', _('This is a way to share what you like.'));
} }
} }

View File

@ -46,10 +46,8 @@ define('MEMBERS_PER_SECTION', 27);
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class ShowgroupAction extends GroupDesignAction class ShowgroupAction extends GroupDesignAction
{ {
/** page we're viewing. */ /** page we're viewing. */
var $page = null; var $page = null;
@ -58,7 +56,6 @@ class ShowgroupAction extends GroupDesignAction
* *
* @return boolean true * @return boolean true
*/ */
function isReadOnly($args) function isReadOnly($args)
{ {
return true; return true;
@ -69,18 +66,16 @@ class ShowgroupAction extends GroupDesignAction
* *
* @return string page title, with page number * @return string page title, with page number
*/ */
function title() function title()
{ {
if (!empty($this->group->fullname)) { $base = $this->group->getFancyName();
$base = $this->group->fullname . ' (' . $this->group->nickname . ')';
} else {
$base = $this->group->nickname;
}
if ($this->page == 1) { if ($this->page == 1) {
// TRANS: Page title for first group page. %s is a group name.
return sprintf(_('%s group'), $base); return sprintf(_('%s group'), $base);
} else { } else {
// TRANS: Page title for any but first group page.
// TRANS: %1$s is a group name, $2$s is a page number.
return sprintf(_('%1$s group, page %2$d'), return sprintf(_('%1$s group, page %2$d'),
$base, $base,
$this->page); $this->page);
@ -96,7 +91,6 @@ class ShowgroupAction extends GroupDesignAction
* *
* @return boolean success flag * @return boolean success flag
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
@ -118,6 +112,7 @@ class ShowgroupAction extends GroupDesignAction
} }
if (!$nickname) { if (!$nickname) {
// TRANS: Client error displayed if no nickname argument was given requesting a group page.
$this->clientError(_('No nickname.'), 404); $this->clientError(_('No nickname.'), 404);
return false; return false;
} }
@ -135,6 +130,7 @@ class ShowgroupAction extends GroupDesignAction
return false; return false;
} else { } else {
common_log(LOG_NOTICE, "Couldn't find local group for nickname '$nickname'"); common_log(LOG_NOTICE, "Couldn't find local group for nickname '$nickname'");
// TRANS: Client error displayed if no remote group with a given name was found requesting group page.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -143,6 +139,7 @@ class ShowgroupAction extends GroupDesignAction
$this->group = User_group::staticGet('id', $local->group_id); $this->group = User_group::staticGet('id', $local->group_id);
if (!$this->group) { if (!$this->group) {
// TRANS: Client error displayed if no local group with a given name was found requesting group page.
$this->clientError(_('No such group.'), 404); $this->clientError(_('No such group.'), 404);
return false; return false;
} }
@ -160,7 +157,6 @@ class ShowgroupAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function handle($args) function handle($args)
{ {
$this->showPage(); $this->showPage();
@ -171,7 +167,6 @@ class ShowgroupAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function showLocalNav() function showLocalNav()
{ {
$nav = new GroupNav($this, $this->group); $nav = new GroupNav($this, $this->group);
@ -183,10 +178,10 @@ class ShowgroupAction extends GroupDesignAction
* *
* Shows a group profile and a list of group notices * Shows a group profile and a list of group notices
*/ */
function showContent() function showContent()
{ {
$this->showGroupProfile(); $this->showGroupProfile();
$this->showGroupActions();
$this->showGroupNotices(); $this->showGroupNotices();
} }
@ -195,7 +190,6 @@ class ShowgroupAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function showGroupNotices() function showGroupNotices()
{ {
$notice = $this->group->getNotices(($this->page-1)*NOTICES_PER_PAGE, $notice = $this->group->getNotices(($this->page-1)*NOTICES_PER_PAGE,
@ -218,109 +212,128 @@ class ShowgroupAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function showGroupProfile() function showGroupProfile()
{ {
$this->elementStart('div', array('id' => 'i', $this->elementStart('div', array('id' => 'i',
'class' => 'entity_profile vcard author')); 'class' => 'entity_profile vcard author'));
$this->element('h2', null, _('Group profile')); if (Event::handle('StartGroupProfileElements', array($this, $this->group))) {
$this->elementStart('dl', 'entity_depiction'); // TRANS: Group profile header (h2). Text hidden by default.
$this->element('dt', null, _('Avatar')); $this->element('h2', null, _('Group profile'));
$this->elementStart('dd');
$logo = ($this->group->homepage_logo) ? $this->elementStart('dl', 'entity_depiction');
$this->group->homepage_logo : User_group::defaultLogo(AVATAR_PROFILE_SIZE); // TRANS: Label for group avatar (dt). Text hidden by default.
$this->element('dt', null, _('Avatar'));
$this->element('img', array('src' => $logo,
'class' => 'photo avatar',
'width' => AVATAR_PROFILE_SIZE,
'height' => AVATAR_PROFILE_SIZE,
'alt' => $this->group->nickname));
$this->elementEnd('dd');
$this->elementEnd('dl');
$this->elementStart('dl', 'entity_nickname');
$this->element('dt', null, _('Nickname'));
$this->elementStart('dd');
$hasFN = ($this->group->fullname) ? 'nickname url uid' : 'fn org nickname url uid';
$this->element('a', array('href' => $this->group->homeUrl(),
'rel' => 'me', 'class' => $hasFN),
$this->group->nickname);
$this->elementEnd('dd');
$this->elementEnd('dl');
if ($this->group->fullname) {
$this->elementStart('dl', 'entity_fn');
$this->element('dt', null, _('Full name'));
$this->elementStart('dd'); $this->elementStart('dd');
$this->element('span', 'fn org', $this->group->fullname);
$logo = ($this->group->homepage_logo) ?
$this->group->homepage_logo : User_group::defaultLogo(AVATAR_PROFILE_SIZE);
$this->element('img', array('src' => $logo,
'class' => 'photo avatar',
'width' => AVATAR_PROFILE_SIZE,
'height' => AVATAR_PROFILE_SIZE,
'alt' => $this->group->nickname));
$this->elementEnd('dd'); $this->elementEnd('dd');
$this->elementEnd('dl'); $this->elementEnd('dl');
}
if ($this->group->location) { $this->elementStart('dl', 'entity_nickname');
$this->elementStart('dl', 'entity_location'); // TRANS: Label for group nickname (dt). Text hidden by default.
$this->element('dt', null, _('Location')); $this->element('dt', null, _('Nickname'));
$this->element('dd', 'label', $this->group->location);
$this->elementEnd('dl');
}
if ($this->group->homepage) {
$this->elementStart('dl', 'entity_url');
$this->element('dt', null, _('URL'));
$this->elementStart('dd'); $this->elementStart('dd');
$this->element('a', array('href' => $this->group->homepage, $hasFN = ($this->group->fullname) ? 'nickname url uid' : 'fn org nickname url uid';
'rel' => 'me', 'class' => 'url'), $this->element('a', array('href' => $this->group->homeUrl(),
$this->group->homepage); 'rel' => 'me', 'class' => $hasFN),
$this->group->nickname);
$this->elementEnd('dd'); $this->elementEnd('dd');
$this->elementEnd('dl'); $this->elementEnd('dl');
}
if ($this->group->description) { if ($this->group->fullname) {
$this->elementStart('dl', 'entity_note'); $this->elementStart('dl', 'entity_fn');
$this->element('dt', null, _('Note')); // TRANS: Label for full group name (dt). Text hidden by default.
$this->element('dd', 'note', $this->group->description); $this->element('dt', null, _('Full name'));
$this->elementEnd('dl'); $this->elementStart('dd');
} $this->element('span', 'fn org', $this->group->fullname);
$this->elementEnd('dd');
if (common_config('group', 'maxaliases') > 0) {
$aliases = $this->group->getAliases();
if (!empty($aliases)) {
$this->elementStart('dl', 'entity_aliases');
$this->element('dt', null, _('Aliases'));
$this->element('dd', 'aliases', implode(' ', $aliases));
$this->elementEnd('dl'); $this->elementEnd('dl');
} }
if ($this->group->location) {
$this->elementStart('dl', 'entity_location');
// TRANS: Label for group location (dt). Text hidden by default.
$this->element('dt', null, _('Location'));
$this->element('dd', 'label', $this->group->location);
$this->elementEnd('dl');
}
if ($this->group->homepage) {
$this->elementStart('dl', 'entity_url');
// TRANS: Label for group URL (dt). Text hidden by default.
$this->element('dt', null, _('URL'));
$this->elementStart('dd');
$this->element('a', array('href' => $this->group->homepage,
'rel' => 'me', 'class' => 'url'),
$this->group->homepage);
$this->elementEnd('dd');
$this->elementEnd('dl');
}
if ($this->group->description) {
$this->elementStart('dl', 'entity_note');
// TRANS: Label for group description or group note (dt). Text hidden by default.
$this->element('dt', null, _('Note'));
$this->element('dd', 'note', $this->group->description);
$this->elementEnd('dl');
}
if (common_config('group', 'maxaliases') > 0) {
$aliases = $this->group->getAliases();
if (!empty($aliases)) {
$this->elementStart('dl', 'entity_aliases');
// TRANS: Label for group aliases (dt). Text hidden by default.
$this->element('dt', null, _('Aliases'));
$this->element('dd', 'aliases', implode(' ', $aliases));
$this->elementEnd('dl');
}
}
Event::handle('EndGroupProfileElements', array($this, $this->group));
} }
$this->elementEnd('div'); $this->elementEnd('div');
}
function showGroupActions()
{
$cur = common_current_user(); $cur = common_current_user();
$this->elementStart('div', 'entity_actions'); $this->elementStart('div', 'entity_actions');
// TRANS: Group actions header (h2). Text hidden by default.
$this->element('h2', null, _('Group actions')); $this->element('h2', null, _('Group actions'));
$this->elementStart('ul'); $this->elementStart('ul');
$this->elementStart('li', 'entity_subscribe'); if (Event::handle('StartGroupActionsList', array($this, $this->group))) {
if (Event::handle('StartGroupSubscribe', array($this, $this->group))) { $this->elementStart('li', 'entity_subscribe');
if ($cur) { if (Event::handle('StartGroupSubscribe', array($this, $this->group))) {
if ($cur->isMember($this->group)) { if ($cur) {
$lf = new LeaveForm($this, $this->group); if ($cur->isMember($this->group)) {
$lf->show(); $lf = new LeaveForm($this, $this->group);
} else if (!Group_block::isBlocked($this->group, $cur->getProfile())) { $lf->show();
$jf = new JoinForm($this, $this->group); } else if (!Group_block::isBlocked($this->group, $cur->getProfile())) {
$jf->show(); $jf = new JoinForm($this, $this->group);
$jf->show();
}
} }
Event::handle('EndGroupSubscribe', array($this, $this->group));
} }
Event::handle('EndGroupSubscribe', array($this, $this->group));
}
$this->elementEnd('li');
if ($cur && $cur->hasRight(Right::DELETEGROUP)) {
$this->elementStart('li', 'entity_delete');
$df = new DeleteGroupForm($this, $this->group);
$df->show();
$this->elementEnd('li'); $this->elementEnd('li');
if ($cur && $cur->hasRight(Right::DELETEGROUP)) {
$this->elementStart('li', 'entity_delete');
$df = new DeleteGroupForm($this, $this->group);
$df->show();
$this->elementEnd('li');
}
Event::handle('EndGroupActionsList', array($this, $this->group));
} }
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->elementEnd('div'); $this->elementEnd('div');
@ -331,7 +344,6 @@ class ShowgroupAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function getFeeds() function getFeeds()
{ {
$url = $url =
@ -341,23 +353,27 @@ class ShowgroupAction extends GroupDesignAction
return array(new Feed(Feed::RSS1, return array(new Feed(Feed::RSS1,
common_local_url('grouprss', common_local_url('grouprss',
array('nickname' => $this->group->nickname)), array('nickname' => $this->group->nickname)),
// TRANS: Tooltip for feed link. %s is a group nickname.
sprintf(_('Notice feed for %s group (RSS 1.0)'), sprintf(_('Notice feed for %s group (RSS 1.0)'),
$this->group->nickname)), $this->group->nickname)),
new Feed(Feed::RSS2, new Feed(Feed::RSS2,
common_local_url('ApiTimelineGroup', common_local_url('ApiTimelineGroup',
array('format' => 'rss', array('format' => 'rss',
'id' => $this->group->id)), 'id' => $this->group->id)),
// TRANS: Tooltip for feed link. %s is a group nickname.
sprintf(_('Notice feed for %s group (RSS 2.0)'), sprintf(_('Notice feed for %s group (RSS 2.0)'),
$this->group->nickname)), $this->group->nickname)),
new Feed(Feed::ATOM, new Feed(Feed::ATOM,
common_local_url('ApiTimelineGroup', common_local_url('ApiTimelineGroup',
array('format' => 'atom', array('format' => 'atom',
'id' => $this->group->id)), 'id' => $this->group->id)),
// TRANS: Tooltip for feed link. %s is a group nickname.
sprintf(_('Notice feed for %s group (Atom)'), sprintf(_('Notice feed for %s group (Atom)'),
$this->group->nickname)), $this->group->nickname)),
new Feed(Feed::FOAF, new Feed(Feed::FOAF,
common_local_url('foafgroup', common_local_url('foafgroup',
array('nickname' => $this->group->nickname)), array('nickname' => $this->group->nickname)),
// TRANS: Tooltip for feed link. %s is a group nickname.
sprintf(_('FOAF for %s group'), sprintf(_('FOAF for %s group'),
$this->group->nickname))); $this->group->nickname)));
} }
@ -367,7 +383,6 @@ class ShowgroupAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function showSections() function showSections()
{ {
$this->showMembers(); $this->showMembers();
@ -382,7 +397,6 @@ class ShowgroupAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function showMembers() function showMembers()
{ {
$member = $this->group->getMembers(0, MEMBERS_PER_SECTION); $member = $this->group->getMembers(0, MEMBERS_PER_SECTION);
@ -396,17 +410,22 @@ class ShowgroupAction extends GroupDesignAction
if (Event::handle('StartShowGroupMembersMiniList', array($this))) { if (Event::handle('StartShowGroupMembersMiniList', array($this))) {
// TRANS: Header for mini list of group members on a group page (h2).
$this->element('h2', null, _('Members')); $this->element('h2', null, _('Members'));
$gmml = new GroupMembersMiniList($member, $this); $gmml = new GroupMembersMiniList($member, $this);
$cnt = $gmml->show(); $cnt = $gmml->show();
if ($cnt == 0) { if ($cnt == 0) {
// TRANS: Description for mini list of group members on a group page when the group has no members.
$this->element('p', null, _('(None)')); $this->element('p', null, _('(None)'));
} }
// @todo FIXME: Should be shown if a group has more than 27 members, but I do not see it displayed at
// for example http://identi.ca/group/statusnet. Broken?
if ($cnt > MEMBERS_PER_SECTION) { if ($cnt > MEMBERS_PER_SECTION) {
$this->element('a', array('href' => common_local_url('groupmembers', $this->element('a', array('href' => common_local_url('groupmembers',
array('nickname' => $this->group->nickname))), array('nickname' => $this->group->nickname))),
// TRANS: Link to all group members from mini list of group members if group has more than n members.
_('All members')); _('All members'));
} }
@ -421,7 +440,6 @@ class ShowgroupAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function showAdmins() function showAdmins()
{ {
$adminSection = new GroupAdminSection($this, $this->group); $adminSection = new GroupAdminSection($this, $this->group);
@ -433,22 +451,26 @@ class ShowgroupAction extends GroupDesignAction
* *
* @return void * @return void
*/ */
function showStatistics() function showStatistics()
{ {
$this->elementStart('div', array('id' => 'entity_statistics', $this->elementStart('div', array('id' => 'entity_statistics',
'class' => 'section')); 'class' => 'section'));
// TRANS: Header for group statistics on a group page (h2).
$this->element('h2', null, _('Statistics')); $this->element('h2', null, _('Statistics'));
$this->elementStart('dl', 'entity_created'); $this->elementStart('dl', 'entity_created');
$this->element('dt', null, _('Created')); // @todo FIXME: i18n issue. This label gets a colon added from somewhere. Should be part of the message.
// TRANS: Label for creation date in statistics on group page.
$this->element('dt', null, _m('LABEL','Created'));
$this->element('dd', null, date('j M Y', $this->element('dd', null, date('j M Y',
strtotime($this->group->created))); strtotime($this->group->created)));
$this->elementEnd('dl'); $this->elementEnd('dl');
$this->elementStart('dl', 'entity_members'); $this->elementStart('dl', 'entity_members');
$this->element('dt', null, _('Members')); // @todo FIXME: i18n issue. This label gets a colon added from somewhere. Should be part of the message.
// TRANS: Label for member count in statistics on group page.
$this->element('dt', null, _m('LABEL','Members'));
$this->element('dd', null, $this->group->getMemberCount()); $this->element('dd', null, $this->group->getMemberCount());
$this->elementEnd('dl'); $this->elementEnd('dl');
@ -458,12 +480,21 @@ class ShowgroupAction extends GroupDesignAction
function showAnonymousMessage() function showAnonymousMessage()
{ {
if (!(common_config('site','closed') || common_config('site','inviteonly'))) { if (!(common_config('site','closed') || common_config('site','inviteonly'))) {
// @todo FIXME: use group full name here if available instead of (uglier) primary alias.
// TRANS: Notice on group pages for anonymous users for StatusNet sites that accept new registrations.
// TRANS: **%s** is the group alias, %%%%site.name%%%% is the site name,
// TRANS: %%%%action.register%%%% is the URL for registration, %%%%doc.help%%%% is a URL to help.
// TRANS: This message contains Markdown links. Ensure they are formatted correctly: [Description](link).
$m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . $m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [StatusNet](http://status.net/) tool. Its members share ' . 'based on the Free Software [StatusNet](http://status.net/) tool. Its members share ' .
'short messages about their life and interests. '. 'short messages about their life and interests. '.
'[Join now](%%%%action.register%%%%) to become part of this group and many more! ([Read more](%%%%doc.help%%%%))'), '[Join now](%%%%action.register%%%%) to become part of this group and many more! ([Read more](%%%%doc.help%%%%))'),
$this->group->nickname); $this->group->nickname);
} else { } else {
// @todo FIXME: use group full name here if available instead of (uglier) primary alias.
// TRANS: Notice on group pages for anonymous users for StatusNet sites that accept no new registrations.
// TRANS: **%s** is the group alias, %%%%site.name%%%% is the site name,
// TRANS: This message contains Markdown links. Ensure they are formatted correctly: [Description](link).
$m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . $m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [StatusNet](http://status.net/) tool. Its members share ' . 'based on the Free Software [StatusNet](http://status.net/) tool. Its members share ' .
'short messages about their life and interests. '), 'short messages about their life and interests. '),
@ -492,6 +523,7 @@ class GroupAdminSection extends ProfileSection
function title() function title()
{ {
// TRANS: Header for list of group administrators on a group page (h2).
return _('Admins'); return _('Admins');
} }
@ -527,4 +559,3 @@ class GroupMembersMiniListItem extends ProfileMiniListItem
return $aAttrs; return $aAttrs;
} }
} }

View File

@ -26,17 +26,13 @@
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
if (!defined('STATUSNET') && !defined('LACONICA')) { if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1); exit(1);
} }
require_once INSTALLDIR.'/lib/mailbox.php';
/** /**
* Show a single message * Show a single message
* *
* // XXX: It is totally weird how this works!
*
* @category Personal * @category Personal
* @package StatusNet * @package StatusNet
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@status.net>
@ -44,18 +40,17 @@ require_once INSTALLDIR.'/lib/mailbox.php';
* @link http://status.net/ * @link http://status.net/
*/ */
class ShowmessageAction extends MailboxAction class ShowmessageAction extends Action
{ {
/** /**
* Message object to show * Message object to show
*/ */
var $message = null; var $message = null;
/** /**
* The current user * The current user
*/ */
var $user = null; var $user = null;
/** /**
@ -67,63 +62,94 @@ class ShowmessageAction extends MailboxAction
* *
* @return success flag * @return success flag
*/ */
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
$this->page = 1; $this->page = 1;
$id = $this->trimmed('message'); $id = $this->trimmed('message');
$this->message = Message::staticGet('id', $id); $this->message = Message::staticGet('id', $id);
if (!$this->message) { if (!$this->message) {
// TRANS: Client error displayed requesting a single message that does not exist.
$this->clientError(_('No such message.'), 404); $this->clientError(_('No such message.'), 404);
return false; return false;
} }
$this->user = common_current_user(); $this->user = common_current_user();
if (empty($this->user) ||
($this->user->id != $this->message->from_profile &&
$this->user->id != $this->message->to_profile)) {
// TRANS: Client error displayed requesting a single direct message the requesting user was not a party in.
throw new ClientException(_('Only the sender and recipient ' .
'may read this message.'), 403);
}
return true; return true;
} }
function handle($args) function handle($args)
{ {
Action::handle($args); $this->showPage();
if ($this->user && ($this->user->id == $this->message->from_profile ||
$this->user->id == $this->message->to_profile)) {
$this->showPage();
} else {
$this->clientError(_('Only the sender and recipient ' .
'may read this message.'), 403);
return;
}
} }
function title() function title()
{ {
if ($this->user->id == $this->message->from_profile) { if ($this->user->id == $this->message->from_profile) {
$to = $this->message->getTo(); $to = $this->message->getTo();
return sprintf(_("Message to %1\$s on %2\$s"), // @todo FIXME: Might be nice if the timestamp could be localised.
// TRANS: Page title for single direct message display when viewing user is the sender.
// TRANS: %1$s is the addressed user's nickname, $2$s is a timestamp.
return sprintf(_('Message to %1$s on %2$s'),
$to->nickname, $to->nickname,
common_exact_date($this->message->created)); common_exact_date($this->message->created));
} else if ($this->user->id == $this->message->to_profile) { } else if ($this->user->id == $this->message->to_profile) {
$from = $this->message->getFrom(); $from = $this->message->getFrom();
return sprintf(_("Message from %1\$s on %2\$s"), // @todo FIXME: Might be nice if the timestamp could be localised.
// TRANS: Page title for single message display.
// TRANS: %1$s is the sending user's nickname, $2$s is a timestamp.
return sprintf(_('Message from %1$s on %2$s'),
$from->nickname, $from->nickname,
common_exact_date($this->message->created)); common_exact_date($this->message->created));
} }
} }
function getMessages()
{ function showContent()
$message = new Message(); {
$message->id = $this->message->id; $this->elementStart('ul', 'notices messages');
$message->find(); $ml = new ShowMessageListItem($this, $this->message, $this->user);
return $message; $ml->show();
$this->elementEnd('ul');
} }
function isReadOnly($args)
{
return true;
}
/**
* Don't show aside
*
* @return void
*/
function showAside() {
}
}
class ShowMessageListItem extends MessageListItem
{
var $user;
function __construct($out, $message, $user)
{
parent::__construct($out, $message);
$this->user = $user;
}
function getMessageProfile() function getMessageProfile()
{ {
if ($this->user->id == $this->message->from_profile) { if ($this->user->id == $this->message->from_profile) {
@ -135,50 +161,4 @@ class ShowmessageAction extends MailboxAction
return null; return null;
} }
} }
/**
* Don't show local navigation
*
* @return void
*/
function showLocalNavBlock()
{
}
/**
* Don't show page notice
*
* @return void
*/
function showPageNoticeBlock()
{
}
/**
* Don't show aside
*
* @return void
*/
function showAside()
{
}
/**
* Don't show any instructions
*
* @return string
*/
function getInstructions()
{
return '';
}
function isReadOnly($args)
{
return true;
}
} }

View File

@ -167,11 +167,7 @@ class ShownoticeAction extends OwnerDesignAction
function title() function title()
{ {
if (!empty($this->profile->fullname)) { $base = $this->profile->getFancyName();
$base = $this->profile->fullname . ' (' . $this->profile->nickname . ')';
} else {
$base = $this->profile->nickname;
}
return sprintf(_('%1$s\'s status on %2$s'), return sprintf(_('%1$s\'s status on %2$s'),
$base, $base,
@ -335,8 +331,38 @@ class SingleNoticeItem extends DoFollowListItem
$this->showEnd(); $this->showEnd();
} }
/**
* For our zoomed-in special case we'll use a fuller list
* for the attachment info.
*/
function showNoticeAttachments() { function showNoticeAttachments() {
$al = new AttachmentList($this->notice, $this->out); $al = new AttachmentList($this->notice, $this->out);
$al->show(); $al->show();
} }
/**
* show the avatar of the notice's author
*
* We use the larger size for single notice page.
*
* @return void
*/
function showAvatar()
{
$avatar_size = AVATAR_PROFILE_SIZE;
$avatar = $this->profile->getAvatar($avatar_size);
$this->out->element('img', array('src' => ($avatar) ?
$avatar->displayUrl() :
Avatar::defaultImage($avatar_size),
'class' => 'avatar photo',
'width' => $avatar_size,
'height' => $avatar_size,
'alt' =>
($this->profile->fullname) ?
$this->profile->fullname :
$this->profile->nickname));
}
} }

View File

@ -63,21 +63,26 @@ class ShowstreamAction extends ProfileAction
function title() function title()
{ {
if (!empty($this->profile->fullname)) { $base = $this->profile->getFancyName();
$base = $this->profile->fullname . ' (' . $this->user->nickname . ') ';
} else {
$base = $this->user->nickname;
}
if (!empty($this->tag)) { if (!empty($this->tag)) {
$base .= sprintf(_(' tagged %s'), $this->tag); if ($this->page == 1) {
} // TRANS: Page title showing tagged notices in one user's stream. %1$s is the username, %2$s is the hash tag.
return sprintf(_('%1$s tagged %2$s'), $base, $this->tag);
if ($this->page == 1) { } else {
return $base; // TRANS: Page title showing tagged notices in one user's stream.
// TRANS: %1$s is the username, %2$s is the hash tag, %1$d is the page number.
return sprintf(_('%1$s tagged %2$s, page %3$d'), $base, $this->tag, $this->page);
}
} else { } else {
return sprintf(_('%1$s, page %2$d'), if ($this->page == 1) {
$base, return $base;
$this->page); } else {
// TRANS: Extended page title showing tagged notices in one user's stream.
// TRANS: %1$s is the username, %2$d is the page number.
return sprintf(_('%1$s, page %2$d'),
$base,
$this->page);
}
} }
} }
@ -117,6 +122,8 @@ class ShowstreamAction extends ProfileAction
common_local_url('userrss', common_local_url('userrss',
array('nickname' => $this->user->nickname, array('nickname' => $this->user->nickname,
'tag' => $this->tag)), 'tag' => $this->tag)),
// TRANS: Title for link to notice feed.
// TRANS: %1$s is a user nickname, %2$s is a hashtag.
sprintf(_('Notice feed for %1$s tagged %2$s (RSS 1.0)'), sprintf(_('Notice feed for %1$s tagged %2$s (RSS 1.0)'),
$this->user->nickname, $this->tag))); $this->user->nickname, $this->tag)));
} }
@ -124,6 +131,8 @@ class ShowstreamAction extends ProfileAction
return array(new Feed(Feed::RSS1, return array(new Feed(Feed::RSS1,
common_local_url('userrss', common_local_url('userrss',
array('nickname' => $this->user->nickname)), array('nickname' => $this->user->nickname)),
// TRANS: Title for link to notice feed.
// TRANS: %s is a user nickname.
sprintf(_('Notice feed for %s (RSS 1.0)'), sprintf(_('Notice feed for %s (RSS 1.0)'),
$this->user->nickname)), $this->user->nickname)),
new Feed(Feed::RSS2, new Feed(Feed::RSS2,
@ -131,6 +140,8 @@ class ShowstreamAction extends ProfileAction
array( array(
'id' => $this->user->id, 'id' => $this->user->id,
'format' => 'rss')), 'format' => 'rss')),
// TRANS: Title for link to notice feed.
// TRANS: %s is a user nickname.
sprintf(_('Notice feed for %s (RSS 2.0)'), sprintf(_('Notice feed for %s (RSS 2.0)'),
$this->user->nickname)), $this->user->nickname)),
new Feed(Feed::ATOM, new Feed(Feed::ATOM,
@ -143,6 +154,8 @@ class ShowstreamAction extends ProfileAction
new Feed(Feed::FOAF, new Feed(Feed::FOAF,
common_local_url('foaf', array('nickname' => common_local_url('foaf', array('nickname' =>
$this->user->nickname)), $this->user->nickname)),
// TRANS: Title for link to notice feed. FOAF stands for Friend of a Friend.
// TRANS: More information at http://www.foaf-project.org. %s is a user nickname.
sprintf(_('FOAF for %s'), $this->user->nickname))); sprintf(_('FOAF for %s'), $this->user->nickname)));
} }
@ -194,17 +207,23 @@ class ShowstreamAction extends ProfileAction
function showEmptyListMessage() function showEmptyListMessage()
{ {
$message = sprintf(_('This is the timeline for %1$s but %2$s hasn\'t posted anything yet.'), $this->user->nickname, $this->user->nickname) . ' '; // TRANS: First sentence of empty list message for a stream. $1%s is a user nickname.
$message = sprintf(_('This is the timeline for %1$s, but %1$s hasn\'t posted anything yet.'), $this->user->nickname) . ' ';
if (common_logged_in()) { if (common_logged_in()) {
$current_user = common_current_user(); $current_user = common_current_user();
if ($this->user->id === $current_user->id) { if ($this->user->id === $current_user->id) {
// TRANS: Second sentence of empty list message for a stream for the user themselves.
$message .= _('Seen anything interesting recently? You haven\'t posted any notices yet, now would be a good time to start :)'); $message .= _('Seen anything interesting recently? You haven\'t posted any notices yet, now would be a good time to start :)');
} else { } else {
// TRANS: Second sentence of empty list message for a non-self stream. %1$s is a user nickname, %2$s is a part of a URL.
// TRANS: This message contains a Markdown link. Keep "](" together.
$message .= sprintf(_('You can try to nudge %1$s or [post something to them](%%%%action.newnotice%%%%?status_textarea=%2$s).'), $this->user->nickname, '@' . $this->user->nickname); $message .= sprintf(_('You can try to nudge %1$s or [post something to them](%%%%action.newnotice%%%%?status_textarea=%2$s).'), $this->user->nickname, '@' . $this->user->nickname);
} }
} }
else { else {
// TRANS: Second sentence of empty message for anonymous users. %s is a user nickname.
// TRANS: This message contains a Markdown link. Keep "](" together.
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->user->nickname); $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->user->nickname);
} }
@ -240,11 +259,15 @@ class ShowstreamAction extends ProfileAction
function showAnonymousMessage() function showAnonymousMessage()
{ {
if (!(common_config('site','closed') || common_config('site','inviteonly'))) { if (!(common_config('site','closed') || common_config('site','inviteonly'))) {
// TRANS: Announcement for anonymous users showing a stream if site registrations are open.
// TRANS: This message contains a Markdown link. Keep "](" together.
$m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . $m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [StatusNet](http://status.net/) tool. ' . 'based on the Free Software [StatusNet](http://status.net/) tool. ' .
'[Join now](%%%%action.register%%%%) to follow **%s**\'s notices and many more! ([Read more](%%%%doc.help%%%%))'), '[Join now](%%%%action.register%%%%) to follow **%s**\'s notices and many more! ([Read more](%%%%doc.help%%%%))'),
$this->user->nickname, $this->user->nickname); $this->user->nickname, $this->user->nickname);
} else { } else {
// TRANS: Announcement for anonymous users showing a stream if site registrations are closed or invite only.
// TRANS: This message contains a Markdown link. Keep "](" together.
$m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . $m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [StatusNet](http://status.net/) tool. '), 'based on the Free Software [StatusNet](http://status.net/) tool. '),
$this->user->nickname, $this->user->nickname); $this->user->nickname, $this->user->nickname);
@ -284,7 +307,6 @@ class ProfileNoticeListItem extends DoFollowListItem
* *
* @return void * @return void
*/ */
function showRepeat() function showRepeat()
{ {
if (!empty($this->repeat)) { if (!empty($this->repeat)) {
@ -295,13 +317,14 @@ class ProfileNoticeListItem extends DoFollowListItem
'class' => 'url'); 'class' => 'url');
if (!empty($this->profile->fullname)) { if (!empty($this->profile->fullname)) {
$attrs['title'] = $this->profile->fullname . ' (' . $this->profile->nickname . ')'; $attrs['title'] = $this->profile->getFancyName();
} }
$this->out->elementStart('span', 'repeat'); $this->out->elementStart('span', 'repeat');
$text_link = XMLStringer::estring('a', $attrs, $this->profile->nickname); $text_link = XMLStringer::estring('a', $attrs, $this->profile->nickname);
// TRANS: Link to the author of a repeated notice. %s is a linked nickname.
$this->out->raw(sprintf(_('Repeat of %s'), $text_link)); $this->out->raw(sprintf(_('Repeat of %s'), $text_link));
$this->out->elementEnd('span'); $this->out->elementEnd('span');

View File

@ -42,7 +42,6 @@ require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
class SitenoticeadminpanelAction extends AdminPanelAction class SitenoticeadminpanelAction extends AdminPanelAction
{ {
/** /**
@ -50,9 +49,9 @@ class SitenoticeadminpanelAction extends AdminPanelAction
* *
* @return string page title * @return string page title
*/ */
function title() function title()
{ {
// TRANS: Page title for site-wide notice tab in admin panel.
return _('Site Notice'); return _('Site Notice');
} }
@ -61,9 +60,9 @@ class SitenoticeadminpanelAction extends AdminPanelAction
* *
* @return string instructions * @return string instructions
*/ */
function getInstructions() function getInstructions()
{ {
// TRANS: Instructions for site-wide notice tab in admin panel.
return _('Edit site-wide message'); return _('Edit site-wide message');
} }
@ -72,7 +71,6 @@ class SitenoticeadminpanelAction extends AdminPanelAction
* *
* @return void * @return void
*/ */
function showForm() function showForm()
{ {
$form = new SiteNoticeAdminPanelForm($this); $form = new SiteNoticeAdminPanelForm($this);
@ -85,7 +83,6 @@ class SitenoticeadminpanelAction extends AdminPanelAction
* *
* @return void * @return void
*/ */
function saveSettings() function saveSettings()
{ {
$siteNotice = $this->trimmed('site-notice'); $siteNotice = $this->trimmed('site-notice');
@ -100,6 +97,7 @@ class SitenoticeadminpanelAction extends AdminPanelAction
$result = Config::save('site', 'notice', $siteNotice); $result = Config::save('site', 'notice', $siteNotice);
if (!$result) { if (!$result) {
// TRANS: Server error displayed when saving a site-wide notice was impossible.
$this->ServerError(_("Unable to save site notice.")); $this->ServerError(_("Unable to save site notice."));
} }
} }
@ -110,7 +108,8 @@ class SitenoticeadminpanelAction extends AdminPanelAction
if (mb_strlen($siteNotice) > 255) { if (mb_strlen($siteNotice) > 255) {
$this->clientError( $this->clientError(
_('Max length for the site-wide notice is 255 chars.') // TRANS: Client error displayed when a site-wide notice was longer than allowed.
_('Maximum length for the site-wide notice is 255 characters.')
); );
} }
@ -173,9 +172,11 @@ class SiteNoticeAdminPanelForm extends AdminForm
$this->out->elementStart('li'); $this->out->elementStart('li');
$this->out->textarea( $this->out->textarea(
'site-notice', 'site-notice',
// TRANS: Label for site-wide notice text field in admin panel.
_('Site notice text'), _('Site notice text'),
common_config('site', 'notice'), common_config('site', 'notice'),
_('Site-wide notice text (255 chars max; HTML okay)') // TRANS: Tooltip for site-wide notice text field in admin panel.
_('Site-wide notice text (255 characters maximum; HTML allowed)')
); );
$this->out->elementEnd('li'); $this->out->elementEnd('li');
@ -192,9 +193,11 @@ class SiteNoticeAdminPanelForm extends AdminForm
{ {
$this->out->submit( $this->out->submit(
'submit', 'submit',
_('Save'), // TRANS: Button text for saving site notice in admin panel.
_m('BUTTON','Save'),
'submit', 'submit',
null, null,
// TRANS: Title for button to save site notice in admin panel.
_('Save site notice') _('Save site notice')
); );
} }

View File

@ -44,7 +44,6 @@ require_once INSTALLDIR.'/lib/connectsettingsaction.php';
* *
* @see SettingsAction * @see SettingsAction
*/ */
class SmssettingsAction extends ConnectSettingsAction class SmssettingsAction extends ConnectSettingsAction
{ {
/** /**
@ -52,7 +51,6 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @return string Title of the page * @return string Title of the page
*/ */
function title() function title()
{ {
// TRANS: Title for SMS settings. // TRANS: Title for SMS settings.
@ -64,7 +62,6 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @return instructions for use * @return instructions for use
*/ */
function getInstructions() function getInstructions()
{ {
// XXX: For consistency of parameters in messages, this should be a // XXX: For consistency of parameters in messages, this should be a
@ -88,7 +85,6 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function showContent() function showContent()
{ {
if (!common_config('sms', 'enabled')) { if (!common_config('sms', 'enabled')) {
@ -219,7 +215,6 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @todo very similar to EmailsettingsAction::getConfirmation(); refactor? * @todo very similar to EmailsettingsAction::getConfirmation(); refactor?
*/ */
function getConfirmation() function getConfirmation()
{ {
$user = common_current_user(); $user = common_current_user();
@ -246,7 +241,6 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function handlePost() function handlePost()
{ {
// CSRF protection // CSRF protection
@ -285,7 +279,6 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function savePreferences() function savePreferences()
{ {
$smsnotify = $this->boolean('smsnotify'); $smsnotify = $this->boolean('smsnotify');
@ -305,7 +298,7 @@ class SmssettingsAction extends ConnectSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error updating SMS preferences. // TRANS: Server error thrown on database error updating SMS preferences.
$this->serverError(_('Couldn\'t update user.')); $this->serverError(_('Could not update user.'));
return; return;
} }
@ -323,7 +316,6 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function addAddress() function addAddress()
{ {
$user = common_current_user(); $user = common_current_user();
@ -370,7 +362,7 @@ class SmssettingsAction extends ConnectSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($confirm, 'INSERT', __FILE__); common_log_db_error($confirm, 'INSERT', __FILE__);
// TRANS: Server error thrown on database error adding SMS confirmation code. // TRANS: Server error thrown on database error adding SMS confirmation code.
$this->serverError(_('Couldn\'t insert confirmation code.')); $this->serverError(_('Could not insert confirmation code.'));
return; return;
} }
@ -395,7 +387,6 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function cancelConfirmation() function cancelConfirmation()
{ {
$sms = $this->trimmed('sms'); $sms = $this->trimmed('sms');
@ -419,7 +410,7 @@ class SmssettingsAction extends ConnectSettingsAction
if (!$result) { if (!$result) {
common_log_db_error($confirm, 'DELETE', __FILE__); common_log_db_error($confirm, 'DELETE', __FILE__);
// TRANS: Server error thrown on database error canceling SMS phone number confirmation. // TRANS: Server error thrown on database error canceling SMS phone number confirmation.
$this->serverError(_('Couldn\'t delete email confirmation.')); $this->serverError(_('Could not delete email confirmation.'));
return; return;
} }
@ -432,7 +423,6 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function removeAddress() function removeAddress()
{ {
$user = common_current_user(); $user = common_current_user();
@ -461,7 +451,7 @@ class SmssettingsAction extends ConnectSettingsAction
if (!$result) { if (!$result) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error removing a registered SMS phone number. // TRANS: Server error thrown on database error removing a registered SMS phone number.
$this->serverError(_('Couldn\'t update user.')); $this->serverError(_('Could not update user.'));
return; return;
} }
$user->query('COMMIT'); $user->query('COMMIT');
@ -479,7 +469,6 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @return boolean does the number exist * @return boolean does the number exist
*/ */
function smsExists($sms) function smsExists($sms)
{ {
$user = common_current_user(); $user = common_current_user();
@ -498,7 +487,6 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function carrierSelect() function carrierSelect()
{ {
$carrier = new Sms_carrier(); $carrier = new Sms_carrier();
@ -538,14 +526,13 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function confirmCode() function confirmCode()
{ {
$code = $this->trimmed('code'); $code = $this->trimmed('code');
if (!$code) { if (!$code) {
// TRANS: Message given saving SMS phone number confirmation code without having provided one. // TRANS: Message given saving SMS phone number confirmation code without having provided one.
$this->showForm(_('No code entered')); $this->showForm(_('No code entered.'));
return; return;
} }
@ -559,12 +546,12 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @return void * @return void
*/ */
function removeIncoming() function removeIncoming()
{ {
$user = common_current_user(); $user = common_current_user();
if (!$user->incomingemail) { if (!$user->incomingemail) {
// TRANS: Form validation error displayed when trying to remove an incoming e-mail address while no address has been set.
$this->showForm(_('No incoming email address.')); $this->showForm(_('No incoming email address.'));
return; return;
} }
@ -575,7 +562,7 @@ class SmssettingsAction extends ConnectSettingsAction
if (!$user->updateKeys($orig)) { if (!$user->updateKeys($orig)) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
$this->serverError(_("Couldn't update user record.")); $this->serverError(_("Could not update user record."));
} }
$this->showForm(_('Incoming email address removed.'), true); $this->showForm(_('Incoming email address removed.'), true);
@ -588,7 +575,6 @@ class SmssettingsAction extends ConnectSettingsAction
* *
* @see Emailsettings::newIncoming * @see Emailsettings::newIncoming
*/ */
function newIncoming() function newIncoming()
{ {
$user = common_current_user(); $user = common_current_user();
@ -599,7 +585,7 @@ class SmssettingsAction extends ConnectSettingsAction
if (!$user->updateKeys($orig)) { if (!$user->updateKeys($orig)) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
$this->serverError(_("Couldn't update user record.")); $this->serverError(_("Could not update user record."));
} }
$this->showForm(_('New incoming email address added.'), true); $this->showForm(_('New incoming email address added.'), true);

View File

@ -19,6 +19,7 @@
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
// @todo FIXME: Documentation needed.
class SubeditAction extends Action class SubeditAction extends Action
{ {
var $profile = null; var $profile = null;
@ -28,6 +29,7 @@ class SubeditAction extends Action
parent::prepare($args); parent::prepare($args);
if (!common_logged_in()) { if (!common_logged_in()) {
// TRANS: Client error displayed trying a change a subscription while not logged in.
$this->clientError(_('Not logged in.')); $this->clientError(_('Not logged in.'));
return false; return false;
} }
@ -43,6 +45,7 @@ class SubeditAction extends Action
$id = $this->trimmed('profile'); $id = $this->trimmed('profile');
if (!$id) { if (!$id) {
// TRANS: Client error displayed trying a change a subscription without providing a profile.
$this->clientError(_('No profile specified.')); $this->clientError(_('No profile specified.'));
return false; return false;
} }
@ -50,6 +53,7 @@ class SubeditAction extends Action
$this->profile = Profile::staticGet('id', $id); $this->profile = Profile::staticGet('id', $id);
if (!$this->profile) { if (!$this->profile) {
// TRANS: Client error displayed trying a change a subscription for a non-existant profile ID.
$this->clientError(_('No profile with that ID.')); $this->clientError(_('No profile with that ID.'));
return false; return false;
} }
@ -67,6 +71,7 @@ class SubeditAction extends Action
'subscribed' => $this->profile->id)); 'subscribed' => $this->profile->id));
if (!$sub) { if (!$sub) {
// TRANS: Client error displayed trying a change a subscription for a non-subscribed profile.
$this->clientError(_('You are not subscribed to that profile.')); $this->clientError(_('You are not subscribed to that profile.'));
return false; return false;
} }
@ -80,6 +85,7 @@ class SubeditAction extends Action
if (!$result) { if (!$result) {
common_log_db_error($sub, 'UPDATE', __FILE__); common_log_db_error($sub, 'UPDATE', __FILE__);
// TRANS: Server error displayed when updating a subscription fails with a database error.
$this->serverError(_('Could not save subscription.')); $this->serverError(_('Could not save subscription.'));
return false; return false;
} }

View File

@ -100,8 +100,6 @@ class SubscribersAction extends GalleryAction
} }
} }
$subscribers->free();
$this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE, $this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE,
$this->page, 'subscribers', $this->page, 'subscribers',
array('nickname' => $this->user->nickname)); array('nickname' => $this->user->nickname));

View File

@ -106,8 +106,6 @@ class SubscriptionsAction extends GalleryAction
} }
} }
$subscriptions->free();
$this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE, $this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE,
$this->page, 'subscriptions', $this->page, 'subscriptions',
array('nickname' => $this->user->nickname)); array('nickname' => $this->user->nickname));
@ -163,6 +161,21 @@ class SubscriptionsAction extends GalleryAction
$cloud2 = new SubscriptionsPeopleSelfTagCloudSection($this); $cloud2 = new SubscriptionsPeopleSelfTagCloudSection($this);
$cloud2->show(); $cloud2->show();
} }
/**
* Link to feeds of subscriptions
*
* @return array of Feed objects
*/
function getFeeds()
{
return array(new Feed(Feed::ATOM,
common_local_url('AtomPubSubscriptionFeed',
array('subscriber' => $this->profile->id)),
// TRANS: Atom feed title. %s is a profile nickname.
sprintf(_('Subscription feed for %s (Atom)'),
$this->profile->nickname)));
}
} }
// XXX SubscriptionsList and SubscriptionList are dangerously close // XXX SubscriptionsList and SubscriptionList are dangerously close

Some files were not shown because too many files have changed in this diff Show More