Merge branch '1.0.x' into schema-x

Conflicts:
	plugins/OStatus/classes/Ostatus_profile.php
This commit is contained in:
Brion Vibber 2010-10-06 17:16:13 -07:00
commit 99194e03fa
1413 changed files with 159244 additions and 49968 deletions

1
.gitignore vendored
View File

@ -25,3 +25,4 @@ good-config.php
lac08.log
php.log
.DS_Store
nbproject

View File

@ -258,10 +258,28 @@ EndShowExportData: just after showing the <div> with export data (feeds)
- $action: action object being shown
StartShowNoticeItem: just before showing the notice item
- $action: action object being shown
- $item: The NoticeListItem object being shown
EndShowNoticeItem: just after showing the notice item
- $action: action object being shown
- $item: the NoticeListItem object being shown
StartShowNoticeInfo: just before showing notice info
- $item: The NoticeListItem object being shown
EndShowNoticeInfo: just after showing notice info
- $item: The NoticeListItem object being shown
StartShowNoticeOptions: just before showing notice options like fave, repeat, etc.
- $item: the NoticeListItem object being shown
EndShowNoticeOptions: just after showing notice options like fave, repeat, etc.
- $item: the NoticeListItem object being shown
StartShowFaveForm: just before showing the fave form
- $item: the NoticeListItem object being shown
EndShowFaveForm: just after showing the fave form
- $item: the NoticeListItem object being shown
StartShowPageNotice: just before showing the page notice (instructions or error)
- $action: action object being shown
@ -551,6 +569,12 @@ EndPublicXRDS: End XRDS output (right before the closing XRDS tag)
- $action: the current action
- &$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
- $nickname: The nickname to check
- $password: The password to check
@ -774,6 +798,22 @@ EndDisfavorNotice: After saving a notice as a favorite
- $profile: profile of the person faving (can be remote!)
- $notice: notice being faved
StartFavorNoticeForm: starting the data in the form for favoring a notice
- $FavorForm: the favor form being shown
- $notice: notice being favored
EndFavorNoticeForm: Ending the data in the form for favoring a notice
- $FavorForm: the favor form being shown
- $notice: notice being favored
StartDisFavorNoticeForm: starting the data in the form for disfavoring a notice
- $DisfavorForm: the disfavor form being shown
- $notice: notice being difavored
EndDisFavorNoticeForm: Ending the data in the form for disfavoring a notice
- $DisfavorForm: the disfavor form being shown
- $notice: notice being disfavored
StartFindMentions: start finding mentions in a block of text
- $sender: sender profile
- $text: plain text version of the notice
@ -1063,3 +1103,60 @@ StartActivityEnd: before the closing </entry> in a notice activity entry (last c
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
- $action: action being executed (instance of NewNoticeAction)
- &$authorId: integer ID of the author
- &$text: text of the notice
- &$options: additional options (location, replies, etc.)
EndNoticeSaveWeb: after saving a notice through the Web interface
- $action: action being executed (instance of NewNoticeAction)
- $notice: notice that was saved
StartRssEntryArray: at the start of copying a notice to an array
- $notice: the notice being copied
- &$entry: the entry (empty at beginning)
EndRssEntryArray: at the end of copying a notice to an array
- $notice: the notice being copied
- &$entry: the entry, with all the fields filled up
NoticeDeleteRelated: at the beginning of deleting related fields to a notice
- $notice: notice being deleted
StartShowHeadTitle: when beginning to show the <title> element
- $action: action being shown
EndShowHeadTitle: when done showing the <title>
- $action: action being shown
StartShowPageTitle: when beginning to show the page title <h1>
- $action: action being shown
EndShowPageTitle: when done showing the page title <h1>
- $action: action being shown
StartDeleteOwnNotice: when a user starts to delete their own notice
- $user: the user doing the delete
- $notice: the notice being deleted
EndDeleteOwnNotice: when a user has deleted their own notice
- $user: the user doing the delete
- $notice: the notice being deleted
StartShowFeedLinkList: before showing the feed list in the sidebar
- $action: action being executed
- $feeds: list of feeds to show
EndShowFeedLinkList: after showing the feed list in the sidebar
- $action: action being executed
- $feeds: list of feeds shown
StartShowFeedLink: before showing an individual feed item
- $action: action being executed
- $feed: feed to show
EndShowFeedLink: after showing an individual feed
- $action: action being executed
- $feed: feed to show

73
README
View File

@ -2,8 +2,8 @@
README
------
StatusNet 0.9.4beta2
11 August 2010
StatusNet 0.9.5 "What's The Frequency, Kenneth?"
10 September 2010
This is the README file for StatusNet, the Open Source microblogging
platform. It includes installation instructions, descriptions of
@ -38,11 +38,16 @@ more, please see the Open Software Service Definition 1.1:
http://www.opendefinition.org/ossd
StatusNet, Inc. <http://status.net/> also offers this software as a
Web service, requiring no installation on your part. The software run
Web service, requiring no installation on your part. See
<http://status.net/signup> for details. The software run
on status.net is identical to the software available for download, so
you can move back and forth between a hosted version or a version
installed on your own servers.
A commercial software subscription is available from StatusNet Inc. It
includes 24-hour technical support and developer support. More
information at http://status.net/contact or email sales@status.net.
License
=======
@ -68,6 +73,20 @@ License along with this program, in the file "COPYING". If not, see
of using the software, and if you do not wish to share your
modifications, *YOU MAY NOT INSTALL STATUSNET*.
Documentation in the /doc-src/ directory is available under the
Creative Commons Attribution 3.0 Unported license, with attribution to
"StatusNet". See http://creativecommons.org/licenses/by/3.0/ for details.
CSS and images in the /theme/ directory are available under the
Creative Commons Attribution 3.0 Unported license, with attribution to
"StatusNet". See http://creativecommons.org/licenses/by/3.0/ for details.
Our understanding and intention is that if you add your own theme that
uses only CSS and images, those files are not subject to the copyleft
requirements of the Affero General Public License 3.0. See
http://wordpress.org/news/2009/07/themes-are-gpl-too/ . This is not
legal advice; consult your lawyer.
Additional library software has been made available in the 'extlib'
directory. All of it is Free Software and can be distributed under
liberal terms, but those terms may differ in detail from the AGPL's
@ -77,31 +96,33 @@ for additional terms.
New this version
================
This is a security, bug and feature release since version 0.9.3 released on
29 June 2010.
This is a security, bug and feature release since version 0.9.4 released on
16 August 2010.
For best compatibility with client software and site federation, and a lot of
bug fixes, it is highly recommended that all public sites upgrade to the new
version.
Changes from 0.9.4beta1:
- fix for daemon config switching on multi-site setup
Notable changes this version:
- OpenID and OAuth libraries patched for potential timing attack
- OStatus feed i/o updated for Activity Streams
- Correctness fixes on XRD, other discovery bits
- Support for contacting SNI-based SSL virtual hosts when SSL
certificate verification is enabled (requires PHP 5.3.2+ or
enabling CURL backend with $config['http']['curl'] = true)
- Experimental SubMirror plugin
- Multi-site status_network table mode has been tweaked to support
multiple tags better
- Many updates to user interface translation from TranslateWiki
- Many other bugfixes
- Change of license for default themes and documentation from
AGPLv3 to CC-By 3.0 Unported.
- An experimental TinyMCE plugin to do in-browser rich editing of
status updates. Does not support StatusNet syntax like @-replies or
#hashtags very well.
- An experimental plugin to add titles to notices.
- A plugin to support the Echo <http://aboutecho.com/> commenting
system.
- A plugin to support the Disqus <http://disqus.com/> commenting system.
- Changes to OStatus support to make StatusNet work for the Social Web
Acid Test Level 0 <http://federatedsocialweb.net/wiki/SWAT0>.
- Themes now support a theme.ini file for theme configuration, including
defining a "base" theme.
- Improved two-way Twitter integration, including support for
repeats and retweets, replies, and faves going both ways across the
bridge, as well as better parsing of Twitter statuses.
A full changelog is available at http://status.net/wiki/StatusNet_0.9.4.
A full changelog is available at http://status.net/wiki/StatusNet_0.9.5.
Prerequisites
=============
@ -214,9 +235,9 @@ especially if you've previously installed PHP/MySQL packages.
1. Unpack the tarball you downloaded on your Web server. Usually a
command like this will work:
tar zxf statusnet-0.9.4.tar.gz
tar zxf statusnet-0.9.5.tar.gz
...which will make a statusnet-0.9.2 subdirectory in your current
...which will make a statusnet-0.9.5 subdirectory in your current
directory. (If you don't have shell access on your Web server, you
may have to unpack the tarball on your local computer and FTP the
files to the server.)
@ -224,7 +245,7 @@ especially if you've previously installed PHP/MySQL packages.
2. Move the tarball to a directory of your choosing in your Web root
directory. Usually something like this will work:
mv statusnet-0.9.4 /var/www/statusnet
mv statusnet-0.9.5 /var/www/statusnet
This will make your StatusNet instance available in the statusnet path of
your server, like "http://example.net/statusnet". "microblog" or
@ -639,7 +660,7 @@ with this situation.
If you've been using StatusNet 0.7, 0.6, 0.5 or lower, or if you've
been tracking the "git" version of the software, you will probably
want to upgrade and keep your existing data. There is no automated
upgrade procedure in StatusNet 0.9.2. Try these step-by-step
upgrade procedure in StatusNet 0.9.5. Try these step-by-step
instructions; read to the end first before trying them.
0. Download StatusNet and set up all the prerequisites as if you were
@ -660,7 +681,7 @@ instructions; read to the end first before trying them.
5. Once all writing processes to your site are turned off, make a
final backup of the Web directory and database.
6. Move your StatusNet directory to a backup spot, like "statusnet.bak".
7. Unpack your StatusNet 0.9.2 tarball and move it to "statusnet" or
7. Unpack your StatusNet 0.9.5 tarball and move it to "statusnet" or
wherever your code used to be.
8. Copy the config.php file and avatar directory from your old
directory to your new directory.
@ -1537,7 +1558,7 @@ repository (see below), and you get a compilation error ("unexpected
T_STRING") in the browser, check to see that you don't have any
conflicts in your code.
If you upgraded to StatusNet 0.9.2 without reading the "Notice
If you upgraded to StatusNet 0.9.5 without reading the "Notice
inboxes" section above, and all your users' 'Personal' tabs are empty,
read the "Notice inboxes" section above.

View File

@ -83,6 +83,7 @@ class ApiAccountUpdateDeliveryDeviceAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error message. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400, $this->format
);

View File

@ -86,6 +86,7 @@ class ApiAccountUpdateProfileAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400, $this->format
);

