Merge branch 'master' into 0.9.x

This commit is contained in:
Evan Prodromou 2011-05-04 14:46:36 -07:00
commit 753bc7302a
19 changed files with 367 additions and 91 deletions

93
README
View File

@ -2,8 +2,8 @@
README README
------ ------
StatusNet 0.9.6 "Man on the Moon" StatusNet 0.9.7 "World Leader Pretend"
29 October 2010 17 March 2011
This is the README file for StatusNet, the Open Source microblogging This is the README file for StatusNet, the Open Source microblogging
platform. It includes installation instructions, descriptions of platform. It includes installation instructions, descriptions of
@ -96,43 +96,47 @@ for additional terms.
New this version New this version
================ ================
This is a security, bug and feature release since version 0.9.5 released on This is a security, bug and feature release since version 0.9.6 released on
10 September 2010. 23 October 2010.
For best compatibility with client software and site federation, and a lot of For best compatibility with client software and site federation, and a
bug fixes, it is highly recommended that all public sites upgrade to the new lot of bug fixes, it is highly recommended that all public sites
version. upgrade to the new version. Upgrades require new database indexes for
best performance; see Upgrade below.
Notable changes this version: Notable changes this version:
- Site moderators can now delete groups. - GroupPrivateMessage plugin lets users send private messages
- New themes: clean, shiny, mnml, victorian to a group. (Similar to "private groups" on Yammer.)
- New YammerImport plugin allows site admins to import non-private profiles and - Support for Twitter streaming API in Twitter bridge plugin
message from an authenticated Yammer site. - Support for a new Activity Streams-based API using AtomPub, allowing
- New experimental plugins: AnonFavorites, SlicedFavorites, GroupFavorited, richer API data. See http://status.net/wiki/AtomPub for details.
ForceGroup, ShareNotice - Unified Facebook plugin, replacing previous Facebook application
- OAuth upgraded to 1.0a and Facebook Connect plugin.
- Localization updates now include plugins, thanks to translatewiki.net! - A plugin to send out a daily summary email to network users.
- SSL link generation should be more consistent; alternate SSL URLs can be - In-line thumbnails of some attachments (video, images) and oEmbed objects.
set in the admin UI for more parts of the system. - Local copies of remote profiles to let moderators manage OStatus users.
- Experimental backupuser.php, restoreuser.php command-line scripts to - Upgrade upstream JS, minify everything.
dump/restore a user's complete activity stream. Can be used to transfer - Allow pushing plugin JS, CSS, and static files to a CDN.
accounts manually between sites, or to save a backup before deleting. - Configurable nickname rules.
- Unicode fixes for OStatus notices - Better support for bit.ly URL shortener.
- Header metadata on notice pages to aid in manual reposting on Facebook - InProcessCache plugin for additional caching on top of memcached.
- Lots of little fixes... - Support for Activity Streams JSON feeds on many streams.
- User-initiated backup and restore of account data in Activity Streams
format.
- Bookmark plugin for making del.icio.us-like social bookmarking sites,
including del.icio.us backup file import. Supports OStatus.
- SQLProfile plugin to tune SQL queries.
- Better sorting on timelines to support restored or imported data.
- Hundreds of translations from http://translatewiki.net/
- Hundreds of performance tunings, bug fixes, and UI improvements.
- Remove deprecated data from Activity Streams Atom output, to the
extent possible.
- NewMenu plugin for new layout of menu items.
- Experimental support for moving an account from one server to
another, using new AtomPub API.
Changes from 0.9.6 release candidate 1: A full changelog is available at http://status.net/wiki/StatusNet_0.9.7.
- fix for broken group pages when logged out
- fix for stuck ping queue entries when bad profile
- fix for bogus single-user nickname config entry error
- i18n updates
- nofollow updates
- SSL-only mode secure cookie fix
- experimental ApiLogger plugin for usage data gathering
- experimental follow-everyone plugin
A full changelog is available at http://status.net/wiki/StatusNet_0.9.6.
Prerequisites Prerequisites
============= =============
@ -243,9 +247,9 @@ especially if you've previously installed PHP/MySQL packages.
1. Unpack the tarball you downloaded on your Web server. Usually a 1. Unpack the tarball you downloaded on your Web server. Usually a
command like this will work: command like this will work:
tar zxf statusnet-0.9.6.tar.gz tar zxf statusnet-0.9.7.tar.gz
...which will make a statusnet-0.9.6 subdirectory in your current ...which will make a statusnet-0.9.7 subdirectory in your current
directory. (If you don't have shell access on your Web server, you 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 may have to unpack the tarball on your local computer and FTP the
files to the server.) files to the server.)
@ -253,7 +257,7 @@ especially if you've previously installed PHP/MySQL packages.
2. Move the tarball to a directory of your choosing in your Web root 2. Move the tarball to a directory of your choosing in your Web root
directory. Usually something like this will work: directory. Usually something like this will work:
mv statusnet-0.9.6 /var/www/statusnet mv statusnet-0.9.7 /var/www/statusnet
This will make your StatusNet instance available in the statusnet path of This will make your StatusNet instance available in the statusnet path of
your server, like "http://example.net/statusnet". "microblog" or your server, like "http://example.net/statusnet". "microblog" or
@ -668,7 +672,7 @@ with this situation.
If you've been using StatusNet 0.7, 0.6, 0.5 or lower, or if you've 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 been tracking the "git" version of the software, you will probably
want to upgrade and keep your existing data. There is no automated want to upgrade and keep your existing data. There is no automated
upgrade procedure in StatusNet 0.9.6. Try these step-by-step upgrade procedure in StatusNet 0.9.7. Try these step-by-step
instructions; read to the end first before trying them. instructions; read to the end first before trying them.
0. Download StatusNet and set up all the prerequisites as if you were 0. Download StatusNet and set up all the prerequisites as if you were
@ -689,25 +693,30 @@ instructions; read to the end first before trying them.
5. Once all writing processes to your site are turned off, make a 5. Once all writing processes to your site are turned off, make a
final backup of the Web directory and database. final backup of the Web directory and database.
6. Move your StatusNet directory to a backup spot, like "statusnet.bak". 6. Move your StatusNet directory to a backup spot, like "statusnet.bak".
7. Unpack your StatusNet 0.9.6 tarball and move it to "statusnet" or 7. Unpack your StatusNet 0.9.7 tarball and move it to "statusnet" or
wherever your code used to be. wherever your code used to be.
8. Copy the config.php file and the contents of the avatar/, background/, 8. Copy the config.php file and the contents of the avatar/, background/,
file/, and local/ subdirectories from your old directory to your new file/, and local/ subdirectories from your old directory to your new
directory. directory.
9. Copy htaccess.sample to .htaccess in the new directory. Change the 9. Copy htaccess.sample to .htaccess in the new directory. Change the
RewriteBase to use the correct path. RewriteBase to use the correct path.
10. Rebuild the database. (You can safely skip this step and go to #12 10. Rebuild the database.
if you're upgrading from another 0.9.x version).
NOTE: this step is destructive and cannot be NOTE: this step is destructive and cannot be
reversed. YOU CAN EASILY DESTROY YOUR SITE WITH THIS STEP. Don't reversed. YOU CAN EASILY DESTROY YOUR SITE WITH THIS STEP. Don't
do it without a known-good backup! do it without a known-good backup!
If your database is at version 0.8.0 or above, you can run a If your database is at version 0.8.0 or higher in the 0.8.x line, you can run a
special upgrade script: special upgrade script:
mysql -u<rootuser> -p<rootpassword> <database> db/08to09.sql mysql -u<rootuser> -p<rootpassword> <database> db/08to09.sql
If you are upgrading from any 0.9.x version like 0.9.6, run this script:
mysql -u<rootuser> -p<rootpassword> <database> db/096to097.sql
Despite the name, it should work for any 0.9.x branch.
Otherwise, go to your StatusNet directory and AFTER YOU MAKE A Otherwise, go to your StatusNet directory and AFTER YOU MAKE A
BACKUP run the rebuilddb.sh script like this: BACKUP run the rebuilddb.sh script like this:

View File

@ -322,8 +322,11 @@ class ApiTimelineUserAction extends ApiBareAuthAction
$this->clientError(_('Atom post must not be empty.')); $this->clientError(_('Atom post must not be empty.'));
} }
$dom = DOMDocument::loadXML($xml); $old = error_reporting(error_reporting() & ~(E_WARNING | E_NOTICE));
if (!$dom) { $dom = new DOMDocument();
$ok = $dom->loadXML($xml);
error_reporting($old);
if (!$ok) {
// TRANS: Client error displayed attempting to post an API that is not well-formed XML. // TRANS: Client error displayed attempting to post an API that is not well-formed XML.
$this->clientError(_('Atom post must be well-formed XML.')); $this->clientError(_('Atom post must be well-formed XML.'));
} }