View File

@ -83,6 +83,7 @@ class ApiAccountUpdateProfileBackgroundImageAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400, $this->format
);

View File

@ -107,6 +107,7 @@ class ApiAccountUpdateProfileColorsAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400, $this->format
);

View File

@ -81,6 +81,7 @@ class ApiAccountUpdateProfileImageAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400, $this->format
);

View File

@ -86,6 +86,7 @@ class ApiBlockCreateAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400,
$this->format

View File

@ -85,6 +85,7 @@ class ApiBlockDestroyAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400,
$this->format

View File

@ -357,6 +357,7 @@ class ApiDirectMessageAction extends ApiAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
strtotime($this->messages[0]->created),
strtotime($this->messages[$last]->created)

View File

@ -106,6 +106,7 @@ class ApiDirectMessageNewAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400,
$this->format

View File

@ -88,6 +88,7 @@ class ApiFavoriteCreateAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400,
$this->format

View File

@ -89,6 +89,7 @@ class ApiFavoriteDestroyAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400,
$this->format

View File

@ -88,6 +88,7 @@ class ApiFriendshipsCreateAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400,
$this->format

View File

@ -88,6 +88,7 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400,
$this->format

View File

@ -102,6 +102,7 @@ class ApiGroupCreateAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400,
$this->format

View File

@ -89,6 +89,7 @@ class ApiGroupJoinAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400,
$this->format

View File

@ -89,6 +89,7 @@ class ApiGroupLeaveAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400,
$this->format

View File

@ -213,6 +213,7 @@ class ApiGroupListAction extends ApiBareAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->user->id,
strtotime($this->groups[0]->created),

View File

@ -204,6 +204,7 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
strtotime($this->groups[0]->created),
strtotime($this->groups[$last]->created))

View File

@ -183,6 +183,7 @@ class ApiGroupMembershipAction extends ApiPrivateAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->group->id,
strtotime($this->profiles[0]->created),

View File

@ -149,6 +149,7 @@ class ApiGroupShowAction extends ApiPrivateAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->group->id,
strtotime($this->group->modified))

View File

@ -64,6 +64,7 @@ class ApiMediaUploadAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400, $this->format
);

View File

@ -270,7 +270,7 @@ class ApiOauthAuthorizeAction extends ApiOauthAction
$this->elementStart('form', array('method' => 'post',
'id' => 'form_apioauthauthorize',
'class' => 'form_settings',
'action' => common_local_url('apioauthauthorize')));
'action' => common_local_url('ApiOauthAuthorize')));
$this->elementStart('fieldset');
$this->element('legend', array('id' => 'apioauthauthorize_allowdeny'),
_('Allow or deny access'));

View File

@ -125,10 +125,10 @@ class ApiStatusesDestroyAction extends ApiAuthAction
}
if ($this->user->id == $this->notice->profile_id) {
$replies = new Reply;
$replies->get('notice_id', $this->notice_id);
$replies->delete();
if (Event::handle('StartDeleteOwnNotice', array($this->user, $this->notice))) {
$this->notice->delete();
Event::handle('EndDeleteOwnNotice', array($this->user, $this->notice));
}
$this->showNotice();
} else {
$this->clientError(

View File

@ -62,6 +62,7 @@ class ApiStatusesRetweetAction extends ApiAuthAction
parent::prepare($args);
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
// TRANS: Client error. POST is a HTTP command. It should not be translated.
$this->clientError(_('This method requires a POST.'),
400, $this->format);
return false;

View File

@ -194,6 +194,7 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->notice->id,
strtotime($this->notice->created))

View File

@ -195,6 +195,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400,
$this->format

View File

@ -181,6 +181,7 @@ class ApiSubscriptionsAction extends ApiBareAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->user->id,
isset($this->ids_only) ? 'IDs' : 'Profiles',

View File

@ -259,6 +259,7 @@ class ApiTimelineFavoritesAction extends ApiBareAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->user->id,
strtotime($this->notices[0]->created),

View File

@ -346,6 +346,7 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->user->id,
strtotime($this->notices[0]->created),

View File

@ -229,6 +229,7 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->group->id,
strtotime($this->notices[0]->created),

View File

@ -254,6 +254,7 @@ class ApiTimelineHomeAction extends ApiBareAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->user->id,
strtotime($this->notices[0]->created),

View File

@ -244,6 +244,7 @@ class ApiTimelineMentionsAction extends ApiBareAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->user->id,
strtotime($this->notices[0]->created),

View File

@ -311,6 +311,7 @@ class ApiTimelinePublicAction extends ApiPrivateAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
strtotime($this->notices[0]->created),
strtotime($this->notices[$last]->created))

View File

@ -232,6 +232,7 @@ class ApiTimelineTagAction extends ApiPrivateAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->tag,
strtotime($this->notices[0]->created),

View File

@ -234,6 +234,7 @@ class ApiTimelineUserAction extends ApiBareAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->user->id,
strtotime($this->notices[0]->created),

View File

@ -172,7 +172,10 @@ class DeletenoticeAction extends Action
}
if ($this->arg('yes')) {
if (Event::handle('StartDeleteOwnNotice', array($this->user, $this->notice))) {
$this->notice->delete();
Event::handle('EndDeleteOwnNotice', array($this->user, $this->notice));
}
}
$url = common_get_returnto();

View File

@ -71,7 +71,7 @@ class DesignadminpanelAction extends AdminPanelAction
function getInstructions()
{
return _('Design settings for this StatusNet site.');
return _('Design settings for this StatusNet site');
}
/**
@ -154,9 +154,22 @@ class DesignadminpanelAction extends AdminPanelAction
$config->query('BEGIN');
// Only update colors if the theme has not changed.
if ($themeChanged) {
// If the theme has changed, reset custom colors and let them pick
// up the new theme's defaults.
$colors = array('background', 'content', 'sidebar', 'text', 'link');
foreach ($colors as $colorKey) {
// Clear from global config so we see defaults on this page...
$GLOBALS['config']['design'][$colorKey . 'color'] = false;
if (!$themeChanged) {
// And remove old settings from DB...
$this->deleteSetting('design', $colorKey . 'color');
}
} else {
// Only save colors from the form if the theme has not changed.
//
// @fixme a future more ajaxy form should allow theme switch
// and color customization in one step.
$bgcolor = new WebColor($this->trimmed('design_background'));
$ccolor = new WebColor($this->trimmed('design_content'));

View File

@ -188,7 +188,7 @@ class EditApplicationAction extends OwnerDesignAction
} elseif (Oauth_application::descriptionTooLong($description)) {
$this->showForm(sprintf(
_('Description is too long (max %d chars).'),
Oauth_application::maxDescription()));
Oauth_application::maxDesc()));
return;
} elseif (mb_strlen($source_url) > 255) {
$this->showForm(_('Source URL is too long.'));
@ -253,7 +253,10 @@ class EditApplicationAction extends OwnerDesignAction
$result = $this->app->update($orig);
if (!$result) {
// Note: 0 means no rows changed, which can happen if the only
// thing we changed was the icon, since it's not altered until
// the next step.
if ($result === false) {
common_log_db_error($this->app, 'UPDATE', __FILE__);
$this->serverError(_('Could not update application.'));
}

View File

@ -131,7 +131,11 @@ class EmailsettingsAction extends AccountSettingsAction
// TRANS: Field label for e-mail address input in e-mail settings form.
$this->input('email', _('Email address'),
($this->arg('email')) ? $this->arg('email') : null,
// TRANS: Instructions for e-mail address input form.
// TRANS: Instructions for e-mail address input form. Do not translate
// TRANS: "example.org". It is one of the domain names reserved for
// TRANS: use in examples by http://www.rfc-editor.org/rfc/rfc2606.txt.
// TRANS: Any other domain may be owned by a legitimate person or
// TRANS: organization.
_('Email address, like "UserName@example.org"'));
$this->elementEnd('li');
$this->elementEnd('ul');

View File

@ -129,9 +129,9 @@ class GetfileAction extends Action
return null;
}
$cache = common_memcache();
$cache = Cache::instance();
if($cache) {
$key = common_cache_key('attachments:etag:' . $this->path);
$key = Cache::key('attachments:etag:' . $this->path);
$etag = $cache->get($key);
if($etag === false) {
$etag = crc32(file_get_contents($this->path));

View File

@ -97,9 +97,13 @@ class GroupmembersAction extends GroupDesignAction
function title()
{
if ($this->page == 1) {
// TRANS: Title of the page showing group members.
// TRANS: %s is the name of the group.
return sprintf(_('%s group members'),
$this->group->nickname);
} else {
// TRANS: Title of the page showing group members.
// TRANS: %1$s is the name of the group, %2$d is the page number of the members list.
return sprintf(_('%1$s group members, page %2$d'),
$this->group->nickname,
$this->page);
@ -389,7 +393,14 @@ class GroupBlockForm extends Form
function formActions()
{
$this->out->submit('submit', _('Block'), 'submit', null, _('Block this user'));
$this->out->submit(
'submit',
// TRANS: Button text for the form that will block a user from a group.
_m('BUTTON','Block'),
'submit',
null,
// TRANS: Submit button title.
_m('TOOLTIP', 'Block this user'));
}
}
@ -516,6 +527,13 @@ class MakeAdminForm extends Form
function formActions()
{
$this->out->submit('submit', _('Make Admin'), 'submit', null, _('Make this user an admin'));
$this->out->submit(
'submit',
// TRANS: Button text for the form that will make a user administrator.
_m('BUTTON','Make Admin'),
'submit',
null,
// TRANS: Submit button title.
_m('TOOLTIP','Make this user an admin'));
}
}

View File

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

View File

@ -133,7 +133,7 @@ class ImsettingsAction extends ConnectSettingsAction
'message with further instructions. '.
'(Did you add %s to your buddy list?)'),
$transport_info['display'],
$transport_info['daemon_screenname']));
$transport_info['daemonScreenname']));
$this->hidden('screenname', $confirm->address);
// TRANS: Button label to cancel an IM address confirmation procedure.
$this->submit('cancel', _m('BUTTON','Cancel'));

View File

@ -0,0 +1,322 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* License administration panel
*
* 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 Settings
* @package StatusNet
* @author Zach Copley <zach@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);
}
/**
* License settings
*
* @category Admin
* @package StatusNet
* @author Zach Copley <zach@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 LicenseadminpanelAction extends AdminPanelAction
{
/**
* Returns the page title
*
* @return string page title
*/
function title()
{
// TRANS: User admin panel title
return _m('TITLE', 'License');
}
/**
* Instructions for using this form.
*
* @return string instructions
*/
function getInstructions()
{
return _('License for this StatusNet site');
}
/**
* Show the site admin panel form
*
* @return void
*/
function showForm()
{
$form = new LicenseAdminPanelForm($this);
$form->show();
return;
}
/**
* Save settings from the form
*
* @return void
*/
function saveSettings()
{
static $settings = array(
'license' => array('type', 'owner', 'url', 'title', 'image')
);
$values = array();
foreach ($settings as $section => $parts) {
foreach ($parts as $setting) {
$values[$section][$setting] = $this->trimmed($setting);
}
}
// This throws an exception on validation errors
$this->validate($values);
// assert(all values are valid);
$config = new Config();
$config->query('BEGIN');
foreach ($settings as $section => $parts) {
foreach ($parts as $setting) {
Config::save($section, $setting, $values[$section][$setting]);
}
}
$config->query('COMMIT');
return;
}
/**
* Validate License admin form values
*
* @param array &$values from the form
*
* @return nothing
*/
function validate(&$values)
{
// Validate license type (shouldn't have to do it, but just in case)
$types = array('private', 'allrightsreserved', 'cc');
if (!in_array($values['license']['type'], $types)) {
$this->clientError(_("Invalid license selection."));
}
// Make sure the user has set an owner if the site has a private
// license
if ($values['license']['type'] == 'allrightsreserved'
&& empty($values['license']['owner'])
) {
$this->clientError(
_("You must specify the owner of the content when using the All Rights Reserved license.")
);
}
// Make sure the license title is not too long
if (mb_strlen($values['license']['type']) > 255) {
$this->clientError(
_("Invalid license title. Max length is 255 characters.")
);
}
// make sure the license URL and license image URL are valid URLs
$options = array('allowed_schemes' => array('http', 'https'));
// URLs should be set for cc license
if ($values['license']['type'] == 'cc') {
if (!Validate::uri($values['license']['url'], $options)) {
$this->clientError(_("Invalid license URL."));
}
if (!Validate::uri($values['license']['image'], $options)) {
$this->clientError(_("Invalid license image URL."));
}
}
// can be either blank or a valid URL for private & allrightsreserved
if (!empty($values['license']['url'])) {
if (!Validate::uri($values['license']['url'], $options)) {
$this->clientError(_("License URL must be blank or a valid URL."));
}
}
// can be either blank or a valid URL for private & allrightsreserved
if (!empty($values['license']['image'])) {
if (!Validate::uri($values['license']['image'], $options)) {
$this->clientError(_("License image must be blank or valid URL."));
}
}
}
}
class LicenseAdminPanelForm extends AdminForm
{
/**
* ID of the form
*
* @return int ID of the form
*/
function id()
{
return 'licenseadminpanel';
}
/**
* class of the form
*
* @return string class of the form
*/
function formClass()
{
return 'form_settings';
}
/**
* Action of the form
*
* @return string URL of the action
*/
function action()
{
return common_local_url('licenseadminpanel');
}
/**
* Data elements of the form
*
* @return void
*/
function formData()
{
$this->out->elementStart(
'fieldset', array('id' => 'settings_license-selection')
);
$this->out->element('legend', null, _('License selection'));
$this->out->elementStart('ul', 'form_data');
$this->li();
$types = array(
'private' => _('Private'),
'allrightsreserved' => _('All Rights Reserved'),
'cc' => _('Creative Commons')
);
$this->out->dropdown(
'type',
_('Type'),
$types,
_('Select license'),
false,
$this->value('type', 'license')
);
$this->unli();
$this->out->elementEnd('ul');
$this->out->elementEnd('fieldset');
$this->out->elementStart(
'fieldset',
array('id' => 'settings_license-details')
);
$this->out->element('legend', null, _('License details'));
$this->out->elementStart('ul', 'form_data');
$this->li();
$this->input(
'owner',
_('Owner'),
_('Name of the owner of the site\'s content (if applicable).'),
'license'
);
$this->unli();
$this->li();
$this->input(
'title',
_('License Title'),
_('The title of the license.'),
'license'
);
$this->unli();
$this->li();
$this->input(
'url',
_('License URL'),
_('URL for more information about the license.'),
'license'
);
$this->unli();
$this->li();
$this->input(
'image', _('License Image URL'),
_('URL for an image to display with the license.'),
'license'
);
$this->unli();
$this->out->elementEnd('ul');
$this->out->elementEnd('fieldset');
}
/**
* Action elements
*
* @return void
*/
function formActions()
{
$this->out->submit(
'submit', _('Save'), 'submit', null, _('Save license settings')
);
}
}

View File

@ -118,27 +118,10 @@ class LoginAction extends Action
* @return void
*/
function checkLogin($user_id=null, $token=null)
function checkLogin($user_id=null)
{
// XXX: login throttle
// CSRF protection - token set in NoticeForm
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
$st = common_session_token();
if (empty($token)) {
common_log(LOG_WARNING, 'No token provided by client.');
} else if (empty($st)) {
common_log(LOG_WARNING, 'No session token stored.');
} else {
common_log(LOG_WARNING, 'Token = ' . $token . ' and session token = ' . $st);
}
$this->clientError(_('There was a problem with your session token. '.
'Try again, please.'));
return;
}
$nickname = $this->trimmed('nickname');
$password = $this->arg('password');
@ -261,7 +244,6 @@ class LoginAction extends Action
$this->elementEnd('li');
$this->elementEnd('ul');
$this->submit('submit', _('Login'));
$this->hidden('token', common_session_token());
$this->elementEnd('fieldset');
$this->elementEnd('form');
$this->elementStart('p');