View File

@ -282,7 +282,11 @@ class RecoverpasswordAction extends Action
$user = User::staticGet('email', common_canonical_email($nore)); $user = User::staticGet('email', common_canonical_email($nore));
if (!$user) { if (!$user) {
$user = User::staticGet('nickname', common_canonical_nickname($nore)); try {
$user = User::staticGet('nickname', common_canonical_nickname($nore));
} catch (NicknameException $e) {
// invalid
}
} }
# See if it's an unconfirmed email address # See if it's an unconfirmed email address

View File

@ -445,19 +445,19 @@ class Notice extends Memcached_DataObject
function blowOnInsert($conversation = false) function blowOnInsert($conversation = false)
{ {
self::blow('profile:notice_ids:%d', $this->profile_id); $this->blowStream('profile:notice_ids:%d', $this->profile_id);
if ($this->isPublic()) { if ($this->isPublic()) {
self::blow('public'); $this->blowStream('public');
} }
// XXX: Before we were blowing the casche only if the notice id // XXX: Before we were blowing the casche only if the notice id
// was not the root of the conversation. What to do now? // was not the root of the conversation. What to do now?
self::blow('notice:conversation_ids:%d', $this->conversation); $this->blowStream('notice:conversation_ids:%d', $this->conversation);
if (!empty($this->repeat_of)) { if (!empty($this->repeat_of)) {
self::blow('notice:repeats:%d', $this->repeat_of); $this->blowStream('notice:repeats:%d', $this->repeat_of);
} }
$original = Notice::staticGet('id', $this->repeat_of); $original = Notice::staticGet('id', $this->repeat_of);
@ -465,11 +465,12 @@ class Notice extends Memcached_DataObject
if (!empty($original)) { if (!empty($original)) {
$originalUser = User::staticGet('id', $original->profile_id); $originalUser = User::staticGet('id', $original->profile_id);
if (!empty($originalUser)) { if (!empty($originalUser)) {
self::blow('user:repeats_of_me:%d', $originalUser->id); $this->blowStream('user:repeats_of_me:%d', $originalUser->id);
} }
} }
$profile = Profile::staticGet($this->profile_id); $profile = Profile::staticGet($this->profile_id);
if (!empty($profile)) { if (!empty($profile)) {
$profile->blowNoticeCount(); $profile->blowNoticeCount();
} }
@ -490,6 +491,42 @@ class Notice extends Memcached_DataObject
} }
} }
function blowStream()
{
$c = self::memcache();
if (empty($c)) {
return false;
}
$args = func_get_args();
$format = array_shift($args);
$keyPart = vsprintf($format, $args);
$cacheKey = Cache::key($keyPart);
$c->delete($cacheKey);
// delete the "last" stream, too, if this notice is
// older than the top of that stream
$lastKey = $cacheKey.';last';
$lastStr = $c->get($lastKey);
if ($lastStr !== false) {
$window = explode(',', $lastStr);
$lastID = $window[0];
$lastNotice = Notice::staticGet('id', $lastID);
if (empty($lastNotice) // just weird
|| strtotime($lastNotice->created) >= strtotime($this->created)) {
$c->delete($lastKey);
}
}
}
/** save all urls in the notice to the db /** save all urls in the notice to the db
* *
* follow redirects and save all available file information * follow redirects and save all available file information
@ -1513,22 +1550,22 @@ class Notice extends Memcached_DataObject
} }
$laststr = $cache->get($idkey.';last'); $laststr = $cache->get($idkey.';last');
if ($laststr !== false) { if ($laststr !== false) {
$window = explode(',', $laststr); $window = explode(',', $laststr);
$last_id = $window[0]; $last_id = $window[0];
$new_ids = call_user_func_array($fn, array_merge($args, array(0, NOTICE_CACHE_WINDOW, $new_ids = call_user_func_array($fn, array_merge($args, array(0, NOTICE_CACHE_WINDOW,
$last_id, 0, null))); $last_id, 0, null)));
$new_window = array_merge($new_ids, $window); $new_window = array_merge($new_ids, $window);
$new_windowstr = implode(',', $new_window); $new_windowstr = implode(',', $new_window);
$result = $cache->set($idkey, $new_windowstr); $result = $cache->set($idkey, $new_windowstr);
$result = $cache->set($idkey . ';last', $new_windowstr); $result = $cache->set($idkey . ';last', $new_windowstr);
$ids = array_slice($new_window, $offset, $limit); $ids = array_slice($new_window, $offset, $limit);
return $ids; return $ids;
} }

View File

@ -83,15 +83,9 @@ class ActivityImporter extends QueueHandler
Event::handle('EndImportActivity', Event::handle('EndImportActivity',
array($user, $author, $activity, $trusted)); array($user, $author, $activity, $trusted));
$done = true; $done = true;
} catch (ClientException $ce) {
common_log(LOG_WARNING, $ce->getMessage());
$done = true;
} catch (ServerException $se) {
common_log(LOG_ERR, $se->getMessage());
$done = false;
} catch (Exception $e) { } catch (Exception $e) {
common_log(LOG_ERR, $e->getMessage()); common_log(LOG_ERR, $e->getMessage());
$done = false; $done = true;
} }
} }
return $done; return $done;

View File

@ -22,13 +22,13 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
//exit with 200 response, if this is checking fancy from the installer //exit with 200 response, if this is checking fancy from the installer
if (isset($_REQUEST['p']) && $_REQUEST['p'] == 'check-fancy') { exit; } if (isset($_REQUEST['p']) && $_REQUEST['p'] == 'check-fancy') { exit; }
define('STATUSNET_BASE_VERSION', '0.9.8'); define('STATUSNET_BASE_VERSION', '0.9.7');
define('STATUSNET_LIFECYCLE', 'dev'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release' define('STATUSNET_LIFECYCLE', 'fix1'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', '' for release
define('STATUSNET_VERSION', STATUSNET_BASE_VERSION . STATUSNET_LIFECYCLE); define('STATUSNET_VERSION', STATUSNET_BASE_VERSION . STATUSNET_LIFECYCLE);
define('LACONICA_VERSION', STATUSNET_VERSION); // compatibility define('LACONICA_VERSION', STATUSNET_VERSION); // compatibility
define('STATUSNET_CODENAME', 'Letter Never Sent'); define('STATUSNET_CODENAME', 'World Leader Pretend');
define('AVATAR_PROFILE_SIZE', 96); define('AVATAR_PROFILE_SIZE', 96);
define('AVATAR_STREAM_SIZE', 48); define('AVATAR_STREAM_SIZE', 48);

View File

@ -102,7 +102,7 @@ class NoticeSection extends Section
$this->out->elementEnd('p'); $this->out->elementEnd('p');
$this->out->elementStart('div', 'entry_content'); $this->out->elementStart('div', 'entry_content');
get_class('NoticeList'); class_exists('NoticeList');
$nli = new NoticeListItem($notice, $this->out); $nli = new NoticeListItem($notice, $this->out);
$nli->showNoticeLink(); $nli->showNoticeLink();
$this->out->elementEnd('div'); $this->out->elementEnd('div');

View File

@ -126,6 +126,15 @@ class Router
return Router::$inst; return Router::$inst;
} }
/**
* Clear the global singleton instance for this class.
* Needed to ensure reset when switching site configurations.
*/
static function clear()
{
Router::$inst = null;
}
function __construct() function __construct()
{ {
if (empty($this->m)) { if (empty($this->m)) {

View File

@ -107,6 +107,8 @@ class StatusNet
*/ */
public static function init($server=null, $path=null, $conffile=null) public static function init($server=null, $path=null, $conffile=null)
{ {
Router::clear();
StatusNet::initDefaults($server, $path); StatusNet::initDefaults($server, $path);
StatusNet::loadConfigFile($conffile); StatusNet::loadConfigFile($conffile);

View File

@ -238,8 +238,23 @@ class Bookmark extends Memcached_DataObject
if (array_key_exists('uri', $options)) { if (array_key_exists('uri', $options)) {
$nb->uri = $options['uri']; $nb->uri = $options['uri'];
} else { } else {
$nb->uri = common_local_url('showbookmark', // FIXME: hacks to work around router bugs in
array('id' => $nb->id)); // queue daemons
$r = Router::get();
$path = $r->build('showbookmark',
array('id' => $nb->id));
if (empty($path)) {
$nb->uri = common_path('bookmark/'.$nb->id, false, false);
} else {
$nb->uri = common_local_url('showbookmark',
array('id' => $nb->id),
null,
null,
false);
}
} }
$nb->insert(); $nb->insert();
@ -314,11 +329,20 @@ class Bookmark extends Memcached_DataObject
$options['uri'] = $nb->uri; $options['uri'] = $nb->uri;
} }
$saved = Notice::saveNew($profile->id, try {
$content, $saved = Notice::saveNew($profile->id,
array_key_exists('source', $options) ? $content,
$options['source'] : 'web', array_key_exists('source', $options) ?
$options); $options['source'] : 'web',
$options);
} catch (Exception $e) {
$nb->delete();
throw $e;
}
if (empty($saved)) {
$nb->delete();
}
return $saved; return $saved;
} }

View File

@ -450,7 +450,7 @@ class BookmarkPlugin extends Plugin
function onPluginVersion(&$versions) function onPluginVersion(&$versions)
{ {
$versions[] = array('name' => 'Sample', $versions[] = array('name' => 'Bookmark',
'version' => self::VERSION, 'version' => self::VERSION,
'author' => 'Evan Prodromou', 'author' => 'Evan Prodromou',
'homepage' => 'http://status.net/wiki/Plugin:Bookmark', 'homepage' => 'http://status.net/wiki/Plugin:Bookmark',

View File

@ -79,6 +79,12 @@ class DeliciousBackupImporter extends QueueHandler
$doc = $this->importHTML($body); $doc = $this->importHTML($body);
// If we can't parse it, it's no good
if (empty($doc)) {
return true;
}
$dls = $doc->getElementsByTagName('dl'); $dls = $doc->getElementsByTagName('dl');
if ($dls->length != 1) { if ($dls->length != 1) {
@ -112,9 +118,11 @@ class DeliciousBackupImporter extends QueueHandler
case 'dd': case 'dd':
$dd = $child; $dd = $child;
// This <dd> contains a description for the bookmark in if (!empty($dt)) {
// the preceding <dt> node. // This <dd> contains a description for the bookmark in
$saved = $this->importBookmark($user, $dt, $dd); // the preceding <dt> node.
$saved = $this->importBookmark($user, $dt, $dd);
}
$dt = null; $dt = null;
$dd = null; $dd = null;

View File

@ -526,7 +526,7 @@ ENDOFSCRIPT;
*/ */
function onEndFavorNotice(Profile $profile, Notice $notice) function onEndFavorNotice(Profile $profile, Notice $notice)
{ {
$client = new Facebookclient($notice); $client = new Facebookclient($notice, $profile);
$client->like(); $client->like();
return true; return true;
@ -542,7 +542,7 @@ ENDOFSCRIPT;
*/ */
function onEndDisfavorNotice(Profile $profile, Notice $notice) function onEndDisfavorNotice(Profile $profile, Notice $notice)
{ {
$client = new Facebookclient($notice); $client = new Facebookclient($notice, $profile);
$client->unLike(); $client->unLike();
return true; return true;

View File

@ -48,7 +48,12 @@ class Facebookclient
protected $notice = null; // The user's notice protected $notice = null; // The user's notice
protected $user = null; // Sender of the notice protected $user = null; // Sender of the notice
function __construct($notice) /**
*
* @param Notice $notice the notice to manipulate
* @param Profile $profile local user to act as; if left empty, the notice's poster will be used.
*/
function __construct($notice, $profile=null)
{ {
$this->facebook = self::getFacebook(); $this->facebook = self::getFacebook();
@ -60,8 +65,9 @@ class Facebookclient
$this->notice = $notice; $this->notice = $notice;
$profile_id = $profile ? $profile->id : $notice->profile_id;
$this->flink = Foreign_link::getByUserID( $this->flink = Foreign_link::getByUserID(
$notice->profile_id, $profile_id,
FACEBOOK_SERVICE FACEBOOK_SERVICE
); );

View File

@ -127,7 +127,10 @@ class Group_message_profile extends Memcached_DataObject
$gmp->insert(); $gmp->insert();
$gmp->notify(); // If it's not for the author, send email notification
if ($gm->from_profile != $profile->id) {
$gmp->notify();
}
return $gmp; return $gmp;
} }
@ -156,9 +159,7 @@ class Group_message_profile extends Memcached_DataObject
// TRANS: Subject for direct-message notification email. // TRANS: Subject for direct-message notification email.
// TRANS: %s is the sending user's nickname. // TRANS: %s is the sending user's nickname.
$subject = sprintf(_('New private message from %s to group %s'), $from->nickname, $group->nickname); $subject = sprintf(_('New private message from %s to group %s'), $from_profile->nickname, $group->nickname);
$from_profile = $from->getProfile();
// TRANS: Body for direct-message notification email. // TRANS: Body for direct-message notification email.
// TRANS: %1$s is the sending user's long name, %2$s is the sending user's nickname, // TRANS: %1$s is the sending user's long name, %2$s is the sending user's nickname,
@ -174,13 +175,13 @@ class Group_message_profile extends Memcached_DataObject
"With kind regards,\n". "With kind regards,\n".
"%6\$s\n"), "%6\$s\n"),
$from_profile->getBestName(), $from_profile->getBestName(),
$from->nickname, $from_profile->nickname,
$group->nickname, $group->nickname,
$this->content, $gm->content,
common_local_url('newmessage', array('to' => $from->id)), common_local_url('newmessage', array('to' => $from_profile->id)),
common_config('site', 'name')); common_config('site', 'name'));
$headers = _mail_prepare_headers('message', $to->nickname, $from->nickname); $headers = _mail_prepare_headers('message', $to->nickname, $from_profile->nickname);
common_switch_locale(); common_switch_locale();

View File

@ -129,9 +129,9 @@ class ModPlusPlugin extends Plugin
* Currently only adds output for remote profiles, nothing for local users. * Currently only adds output for remote profiles, nothing for local users.
* *
* @param HTMLOutputter $out * @param HTMLOutputter $out
* @param Profile $profile * @param Profile $profile (may also be an ArrayWrapper... sigh)
*/ */
protected function showProfileOptions(HTMLOutputter $out, Profile $profile) protected function showProfileOptions(HTMLOutputter $out, $profile)
{ {
$isRemote = !(User::staticGet('id', $profile->id)); $isRemote = !(User::staticGet('id', $profile->id));
if ($isRemote) { if ($isRemote) {

View File

@ -0,0 +1,92 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Plugin to put the site notice in the sidebar
*
* 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 Plugin
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
/**
* Put the site notice in the sidebar
*
* @category General
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class SiteNoticeInSidebarPlugin extends Plugin
{
/**
* Function comment
*
* @param
*
* @return
*/
function onStartShowSiteNotice($action)
{
return false;
}
function onStartShowSections($action)
{
$text = common_config('site', 'notice');
if (!empty($text)) {
$sns = new SiteNoticeSection($action, $text);
$sns->show();
}
return true;
}
function onEndShowStyles($action)
{
$action->element('style', null, '#site_notice { width: 100% }');
return true;
}
function onAutoload($cls)
{
$dir = dirname(__FILE__);
switch ($cls)
{
case 'SiteNoticeSection':
include_once $dir . '/'.strtolower($cls).'.php';
return false;
default:
return true;
}
}
}

View File

@ -0,0 +1,67 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Site notice section
*
* 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 Site
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
/**
* Site notice section
*
* @category Site
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class SiteNoticeSection extends Section
{
var $text;
function __construct($action, $text)
{
parent::__construct($action);
$this->text = $text;
}
function title()
{
return _('Site notice');
}
function showContent()
{
$this->out->raw($this->text);
}
}

View File

@ -320,7 +320,20 @@ function process_error($e, $flink, $notice)
common_log(LOG_WARNING, $logmsg); common_log(LOG_WARNING, $logmsg);
// http://dev.twitter.com/pages/responses_errors
switch($code) { switch($code) {
case 400:
// Probably invalid data (bad Unicode chars or coords) that
// cannot be resolved by just sending again.
//
// It could also be rate limiting, but retrying immediately
// won't help much with that, so we'll discard for now.
// If a facility for retrying things later comes up in future,
// we can detect the rate-limiting headers and use that.
//
// Discard the message permanently.
return true;
break;
case 401: case 401:
// Probably a revoked or otherwise bad access token - nuke! // Probably a revoked or otherwise bad access token - nuke!
remove_twitter_link($flink); remove_twitter_link($flink);
@ -330,6 +343,13 @@ function process_error($e, $flink, $notice)
// User has exceeder her rate limit -- toss the notice // User has exceeder her rate limit -- toss the notice
return true; return true;
break; break;
case 404:
// Resource not found. Shouldn't happen much on posting,
// but just in case!
//
// Consider it a matter for tossing the notice.
return true;
break;
default: default:
// For every other case, it's probably some flakiness so try // For every other case, it's probably some flakiness so try