View File

@ -170,7 +170,7 @@ class NewApplicationAction extends OwnerDesignAction
} elseif (Oauth_application::descriptionTooLong($description)) {
$this->showForm(sprintf(
_('Description is too long (max %d chars).'),
Oauth_application::maxDescription()));
Oauth_application::maxDesc()));
return;
} elseif (empty($source_url)) {
$this->showForm(_('Source URL is required.'));

View File

@ -161,7 +161,7 @@ class NewnoticeAction extends Action
$replyto = intval($this->trimmed('inreplyto'));
if ($replyto) {
$options['replyto'] = $replyto;
$options['reply_to'] = $replyto;
}
$upload = null;
@ -204,11 +204,19 @@ class NewnoticeAction extends Action
$options = array_merge($options, $locOptions);
}
$author_id = $user->id;
$text = $content_shortened;
if (Event::handle('StartNoticeSaveWeb', array($this, &$author_id, &$text, &$options))) {
$notice = Notice::saveNew($user->id, $content_shortened, 'web', $options);
if (isset($upload)) {
$upload->attachToNotice($notice);
}
Event::handle('EndNoticeSaveWeb', array($this, $notice));
}
Event::handle('EndSaveNewNoticeWeb', array($this, $user, &$content_shortened, &$options));
if ($this->boolean('ajax')) {

View File

@ -80,7 +80,7 @@ class OauthconnectionssettingsAction extends ConnectSettingsAction
function getInstructions()
{
return _('You have allowed the following applications to access you account.');
return _('You have allowed the following applications to access your account.');
}
/**

View File

@ -67,7 +67,7 @@ class PathsadminpanelAction extends AdminPanelAction
function getInstructions()
{
return _('Path and server settings for this StatusNet site.');
return _('Path and server settings for this StatusNet site');
}
/**

View File

@ -62,7 +62,7 @@ class SessionsadminpanelAction extends AdminPanelAction
function getInstructions()
{
return _('Session settings for this StatusNet site.');
return _('Session settings for this StatusNet site');
}
/**

View File

@ -271,17 +271,17 @@ class ShowApplicationAction extends OwnerDesignAction
$this->elementStart('dl', 'entity_request_token_url');
$this->element('dt', null, _('Request token URL'));
$this->element('dd', null, common_local_url('apioauthrequesttoken'));
$this->element('dd', null, common_local_url('ApiOauthRequestToken'));
$this->elementEnd('dl');
$this->elementStart('dl', 'entity_access_token_url');
$this->element('dt', null, _('Access token URL'));
$this->element('dd', null, common_local_url('apioauthaccesstoken'));
$this->element('dd', null, common_local_url('ApiOauthAccessToken'));
$this->elementEnd('dl');
$this->elementStart('dl', 'entity_authorize_url');
$this->element('dt', null, _('Authorize URL'));
$this->element('dd', null, common_local_url('apioauthauthorize'));
$this->element('dd', null, common_local_url('ApiOauthAuthorize'));
$this->elementEnd('dl');
$this->element('p', 'note',

View File

@ -151,6 +151,7 @@ class ShownoticeAction extends OwnerDesignAction
strtotime($this->avatar->modified) : 0;
return 'W/"' . implode(':', array($this->arg('action'),
common_user_cache_hash(),
common_language(),
$this->notice->id,
strtotime($this->notice->created),
@ -291,6 +292,16 @@ class ShownoticeAction extends OwnerDesignAction
array(),
array('format'=>'xml','url'=>$this->notice->uri)),
'title'=>'oEmbed'),null);
// Extras to aid in sharing notices to Facebook
$avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE);
$avatarUrl = ($avatar) ?
$avatar->displayUrl() :
Avatar::defaultImage(AVATAR_PROFILE_SIZE);
$this->element('meta', array('property' => 'og:image',
'content' => $avatarUrl));
$this->element('meta', array('property' => 'og:description',
'content' => $this->notice->content));
}
}
@ -307,10 +318,14 @@ class SingleNoticeItem extends NoticeListItem
function show()
{
$this->showStart();
if (Event::handle('StartShowNoticeItem', array($this))) {
$this->showNotice();
$this->showNoticeAttachments();
$this->showNoticeInfo();
$this->showNoticeOptions();
Event::handle('EndShowNoticeItem', array($this));
}
$this->showEnd();
}

View File

@ -216,7 +216,10 @@ class ShowstreamAction extends ProfileAction
? $this->user->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1)
: $this->user->getTaggedNotices($this->tag, ($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1, 0, 0, null);
$pnl = null;
if (Event::handle('ShowStreamNoticeList', array($notice, $this, &$pnl))) {
$pnl = new ProfileNoticeList($notice, $this);
}
$cnt = $pnl->show();
if (0 == $cnt) {
$this->showEmptyListMessage();

View File

@ -12,6 +12,7 @@
* (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.
@ -24,7 +25,7 @@
* @author Evan Prodromou <evan@status.net>
* @author Zach Copley <zach@status.net>
* @author Sarven Capadisli <csarven@status.net>
* @copyright 2008-2009 StatusNet, Inc.
* @copyright 2008-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/
*/
@ -67,7 +68,7 @@ class UseradminpanelAction extends AdminPanelAction
function getInstructions()
{
return _('User settings for this StatusNet site.');
return _('User settings for this StatusNet site');
}
/**
@ -291,6 +292,6 @@ class UserAdminPanelForm extends AdminForm
function formActions()
{
$this->out->submit('submit', _('Save'), 'submit', null, _('Save site settings'));
$this->out->submit('submit', _('Save'), 'submit', null, _('Save user settings'));
}
}

View File

@ -42,8 +42,9 @@ class Avatar extends Memcached_DataObject
return Memcached_DataObject::pkeyGet('Avatar', $kv);
}
// where should the avatar go for this user?
/**
* Where should the avatar go for this user?
*/
static function filename($id, $extension, $size=null, $extra=null)
{
if ($size) {

View File

@ -58,7 +58,7 @@ class Config extends Memcached_DataObject
$c = self::memcache();
if (!empty($c)) {
$settings = $c->get(common_cache_key(self::settingsKey));
$settings = $c->get(Cache::key(self::settingsKey));
if ($settings !== false) {
return $settings;
}
@ -77,7 +77,7 @@ class Config extends Memcached_DataObject
$config->free();
if (!empty($c)) {
$c->set(common_cache_key(self::settingsKey), $settings);
$c->set(Cache::key(self::settingsKey), $settings);
}
return $settings;
@ -154,7 +154,7 @@ class Config extends Memcached_DataObject
$c = self::memcache();
if (!empty($c)) {
$c->delete(common_cache_key(self::settingsKey));
$c->delete(Cache::key(self::settingsKey));
}
}
}

View File

@ -65,5 +65,4 @@ class Consumer extends Memcached_DataObject
$nonce->consumer_key = $this->consumer_key;
$nonce->delete();
}
}

View File

@ -74,6 +74,4 @@ class Conversation extends Memcached_DataObject
return $conv;
}
}

View File

@ -129,4 +129,32 @@ class Fave extends Memcached_DataObject
return $ids;
}
function asActivity()
{
$notice = Notice::staticGet('id', $this->notice_id);
$profile = Profile::staticGet('id', $this->user_id);
$act = new Activity();
$act->verb = ActivityVerb::FAVORITE;
$act->id = TagURI::mint('favor:%d:%d:%s',
$profile->id,
$notice->id,
common_date_iso8601($this->modified));
$act->time = strtotime($this->modified);
// TRANS: Activity title when marking a notice as favorite.
$act->title = _("Favor");
// TRANS: Ntofication given when a user marks a notice as favorite.
// TRANS: %1$s is a user nickname or full name, %2$s is a notice URI.
$act->content = sprintf(_('%1$s marked notice %2$s as a favorite.'),
$profile->getBestName(),
$notice->uri);
$act->actor = ActivityObject::fromProfile($profile);
$act->objects[] = ActivityObject::fromNotice($notice);
return $act;
}
}

View File

@ -29,7 +29,6 @@ require_once INSTALLDIR.'/classes/File_to_post.php';
/**
* Table Definition for file
*/
class File extends Memcached_DataObject
{
###START_AUTOCODE

View File

@ -131,4 +131,3 @@ class File_oembed extends Memcached_DataObject
}
}
}

View File

@ -240,6 +240,14 @@ class File_redirection extends Memcached_DataObject
} else if (is_string($redir_data)) {
// The file is a known redirect target.
$file = File::staticGet('url', $redir_data);
if (empty($file)) {
// @fixme should we save a new one?
// this case was triggering sometimes for redirects
// with unresolvable targets; found while fixing
// "can't linkify" bugs with shortened links to
// SSL sites with cert issues.
return null;
}
$file_id = $file->id;
}
} else {
@ -303,4 +311,3 @@ class File_redirection extends Memcached_DataObject
$file_redir->insert();
}
}

View File

@ -57,4 +57,3 @@ class File_thumbnail extends Memcached_DataObject
$tn->insert();
}
}

View File

@ -67,4 +67,3 @@ class File_to_post extends Memcached_DataObject
return Memcached_DataObject::pkeyGet('File_to_post', $kv);
}
}

View File

@ -44,7 +44,6 @@ class Foreign_link extends Memcached_DataObject
$result = $flink->find(true);
return empty($result) ? null : $flink;
}
static function getByForeignID($foreign_id, $service)
@ -129,5 +128,4 @@ class Foreign_link extends Memcached_DataObject
return false;
}
}
}

View File

@ -83,5 +83,4 @@ class Foreign_user extends Memcached_DataObject
}
return $result;
}
}

View File

@ -111,5 +111,4 @@ class Group_block extends Memcached_DataObject
return true;
}
}

View File

@ -1,8 +1,8 @@
<?php
/**
* Table Definition for group_inbox
*/
class Group_inbox extends Memcached_DataObject
{
###START_AUTOCODE

View File

@ -65,4 +65,59 @@ class Group_member extends Memcached_DataObject
return true;
}
function getMember()
{
$member = Profile::staticGet('id', $this->profile_id);
if (empty($member)) {
// TRANS: Exception thrown providing an invalid profile ID.
// TRANS: %s is the invalid profile ID.
throw new Exception(sprintf(_("Profile ID %s is invalid."),$this->profile_id));
}
return $member;
}
function getGroup()
{
$group = User_group::staticGet('id', $this->group_id);
if (empty($group)) {
// TRANS: Exception thrown providing an invalid group ID.
// TRANS: %s is the invalid group ID.
throw new Exception(sprintf(_("Group ID %s is invalid."),$this->group_id));
}
return $group;
}
function asActivity()
{
$member = $this->getMember();
$group = $this->getGroup();
$act = new Activity();
$act->id = TagURI::mint('join:%d:%d:%s',
$member->id,
$group->id,
common_date_iso8601($this->created));
$act->actor = ActivityObject::fromProfile($member);
$act->verb = ActivityVerb::JOIN;
$act->objects[] = ActivityObject::fromGroup($group);
$act->time = strtotime($this->created);
// TRANS: Activity title.
$act->title = _("Join");
// TRANS: Success message for subscribe to group attempt through OStatus.
// TRANS: %1$s is the member name, %2$s is the subscribed group's name.
$act->content = sprintf(_('%1$s has joined group %2$s.'),
$member->getBestName(),
$group->getBestName());
return $act;
}
}

View File

@ -55,7 +55,6 @@ class Inbox extends Memcached_DataObject
/**
* Create a new inbox from existing Notice_inbox stuff
*/
static function initialize($user_id)
{
$inbox = Inbox::fromNoticeInbox($user_id);

View File

@ -124,7 +124,7 @@ class Memcached_DataObject extends Safe_DataObject
}
static function memcache() {
return common_memcache();
return Cache::instance();
}
static function cacheKey($cls, $k, $v) {
@ -134,7 +134,7 @@ class Memcached_DataObject extends Safe_DataObject
str_replace("\n", " ", $e->getTraceAsString()));
}
$vstr = self::valueString($v);
return common_cache_key(strtolower($cls).':'.$k.':'.$vstr);
return Cache::key(strtolower($cls).':'.$k.':'.$vstr);
}
static function getcached($cls, $k, $v) {
@ -302,8 +302,8 @@ class Memcached_DataObject extends Safe_DataObject
$inst->query($qry);
return $inst;
}
$key_part = common_keyize($cls).':'.md5($qry);
$ckey = common_cache_key($key_part);
$key_part = Cache::keyize($cls).':'.md5($qry);
$ckey = Cache::key($key_part);
$stored = $c->get($ckey);
if ($stored !== false) {
@ -550,7 +550,7 @@ class Memcached_DataObject extends Safe_DataObject
$keyPart = vsprintf($format, $args);
$cacheKey = common_cache_key($keyPart);
$cacheKey = Cache::key($keyPart);
return $c->delete($cacheKey);
}
@ -592,7 +592,7 @@ class Memcached_DataObject extends Safe_DataObject
return false;
}
$cacheKey = common_cache_key($keyPart);
$cacheKey = Cache::key($keyPart);
return $c->get($cacheKey);
}
@ -605,7 +605,7 @@ class Memcached_DataObject extends Safe_DataObject
return false;
}
$cacheKey = common_cache_key($keyPart);
$cacheKey = Cache::key($keyPart);
return $c->set($cacheKey, $value, $flag, $expiry);
}
@ -637,4 +637,3 @@ class Memcached_DataObject extends Safe_DataObject
return $vstr;
}
}

View File

@ -38,7 +38,6 @@ class Message extends Memcached_DataObject
}
static function saveNew($from, $to, $content, $source) {
$sender = Profile::staticGet('id', $from);
if (!$sender->hasRight(Right::NEWMESSAGE)) {

View File

@ -36,5 +36,4 @@ class Nonce extends Memcached_DataObject
{
return array('consumer_key,token' => 'token:consumer_key,token');
}
}

View File

@ -121,6 +121,8 @@ class Notice extends Memcached_DataObject
$deleted->insert();
}
if (Event::handle('NoticeDeleteRelated', array($this))) {
// Clear related records
$this->clearReplies();
@ -131,6 +133,7 @@ class Notice extends Memcached_DataObject
// NOTE: we don't clear inboxes
// NOTE: we don't clear queue items
}
$result = parent::delete();
@ -245,6 +248,8 @@ class Notice extends Memcached_DataObject
if (!empty($options)) {
$options = $options + $defaults;
extract($options);
} else {
extract($defaults);
}
if (!isset($is_local)) {
@ -578,15 +583,17 @@ class Notice extends Memcached_DataObject
if ($f2p->find()) {
while ($f2p->fetch()) {
$f = File::staticGet($f2p->file_id);
if ($f) {
$att[] = clone($f);
}
}
}
return $att;
}
function getStreamByIds($ids)
{
$cache = common_memcache();
$cache = Cache::instance();
if (!empty($cache)) {
$notices = array();
@ -738,6 +745,7 @@ class Notice extends Memcached_DataObject
1,
1
);
if ($conversation->N > 0) {
return true;
}
@ -746,15 +754,22 @@ class Notice extends Memcached_DataObject
}
/**
* @param $groups array of Group *objects*
* @param $recipients array of profile *ids*
* Pull up a full list of local recipients who will be getting
* this notice in their inbox. Results will be cached, so don't
* change the input data wily-nilly!
*
* @param array $groups optional list of Group objects;
* if left empty, will be loaded from group_inbox records
* @param array $recipient optional list of reply profile ids
* if left empty, will be loaded from reply records
* @return array associating recipient user IDs with an inbox source constant
*/
function whoGets($groups=null, $recipients=null)
{
$c = self::memcache();
if (!empty($c)) {
$ni = $c->get(common_cache_key('notice:who_gets:'.$this->id));
$ni = $c->get(Cache::key('notice:who_gets:'.$this->id));
if ($ni !== false) {
return $ni;
}
@ -780,33 +795,33 @@ class Notice extends Memcached_DataObject
$ni[$id] = NOTICE_INBOX_SOURCE_SUB;
}
$profile = $this->getProfile();
foreach ($groups as $group) {
$users = $group->getUserMembers();
foreach ($users as $id) {
if (!array_key_exists($id, $ni)) {
$user = User::staticGet('id', $id);
if (!$user->hasBlocked($profile)) {
$ni[$id] = NOTICE_INBOX_SOURCE_GROUP;
}
}
}
}
foreach ($recipients as $recipient) {
if (!array_key_exists($recipient, $ni)) {
$recipientUser = User::staticGet('id', $recipient);
if (!empty($recipientUser)) {
$ni[$recipient] = NOTICE_INBOX_SOURCE_REPLY;
}
}
// Exclude any deleted, non-local, or blocking recipients.
$profile = $this->getProfile();
foreach ($ni as $id => $source) {
$user = User::staticGet('id', $id);
if (empty($user) || $user->hasBlocked($profile)) {
unset($ni[$id]);
}
}
if (!empty($c)) {
// XXX: pack this data better
$c->set(common_cache_key('notice:who_gets:'.$this->id), $ni);
$c->set(Cache::key('notice:who_gets:'.$this->id), $ni);
}
return $ni;
@ -1014,26 +1029,32 @@ class Notice extends Memcached_DataObject
if (empty($uris)) {
return;
}
$sender = Profile::staticGet($this->profile_id);
foreach (array_unique($uris) as $uri) {
$user = User::staticGet('uri', $uri);
$profile = Profile::fromURI($uri);
if (!empty($user)) {
if ($user->hasBlocked($sender)) {
if (empty($profile)) {
common_log(LOG_WARNING, "Unable to determine profile for URI '$uri'");
continue;
}
if ($profile->hasBlocked($sender)) {
common_log(LOG_INFO, "Not saving reply to profile {$profile->id} ($uri) from sender {$sender->id} because of a block.");
continue;
}
$reply = new Reply();
$reply->notice_id = $this->id;
$reply->profile_id = $user->id;
common_log(LOG_INFO, __METHOD__ . ": saving reply: notice $this->id to profile $user->id");
$reply->profile_id = $profile->id;
common_log(LOG_INFO, __METHOD__ . ": saving reply: notice $this->id to profile $profile->id");
$id = $reply->insert();
}
}
return;
}
@ -1096,7 +1117,7 @@ class Notice extends Memcached_DataObject
common_log_db_error($reply, 'INSERT', __FILE__);
// TRANS: Server exception thrown when a reply cannot be saved.
// TRANS: %1$d is a notice ID, %2$d is the ID of the mentioned user.
throw new ServerException(sprintf(_("Could not save reply for %1$d, %2$d."), $this->id, $mentioned->id));
throw new ServerException(sprintf(_('Could not save reply for %1$d, %2$d.'), $this->id, $mentioned->id));
} else {
$replied[$mentioned->id] = 1;
self::blow('reply:stream:%d', $mentioned->id);
@ -1199,6 +1220,64 @@ class Notice extends Memcached_DataObject
return $groups;
}
function asActivity()
{
$profile = $this->getProfile();
$act = new Activity();
$act->actor = ActivityObject::fromProfile($profile);
$act->verb = ActivityVerb::POST;
$act->objects[] = ActivityObject::fromNotice($this);
$act->time = strtotime($this->created);
$act->link = $this->bestUrl();
$act->content = common_xml_safe_str($this->rendered);
$act->id = $this->uri;
$act->title = common_xml_safe_str($this->content);
$ctx = new ActivityContext();
if (!empty($this->reply_to)) {
$reply = Notice::staticGet('id', $this->reply_to);
if (!empty($reply)) {
$ctx->replyToID = $reply->uri;
$ctx->replyToUrl = $reply->bestUrl();
}
}
$ctx->location = $this->getLocation();
$conv = null;
if (!empty($this->conversation)) {
$conv = Conversation::staticGet('id', $this->conversation);
if (!empty($conv)) {
$ctx->conversation = $conv->uri;
}
}
$reply_ids = $this->getReplies();
foreach ($reply_ids as $id) {
$profile = Profile::staticGet('id', $id);
if (!empty($profile)) {
$ctx->attention[] = $profile->getUri();
}
}
$groups = $this->getGroups();
foreach ($groups as $group) {
$ctx->attention[] = $group->uri;
}
$act->context = $ctx;
return $act;
}
// This has gotten way too long. Needs to be sliced up into functional bits
// or ideally exported to a utility class.
@ -1227,13 +1306,10 @@ class Notice extends Memcached_DataObject
}
if (Event::handle('StartActivitySource', array(&$this, &$xs))) {
if ($source) {
$atom_feed = $profile->getAtomFeed();
if (!empty($atom_feed)) {
$xs->elementStart('source');
// XXX: we should store the actual feed ID
@ -1574,7 +1650,7 @@ class Notice extends Memcached_DataObject
function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $max_id=0)
{
$cache = common_memcache();
$cache = Cache::instance();
if (empty($cache) ||
$since_id != 0 || $max_id != 0 ||
@ -1584,7 +1660,7 @@ class Notice extends Memcached_DataObject
$max_id)));
}
$idkey = common_cache_key($cachekey);
$idkey = Cache::key($cachekey);
$idstr = $cache->get($idkey);
@ -1766,17 +1842,17 @@ class Notice extends Memcached_DataObject
function repeatStream($limit=100)
{
$cache = common_memcache();
$cache = Cache::instance();
if (empty($cache)) {
$ids = $this->_repeatStreamDirect($limit);
} else {
$idstr = $cache->get(common_cache_key('notice:repeats:'.$this->id));
$idstr = $cache->get(Cache::key('notice:repeats:'.$this->id));
if ($idstr !== false) {
$ids = explode(',', $idstr);
} else {
$ids = $this->_repeatStreamDirect(100);
$cache->set(common_cache_key('notice:repeats:'.$this->id), implode(',', $ids));
$cache->set(Cache::key('notice:repeats:'.$this->id), implode(',', $ids));
}
if ($limit < 100) {
// We do a max of 100, so slice down to limit
@ -1821,7 +1897,6 @@ class Notice extends Memcached_DataObject
$options = array();
if (!empty($location_id) && !empty($location_ns)) {
$options['location_id'] = $location_id;
$options['location_ns'] = $location_ns;
@ -1833,7 +1908,6 @@ class Notice extends Memcached_DataObject
}
} else if (!empty($lat) && !empty($lon)) {
$options['lat'] = $lat;
$options['lon'] = $lon;
@ -1844,7 +1918,6 @@ class Notice extends Memcached_DataObject
$options['location_ns'] = $location->location_ns;
}
} else if (!empty($profile)) {
if (isset($profile->lat) && isset($profile->lon)) {
$options['lat'] = $profile->lat;
$options['lon'] = $profile->lon;
@ -1930,10 +2003,10 @@ class Notice extends Memcached_DataObject
if ($tag->find()) {
while ($tag->fetch()) {
self::blow('profile:notice_ids_tagged:%d:%s', $this->profile_id, common_keyize($tag->tag));
self::blow('profile:notice_ids_tagged:%d:%s;last', $this->profile_id, common_keyize($tag->tag));
self::blow('notice_tag:notice_ids:%s', common_keyize($tag->tag));
self::blow('notice_tag:notice_ids:%s;last', common_keyize($tag->tag));
self::blow('profile:notice_ids_tagged:%d:%s', $this->profile_id, Cache::keyize($tag->tag));
self::blow('profile:notice_ids_tagged:%d:%s;last', $this->profile_id, Cache::keyize($tag->tag));
self::blow('notice_tag:notice_ids:%s', Cache::keyize($tag->tag));
self::blow('notice_tag:notice_ids:%s;last', Cache::keyize($tag->tag));
$tag->delete();
}
}
@ -1961,6 +2034,7 @@ class Notice extends Memcached_DataObject
{
// We always insert for the author so they don't
// have to wait
Event::handle('StartNoticeDistribute', array($this));
$user = User::staticGet('id', $this->profile_id);
if (!empty($user)) {

View File

@ -40,7 +40,7 @@ class Notice_tag extends Memcached_DataObject
$ids = Notice::stream(array('Notice_tag', '_streamDirect'),
array($tag),
'notice_tag:notice_ids:' . common_keyize($tag),
'notice_tag:notice_ids:' . Cache::keyize($tag),
$offset, $limit);
return Notice::getStreamByIds($ids);
@ -82,9 +82,9 @@ class Notice_tag extends Memcached_DataObject
function blowCache($blowLast=false)
{
self::blow('notice_tag:notice_ids:%s', common_keyize($this->tag));
self::blow('notice_tag:notice_ids:%s', Cache::keyize($this->tag));
if ($blowLast) {
self::blow('notice_tag:notice_ids:%s;last', common_keyize($this->tag));
self::blow('notice_tag:notice_ids:%s;last', Cache::keyize($this->tag));
}
}

View File

@ -110,7 +110,6 @@ class Oauth_application extends Memcached_DataObject
*
* @return void
*/
function uploadLogo()
{
if ($_FILES['app_icon']['error'] ==
@ -153,5 +152,4 @@ class Oauth_application extends Memcached_DataObject
$oauser->application_id = $this->id;
$oauser->delete();
}
}

View File

@ -40,5 +40,4 @@ class Oauth_application_user extends Memcached_DataObject
return empty($result) ? null : $oau;
}
}

View File

@ -103,7 +103,6 @@ class Profile extends Memcached_DataObject
foreach (array(AVATAR_PROFILE_SIZE, AVATAR_STREAM_SIZE, AVATAR_MINI_SIZE) as $size) {
# We don't do a scaled one if original is our scaled size
if (!($avatar->width == $size && $avatar->height == $size)) {
$scaled_filename = $imagefile->resize($size);
//$scaled = DB_DataObject::factory('avatar');
@ -429,10 +428,10 @@ class Profile extends Memcached_DataObject
function subscriptionCount()
{
$c = common_memcache();
$c = Cache::instance();
if (!empty($c)) {
$cnt = $c->get(common_cache_key('profile:subscription_count:'.$this->id));
$cnt = $c->get(Cache::key('profile:subscription_count:'.$this->id));
if (is_integer($cnt)) {
return (int) $cnt;
}
@ -446,7 +445,7 @@ class Profile extends Memcached_DataObject
$cnt = ($cnt > 0) ? $cnt - 1 : $cnt;
if (!empty($c)) {
$c->set(common_cache_key('profile:subscription_count:'.$this->id), $cnt);
$c->set(Cache::key('profile:subscription_count:'.$this->id), $cnt);
}
return $cnt;
@ -454,9 +453,9 @@ class Profile extends Memcached_DataObject
function subscriberCount()
{
$c = common_memcache();
$c = Cache::instance();
if (!empty($c)) {
$cnt = $c->get(common_cache_key('profile:subscriber_count:'.$this->id));
$cnt = $c->get(Cache::key('profile:subscriber_count:'.$this->id));
if (is_integer($cnt)) {
return (int) $cnt;
}
@ -468,17 +467,52 @@ class Profile extends Memcached_DataObject
$cnt = (int) $sub->count('distinct subscriber');
if (!empty($c)) {
$c->set(common_cache_key('profile:subscriber_count:'.$this->id), $cnt);
$c->set(Cache::key('profile:subscriber_count:'.$this->id), $cnt);
}
return $cnt;
}
function hasFave($notice)
{
$cache = Cache::instance();
// XXX: Kind of a hack.
if (!empty($cache)) {
// This is the stream of favorite notices, in rev chron
// order. This forces it into cache.
$ids = Fave::stream($this->id, 0, NOTICE_CACHE_WINDOW);
// If it's in the list, then it's a fave
if (in_array($notice->id, $ids)) {
return true;
}
// If we're not past the end of the cache window,
// then the cache has all available faves, so this one
// is not a fave.
if (count($ids) < NOTICE_CACHE_WINDOW) {
return false;
}
// Otherwise, cache doesn't have all faves;
// fall through to the default
}
$fave = Fave::pkeyGet(array('user_id' => $this->id,
'notice_id' => $notice->id));
return ((is_null($fave)) ? false : true);
}
function faveCount()
{
$c = common_memcache();
$c = Cache::instance();
if (!empty($c)) {
$cnt = $c->get(common_cache_key('profile:fave_count:'.$this->id));
$cnt = $c->get(Cache::key('profile:fave_count:'.$this->id));
if (is_integer($cnt)) {
return (int) $cnt;
}
@ -489,7 +523,7 @@ class Profile extends Memcached_DataObject
$cnt = (int) $faves->count('distinct notice_id');
if (!empty($c)) {
$c->set(common_cache_key('profile:fave_count:'.$this->id), $cnt);
$c->set(Cache::key('profile:fave_count:'.$this->id), $cnt);
}
return $cnt;
@ -497,10 +531,10 @@ class Profile extends Memcached_DataObject
function noticeCount()
{
$c = common_memcache();
$c = Cache::instance();
if (!empty($c)) {
$cnt = $c->get(common_cache_key('profile:notice_count:'.$this->id));
$cnt = $c->get(Cache::key('profile:notice_count:'.$this->id));
if (is_integer($cnt)) {
return (int) $cnt;
}
@ -511,41 +545,55 @@ class Profile extends Memcached_DataObject
$cnt = (int) $notices->count('distinct id');
if (!empty($c)) {
$c->set(common_cache_key('profile:notice_count:'.$this->id), $cnt);
$c->set(Cache::key('profile:notice_count:'.$this->id), $cnt);
}
return $cnt;
}
function blowFavesCache()
{
$cache = common_memcache();
if ($cache) {
// Faves don't happen chronologically, so we need to blow
// ;last cache, too
$cache->delete(common_cache_key('fave:ids_by_user:'.$this->id));
$cache->delete(common_cache_key('fave:ids_by_user:'.$this->id.';last'));
$cache->delete(common_cache_key('fave:ids_by_user_own:'.$this->id));
$cache->delete(common_cache_key('fave:ids_by_user_own:'.$this->id.';last'));
}
$this->blowFaveCount();
}
function blowSubscriberCount()
{
$c = common_memcache();
$c = Cache::instance();
if (!empty($c)) {
$c->delete(common_cache_key('profile:subscriber_count:'.$this->id));
$c->delete(Cache::key('profile:subscriber_count:'.$this->id));
}
}
function blowSubscriptionCount()
{
$c = common_memcache();
$c = Cache::instance();
if (!empty($c)) {
$c->delete(common_cache_key('profile:subscription_count:'.$this->id));
$c->delete(Cache::key('profile:subscription_count:'.$this->id));
}
}
function blowFaveCount()
{
$c = common_memcache();
$c = Cache::instance();
if (!empty($c)) {
$c->delete(common_cache_key('profile:fave_count:'.$this->id));
$c->delete(Cache::key('profile:fave_count:'.$this->id));
}
}
function blowNoticeCount()
{
$c = common_memcache();
$c = Cache::instance();
if (!empty($c)) {
$c->delete(common_cache_key('profile:notice_count:'.$this->id));
$c->delete(Cache::key('profile:notice_count:'.$this->id));
}
}
@ -790,13 +838,14 @@ class Profile extends Memcached_DataObject
* @param $right string Name of the right, usually a constant in class Right
* @return boolean whether the user has the right in question
*/
function hasRight($right)
{
$result = false;
if ($this->hasRole(Profile_role::DELETED)) {
return false;
}
if (Event::handle('UserRightsCheck', array($this, $right, &$result))) {
switch ($right)
{
@ -960,4 +1009,25 @@ class Profile extends Memcached_DataObject
return $feed;
}
static function fromURI($uri)
{
$profile = null;
if (Event::handle('StartGetProfileFromURI', array($uri, &$profile))) {
// Get a local user or remote (OMB 0.1) profile
$user = User::staticGet('uri', $uri);
if (!empty($user)) {
$profile = $user->getProfile();
} else {
$remote_profile = Remote_profile::staticGet('uri', $uri);
if (!empty($remote_profile)) {
$profile = Profile::staticGet('id', $remote_profile->profile_id);
}
}
Event::handle('EndGetProfileFromURI', array($uri, $profile));
}
return $profile;
}
}

View File

@ -23,7 +23,6 @@ class Profile_tag extends Memcached_DataObject
###END_AUTOCODE
static function getTags($tagger, $tagged) {
$tags = array();
# XXX: store this in memcached
@ -44,7 +43,6 @@ class Profile_tag extends Memcached_DataObject
}
static function setTags($tagger, $tagged, $newtags) {
$newtags = array_unique($newtags);
$oldtags = Profile_tag::getTags($tagger, $tagged);

View File

@ -16,11 +16,15 @@ class Remember_me extends Memcached_DataObject
/* Static get */
function staticGet($k,$v=null)
{ return Memcached_DataObject::staticGet('Remember_me',$k,$v); }
{
return Memcached_DataObject::staticGet('Remember_me',$k,$v);
}
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
function sequenceKey()
{ return array(false, false); }
{
return array(false, false);
}
}

View File

@ -287,4 +287,3 @@ class Safe_DataObject extends DB_DataObject
return Safe_DataObject::$iniCache[$key];
}
}

View File

@ -167,9 +167,8 @@ class Status_network extends Safe_DataObject
' WHERE nickname = ' . $this->_quote($this->nickname);
$orig->decache();
$result = $this->query($qry);
if ($result) {
$this->encache();
}
$this->decache();
return $result;
}
@ -308,15 +307,7 @@ class Status_network extends Safe_DataObject
*/
function getTags()
{
$result = array();
$tags = new Status_network_tag();
$tags->site_id = $this->site_id;
if ($tags->find()) {
while ($tags->fetch()) {
$result[] = $tags->tag;
}
}
$result = Status_network_tag::getTags($this->site_id);
// XXX : for backwards compatibility
if (empty($result)) {
@ -329,6 +320,7 @@ class Status_network extends Safe_DataObject
/**
* Save a given set of tags
* @param array tags
* @fixme only add/remove differentials
*/
function setTags($tags)
{

View File

@ -61,9 +61,73 @@ class Status_network_tag extends Safe_DataObject
###END_AUTOCODE
function pkeyGet($kv)
{
return Memcached_DataObject::pkeyGet('Status_network_tag', $kv);
}
/**
* Fetch the (possibly cached) tag entries for the given site id.
* Uses status_network's cache settings.
*
* @param string $site_id
* @return array of strings
*/
static function getTags($site_id)
{
$key = 'status_network_tags:' . $site_id;
if (Status_network::$cache) {
$packed = Status_network::$cache->get($key);
if (is_string($packed)) {
if ($packed == '') {
return array();
} else {
return explode('|', $packed);
}
}
}
$result = array();
$tags = new Status_network_tag();
$tags->site_id = $site_id;
if ($tags->find()) {
while ($tags->fetch()) {
$result[] = $tags->tag;
}
}
if (Status_network::$cache) {
$packed = implode('|', $result);
Status_network::$cache->set($key, $packed, 3600);
}
return $result;
}
/**
* Drop the cached tag entries for this site.
* Needed after inserting/deleting a tag entry.
*/
function decache()
{
$key = 'status_network_tags:' . $this->site_id;
if (Status_network::$cache) {
Status_network::$cache->delete($key);
}
}
function insert()
{
$ret = parent::insert();
$this->decache();
return $ret;
}
function delete()
{
$ret = parent::delete();
$this->decache();
return $ret;
}
}

View File

@ -235,4 +235,33 @@ class Subscription extends Memcached_DataObject
'subscribed' => $other->id));
return (empty($sub)) ? false : true;
}
function asActivity()
{
$subscriber = Profile::staticGet('id', $this->subscriber);
$subscribed = Profile::staticGet('id', $this->subscribed);
$act = new Activity();
$act->verb = ActivityVerb::FOLLOW;
$act->id = TagURI::mint('follow:%d:%d:%s',
$subscriber->id,
$subscribed->id,
common_date_iso8601($this->created));
$act->time = strtotime($this->created);
// TRANS: Activity tile when subscribing to another person.
$act->title = _("Follow");
// TRANS: Notification given when one person starts following another.
// TRANS: %1$s is the subscriber, %2$s is the subscribed.
$act->content = sprintf(_('%1$s is now following %2$s.'),
$subscriber->getBestName(),
$subscribed->getBestName());
$act->actor = ActivityObject::fromProfile($subscriber);
$act->objects[] = ActivityObject::fromProfile($subscribed);
return $act;
}
}

View File

@ -250,6 +250,19 @@ class User extends Memcached_DataObject
$user->inboxed = 1;
// Set default-on options here, otherwise they'll be disabled
// initially for sites using caching, since the initial encache
// doesn't know about the defaults in the database.
$user->emailnotifysub = 1;
$user->emailnotifyfav = 1;
$user->emailnotifynudge = 1;
$user->emailnotifymsg = 1;
$user->emailnotifyattn = 1;
$user->emailmicroid = 1;
$user->emailpost = 1;
$user->jabbermicroid = 1;
$user->viewdesigns = 1;
$user->created = common_sql_now();
if (Event::handle('StartUserRegister', array(&$user, &$profile))) {
@ -264,7 +277,13 @@ class User extends Memcached_DataObject
}
$user->id = $id;
if (!empty($uri)) {
$user->uri = $uri;
} else {
$user->uri = common_user_uri($user);
}
if (!empty($password)) { // may not have a password for OpenID users
$user->password = common_munge_password($password, $id);
}
@ -388,37 +407,8 @@ class User extends Memcached_DataObject
function hasFave($notice)
{
$cache = common_memcache();
// XXX: Kind of a hack.
if ($cache) {
// This is the stream of favorite notices, in rev chron
// order. This forces it into cache.
$ids = Fave::stream($this->id, 0, NOTICE_CACHE_WINDOW);
// If it's in the list, then it's a fave
if (in_array($notice->id, $ids)) {
return true;
}
// If we're not past the end of the cache window,
// then the cache has all available faves, so this one
// is not a fave.
if (count($ids) < NOTICE_CACHE_WINDOW) {
return false;
}
// Otherwise, cache doesn't have all faves;
// fall through to the default
}
$fave = Fave::pkeyGet(array('user_id' => $this->id,
'notice_id' => $notice->id));
return ((is_null($fave)) ? false : true);
$profile = $this->getProfile();
return $profile->hasFave($notice);
}
function mutuallySubscribed($other)
@ -487,17 +477,8 @@ class User extends Memcached_DataObject
function blowFavesCache()
{
$cache = common_memcache();
if ($cache) {
// Faves don't happen chronologically, so we need to blow
// ;last cache, too
$cache->delete(common_cache_key('fave:ids_by_user:'.$this->id));
$cache->delete(common_cache_key('fave:ids_by_user:'.$this->id.';last'));
$cache->delete(common_cache_key('fave:ids_by_user_own:'.$this->id));
$cache->delete(common_cache_key('fave:ids_by_user_own:'.$this->id.';last'));
}
$profile = $this->getProfile();
$profile->blowFaveCount();
$profile->blowFavesCache();
}
function getSelfTags()
@ -547,6 +528,9 @@ class User extends Memcached_DataObject
if (Subscription::exists($other, $self)) {
Subscription::cancel($other, $self);
}
if (Subscription::exists($self, $other)) {
Subscription::cancel($self, $other);
}
$block->query('COMMIT');

View File

@ -465,7 +465,6 @@ class User_group extends Memcached_DataObject
}
static function register($fields) {
// MAGICALLY put fields into current scope
extract($fields);

View File

@ -18,7 +18,9 @@ class User_username extends Memcached_DataObject
/* Static get */
function staticGet($k,$v=null)
{ return Memcached_DataObject::staticGet('User_username',$k,$v); }
{
return Memcached_DataObject::staticGet('User_username',$k,$v);
}
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
@ -37,6 +39,7 @@ class User_username extends Memcached_DataObject
$user_username->provider_name = $provider_name;
$user_username->username = $username;
$user_username->created = DB_DataObject_Cast::dateTime();
if($user_username->insert()){
return $user_username;
}else{
@ -57,5 +60,4 @@ class User_username extends Memcached_DataObject
function keys() {
return array('provider_name' => 'K', 'username' => 'K');
}
}

View File

@ -120,3 +120,21 @@ create table inbox (
);
create table user_location_prefs (
user_id integer not null /*comment 'user who has the preference'*/ references "user" (id),
share_location int default 1 /* comment 'Whether to share location data'*/,
created timestamp not null /*comment 'date this record was created'*/,
modified timestamp /* comment 'date this record was modified'*/,
primary key (user_id)
);
create table inbox (
user_id integer not null /* comment 'user receiving the notice' */ references "user" (id),
notice_ids bytea /* comment 'packed list of notice ids' */,
primary key (user_id)
);

View File

@ -52,6 +52,10 @@ VALUES
('socialoomphBfD4pMqz31', 'SocialOomph', 'http://www.socialoomph.com/', now()),
('spaz','Spaz','http://funkatron.com/spaz', now()),
('StatusNet Desktop', 'StatusNet Desktop', 'http://status.net/desktop', now()),
('StatusNet Mobile', 'StatusNet Mobile', 'http://status.net/mobile', now()),
('StatusNet iPhone', 'iPhone', 'http://status.net/iphone', now()),
('StatusNet Android', 'Android', 'http://status.net/android', now()),
('StatusNet Blackberry', 'Blackberry', 'http://status.net/blackberry', now()),
('tarpipe','tarpipe','http://tarpipe.com/', now()),
('tjunar','Tjunar','http://nederflash.nl/boek/titels/tjunar-air', now()),
('tr.im','tr.im','http://tr.im/', now()),

View File

@ -136,7 +136,6 @@ create table notice (
is_local integer default 0 /* comment 'notice was generated by a user' */,
source varchar(32) /* comment 'source of comment, like "web", "im", or "clientname"' */,
conversation integer /*id of root notice in this conversation' */ references notice (id),
location varchar(255) /* comment 'physical location' */,
lat decimal(10,7) /* comment 'latitude'*/ ,
lon decimal(10,7) /* comment 'longitude'*/ ,
location_id integer /* comment 'location id if possible'*/ ,

View File

@ -1,3 +1,7 @@
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->
%%site.name%% is a
[micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service
based on the Free Software [StatusNet](http://status.net/) tool.

View File

@ -1,3 +1,7 @@
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->
Install the %%site.name%% badge on your blog or web site to show the latest updates
from you and your friends!

View File

@ -1,3 +1,7 @@
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->
A bookmarklet is a small piece of javascript code used as a bookmark. This one will let you post to %%site.name%% simply by selecting some text on a page and pressing the bookmarklet.
Drag-and-drop the following link to your bookmarks bar or right-click it and add it to your browser favorites to keep it handy.

View File

@ -1,3 +1,7 @@
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->
There are a number of options for getting in contact with responsible
people for %%site.name%%.

View File

@ -1,3 +1,7 @@
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->
These are some *Frequently Asked Questions* about this service, with
some answers.

View File

@ -1,3 +1,7 @@
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->
Users on %%site.name%% can create *groups* that other users can join.
Groups can be a great way to share information and entertainment with
a group of people who have a common interest or background.

View File

@ -1,3 +1,7 @@
<!-- Copyright 2008-2010 StatusNet Inc. and contributors. -->
<!-- Document licensed under Creative Commons Attribution 3.0 Unported. See -->
<!-- http://creativecommons.org/licenses/by/3.0/ for details. -->
%%site.name%% is a **microblogging service**. Users post short (%%site.textlimit%%
character) notices which are broadcast to their friends and fans using
the Web, RSS, or instant messages.

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