Merge branch '0.7.x' into 0.8.x
Conflicts: classes/Notice.php classes/Profile.php lib/common.php lib/util.php scripts/getvaliddaemons.php scripts/stopdaemons.sh
This commit is contained in:
commit
adfb79a9bb
60
README
60
README
@ -2,8 +2,8 @@
|
||||
README
|
||||
------
|
||||
|
||||
Laconica 0.7.3 ("You Are The Everything")
|
||||
7 April 2009
|
||||
Laconica 0.7.4 ("Can't Get There From Here")
|
||||
29 May 2009
|
||||
|
||||
This is the README file for Laconica, the Open Source microblogging
|
||||
platform. It includes installation instructions, descriptions of
|
||||
@ -71,29 +71,29 @@ for additional terms.
|
||||
New this version
|
||||
================
|
||||
|
||||
This is a minor bug-fix and feature release since version 0.7.2.1,
|
||||
released Mar 11 2009. Notable changes this version:
|
||||
This is a minor bug-fix and feature release since version 0.7.3,
|
||||
released Apr 4 2009. Notable changes this version:
|
||||
|
||||
- A plugin to allow a templating language for customization
|
||||
- A plugin for Piwik Analytics engine
|
||||
- A bookmarklet for posting a notice about a Web page you're reading
|
||||
- A welcome notice ('welcomebot') and default subscription for new users
|
||||
- Support for SSL for some or all pages on the site
|
||||
- Better handling of empty notice lists on many pages
|
||||
- Major improvements to the Twitter friend-sync offline processing
|
||||
- subscribers, subscriptions, groups are listed on the Personal page.
|
||||
- "Invite" link restored to main menu
|
||||
- Better memory handling in FOAF output
|
||||
- Fix for SUP support (FriendFeed)
|
||||
- Correct and intelligent redirect HTTP status codes
|
||||
- Fix DB collations for search and sort
|
||||
- Better H1s and Titles using user full names
|
||||
- Fixes to make the linkback plugin operational
|
||||
- Better indication that a notice is being published by Ajax (spinner)
|
||||
- Better and unified Atom output
|
||||
- Hiding "register" and "join now" messages when site is closed
|
||||
- ping, twitter and facebook queuehandlers working better
|
||||
- Updated RPM spec
|
||||
- Improved handling of UTF-8 characters. The new code is *not* backwards
|
||||
compatible by default; see "Upgrading" below for instructions on
|
||||
converting existing databases to the correct character set.
|
||||
- Unroll joins for large queries. This greatly enhanced database
|
||||
performance -- up to 50x for some queries -- at the expense of making
|
||||
an extra DB hit for some queries.
|
||||
- Added an optional plugin to use WikiHashtags
|
||||
(http://hashtags.wikia.com/) for the sidebar on hashtag pages.
|
||||
- Optimized Twitter friend synchronization.
|
||||
- Better error handling for Ajax posting of notices, including
|
||||
HTTP errors and timeouts.
|
||||
- Experimental Comet plugin -- supports the cometd and the Bayeux
|
||||
protocol. Using this plugin, you can show "real time" updates on the
|
||||
public and tag pages. However, server configuration is complex.
|
||||
- If queues are enabled, update inboxes and memcached off-line. Speeds
|
||||
up posting considerably.
|
||||
- Correctly shorten links posted through XMPP.
|
||||
- <link> elements for pagination, supported by some browsers like Opera.
|
||||
- Corrected date format in search API.
|
||||
- Made the public XRDS file work correctly.
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
@ -197,9 +197,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 laconica-0.7.3.tar.gz
|
||||
tar zxf laconica-0.7.4.tar.gz
|
||||
|
||||
...which will make a laconica-0.7.3 subdirectory in your current
|
||||
...which will make a laconica-0.7.4 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.)
|
||||
@ -207,7 +207,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 laconica-0.7.3 /var/www/mublog
|
||||
mv laconica-0.7.4 /var/www/mublog
|
||||
|
||||
This will make your Laconica instance available in the mublog path of
|
||||
your server, like "http://example.net/mublog". "microblog" or
|
||||
@ -704,7 +704,7 @@ with this situation.
|
||||
If you've been using Laconica 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 Laconica 0.7.3. Try these step-by-step instructions; read
|
||||
procedure in Laconica 0.7.4. Try these step-by-step instructions; read
|
||||
to the end first before trying them.
|
||||
|
||||
0. Download Laconica and set up all the prerequisites as if you were
|
||||
@ -1239,7 +1239,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 Laconica 0.7.3 without reading the "Notice inboxes"
|
||||
If you upgraded to Laconica 0.7.4 without reading the "Notice inboxes"
|
||||
section above, and all your users' 'Personal' tabs are empty, read the
|
||||
"Notice inboxes" section above.
|
||||
|
||||
@ -1330,6 +1330,8 @@ if anyone's been overlooked in error.
|
||||
* Ken Sedgwick
|
||||
* Brian Hendrickson
|
||||
* Tobias Diekershoff
|
||||
* Dan Moore
|
||||
* Fil
|
||||
|
||||
Thanks also to the developers of our upstream library code and to the
|
||||
thousands of people who have tried out Identi.ca, installed Laconi.ca,
|
||||
|
@ -144,8 +144,8 @@ class ApiAction extends Action
|
||||
}
|
||||
|
||||
if (in_array($fullname, $bareauth)) {
|
||||
# bareauth: only needs auth if without an argument
|
||||
if ($this->api_arg) {
|
||||
# bareauth: only needs auth if without an argument or query param specifying user
|
||||
if ($this->api_arg || $this->arg('id') || is_numeric($this->arg('user_id')) || $this->arg('screen_name')) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
|
@ -122,7 +122,7 @@ class ShownoticeAction extends Action
|
||||
|
||||
function lastModified()
|
||||
{
|
||||
return max(strtotime($this->notice->created),
|
||||
return max(strtotime($this->notice->modified),
|
||||
strtotime($this->profile->modified),
|
||||
($this->avatar) ? strtotime($this->avatar->modified) : 0);
|
||||
}
|
||||
|
@ -98,9 +98,31 @@ class TwitapiaccountAction extends TwitterapiAction
|
||||
$this->serverError(_('API method under construction.'), $code=501);
|
||||
}
|
||||
|
||||
// We don't have a rate limit, but some clients check this method.
|
||||
// It always returns the same thing: 100 hit left.
|
||||
function rate_limit_status($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
$this->serverError(_('API method under construction.'), $code=501);
|
||||
|
||||
$type = $apidata['content-type'];
|
||||
$this->init_document($type);
|
||||
|
||||
if ($apidata['content-type'] == 'xml') {
|
||||
$this->elementStart('hash');
|
||||
$this->element('remaining-hits', array('type' => 'integer'), 100);
|
||||
$this->element('hourly-limit', array('type' => 'integer'), 100);
|
||||
$this->element('reset-time', array('type' => 'datetime'), null);
|
||||
$this->element('reset_time_in_seconds', array('type' => 'integer'), 0);
|
||||
$this->elementEnd('hash');
|
||||
} elseif ($apidata['content-type'] == 'json') {
|
||||
|
||||
$out = array('reset_time_in_seconds' => 0,
|
||||
'remaining_hits' => 100,
|
||||
'hourly_limit' => 100,
|
||||
'reset_time' => '');
|
||||
print json_encode($out);
|
||||
}
|
||||
|
||||
$this->end_document($type);
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ class Twitapidirect_messagesAction extends TwitterapiAction
|
||||
$count = $this->arg('count');
|
||||
$since = $this->arg('since');
|
||||
$since_id = $this->arg('since_id');
|
||||
$before_id = $this->arg('before_id');
|
||||
$max_id = $this->arg('max_id');
|
||||
|
||||
$page = $this->arg('page');
|
||||
|
||||
@ -74,8 +74,8 @@ class Twitapidirect_messagesAction extends TwitterapiAction
|
||||
$link = $server . $user->nickname . '/outbox';
|
||||
}
|
||||
|
||||
if ($before_id) {
|
||||
$message->whereAdd("id < $before_id");
|
||||
if ($max_id) {
|
||||
$message->whereAdd("id <= $max_id");
|
||||
}
|
||||
|
||||
if ($since_id) {
|
||||
|
@ -45,22 +45,21 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
|
||||
$page = $this->arg('page');
|
||||
$since_id = $this->arg('since_id');
|
||||
$before_id = $this->arg('before_id');
|
||||
$max_id = $this->arg('max_id');
|
||||
|
||||
// NOTE: page, since_id, and before_id are extensions to Twitter API -- TB
|
||||
if (!$page) {
|
||||
$page = 1;
|
||||
}
|
||||
if (!$since_id) {
|
||||
$since_id = 0;
|
||||
}
|
||||
if (!$before_id) {
|
||||
$before_id = 0;
|
||||
if (!$max_id) {
|
||||
$max_id = 0;
|
||||
}
|
||||
|
||||
$since = strtotime($this->arg('since'));
|
||||
|
||||
$notice = Notice::publicStream((($page-1)*$MAX_PUBSTATUSES), $MAX_PUBSTATUSES, $since_id, $before_id, $since);
|
||||
$notice = Notice::publicStream((($page-1)*$MAX_PUBSTATUSES), $MAX_PUBSTATUSES, $since_id, $max_id, $since);
|
||||
|
||||
if ($notice) {
|
||||
|
||||
@ -97,7 +96,7 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$since_id = $this->arg('since_id');
|
||||
$count = $this->arg('count');
|
||||
$page = $this->arg('page');
|
||||
$before_id = $this->arg('before_id');
|
||||
$max_id = $this->arg('max_id');
|
||||
|
||||
if (!$page) {
|
||||
$page = 1;
|
||||
@ -111,9 +110,8 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$since_id = 0;
|
||||
}
|
||||
|
||||
// NOTE: before_id is an extension to Twitter API -- TB
|
||||
if (!$before_id) {
|
||||
$before_id = 0;
|
||||
if (!$max_id) {
|
||||
$max_id = 0;
|
||||
}
|
||||
|
||||
$since = strtotime($this->arg('since'));
|
||||
@ -133,7 +131,7 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$link = common_local_url('all', array('nickname' => $user->nickname));
|
||||
$subtitle = sprintf(_('Updates from %1$s and friends on %2$s!'), $user->nickname, $sitename);
|
||||
|
||||
$notice = $user->noticesWithFriends(($page-1)*20, $count, $since_id, $before_id, $since);
|
||||
$notice = $user->noticesWithFriends(($page-1)*20, $count, $since_id, $max_id, $since);
|
||||
|
||||
switch($apidata['content-type']) {
|
||||
case 'xml':
|
||||
@ -184,7 +182,7 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$since = $this->arg('since');
|
||||
$since_id = $this->arg('since_id');
|
||||
$page = $this->arg('page');
|
||||
$before_id = $this->arg('before_id');
|
||||
$max_id = $this->arg('max_id');
|
||||
|
||||
if (!$page) {
|
||||
$page = 1;
|
||||
@ -198,9 +196,8 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$since_id = 0;
|
||||
}
|
||||
|
||||
// NOTE: before_id is an extensions to Twitter API -- TB
|
||||
if (!$before_id) {
|
||||
$before_id = 0;
|
||||
if (!$max_id) {
|
||||
$max_id = 0;
|
||||
}
|
||||
|
||||
$since = strtotime($this->arg('since'));
|
||||
@ -220,7 +217,7 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
|
||||
# XXX: since
|
||||
|
||||
$notice = $user->getNotices((($page-1)*20), $count, $since_id, $before_id, $since);
|
||||
$notice = $user->getNotices((($page-1)*20), $count, $since_id, $max_id, $since);
|
||||
|
||||
switch($apidata['content-type']) {
|
||||
case 'xml':
|
||||
@ -353,7 +350,7 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$count = $this->arg('count');
|
||||
$page = $this->arg('page');
|
||||
$since_id = $this->arg('since_id');
|
||||
$before_id = $this->arg('before_id');
|
||||
$max_id = $this->arg('max_id');
|
||||
|
||||
$user = $this->get_user($apidata['api_arg'], $apidata);
|
||||
$this->auth_user = $apidata['user'];
|
||||
@ -380,15 +377,14 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$since_id = 0;
|
||||
}
|
||||
|
||||
// NOTE: before_id is an extension to Twitter API -- TB
|
||||
if (!$before_id) {
|
||||
$before_id = 0;
|
||||
if (!$max_id) {
|
||||
$max_id = 0;
|
||||
}
|
||||
|
||||
$since = strtotime($this->arg('since'));
|
||||
|
||||
$notice = $user->getReplies((($page-1)*20),
|
||||
$count, $since_id, $before_id, $since);
|
||||
$count, $since_id, $max_id, $since);
|
||||
$notices = array();
|
||||
|
||||
while ($notice->fetch()) {
|
||||
|
@ -25,110 +25,61 @@ class TwitapiusersAction extends TwitterapiAction
|
||||
{
|
||||
|
||||
function show($args, $apidata)
|
||||
{
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
|
||||
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
|
||||
$this->clientError(_('API method not found!'), $code = 404);
|
||||
return;
|
||||
}
|
||||
|
||||
$user = null;
|
||||
$email = $this->arg('email');
|
||||
$user_id = $this->arg('user_id');
|
||||
|
||||
if ($email) {
|
||||
$user = User::staticGet('email', $email);
|
||||
} elseif ($user_id) {
|
||||
$user = $this->get_user($user_id);
|
||||
} elseif (isset($apidata['api_arg'])) {
|
||||
$user = $this->get_user($apidata['api_arg']);
|
||||
} elseif (isset($apidata['user'])) {
|
||||
$user = $apidata['user'];
|
||||
}
|
||||
|
||||
if (!$user) {
|
||||
// XXX: Twitter returns a random(?) user instead of throwing and err! -- Zach
|
||||
$this->client_error(_('Not found.'), 404, $apidata['content-type']);
|
||||
return;
|
||||
}
|
||||
$user = null;
|
||||
$email = $this->arg('email');
|
||||
$user_id = $this->arg('user_id');
|
||||
|
||||
$profile = $user->getProfile();
|
||||
// XXX: email field deprecated in Twitter's API
|
||||
|
||||
if (!$profile) {
|
||||
common_server_error(_('User has no profile.'));
|
||||
return;
|
||||
}
|
||||
// XXX: Also: need to add screen_name param
|
||||
|
||||
$twitter_user = $this->twitter_user_array($profile, true);
|
||||
if ($email) {
|
||||
$user = User::staticGet('email', $email);
|
||||
} elseif ($user_id) {
|
||||
$user = $this->get_user($user_id);
|
||||
} elseif (isset($apidata['api_arg'])) {
|
||||
$user = $this->get_user($apidata['api_arg']);
|
||||
} elseif (isset($apidata['user'])) {
|
||||
$user = $apidata['user'];
|
||||
}
|
||||
|
||||
// Add in extended user fields offered up by this method
|
||||
$twitter_user['created_at'] = $this->date_twitter($profile->created);
|
||||
if (!$user) {
|
||||
$this->client_error(_('Not found.'), 404, $apidata['content-type']);
|
||||
return;
|
||||
}
|
||||
|
||||
$subbed = DB_DataObject::factory('subscription');
|
||||
$subbed->subscriber = $profile->id;
|
||||
$subbed_count = (int) $subbed->count() - 1;
|
||||
$profile = $user->getProfile();
|
||||
|
||||
$notices = DB_DataObject::factory('notice');
|
||||
$notices->profile_id = $profile->id;
|
||||
$notice_count = (int) $notices->count();
|
||||
if (!$profile) {
|
||||
common_server_error(_('User has no profile.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$twitter_user['friends_count'] = (is_int($subbed_count)) ? $subbed_count : 0;
|
||||
$twitter_user['statuses_count'] = (is_int($notice_count)) ? $notice_count : 0;
|
||||
$twitter_user = $this->twitter_user_array($profile, true);
|
||||
|
||||
// Other fields Twitter sends...
|
||||
$twitter_user['profile_background_color'] = '';
|
||||
$twitter_user['profile_background_image_url'] = '';
|
||||
$twitter_user['profile_text_color'] = '';
|
||||
$twitter_user['profile_link_color'] = '';
|
||||
$twitter_user['profile_sidebar_fill_color'] = '';
|
||||
$twitter_user['profile_sidebar_border_color'] = '';
|
||||
$twitter_user['profile_background_tile'] = false;
|
||||
if ($apidata['content-type'] == 'xml') {
|
||||
$this->init_document('xml');
|
||||
$this->show_twitter_xml_user($twitter_user);
|
||||
$this->end_document('xml');
|
||||
} elseif ($apidata['content-type'] == 'json') {
|
||||
$this->init_document('json');
|
||||
$this->show_json_objects($twitter_user);
|
||||
$this->end_document('json');
|
||||
} else {
|
||||
|
||||
$faves = DB_DataObject::factory('fave');
|
||||
$faves->user_id = $user->id;
|
||||
$faves_count = (int) $faves->count();
|
||||
$twitter_user['favourites_count'] = $faves_count;
|
||||
|
||||
$timezone = 'UTC';
|
||||
|
||||
if ($user->timezone) {
|
||||
$timezone = $user->timezone;
|
||||
}
|
||||
|
||||
$t = new DateTime;
|
||||
$t->setTimezone(new DateTimeZone($timezone));
|
||||
$twitter_user['utc_offset'] = $t->format('Z');
|
||||
$twitter_user['time_zone'] = $timezone;
|
||||
|
||||
if (isset($apidata['user'])) {
|
||||
|
||||
$twitter_user['following'] = $apidata['user']->isSubscribed($profile);
|
||||
|
||||
// Notifications on?
|
||||
$sub = Subscription::pkeyGet(array('subscriber' =>
|
||||
$apidata['user']->id, 'subscribed' => $profile->id));
|
||||
|
||||
if ($sub) {
|
||||
$twitter_user['notifications'] = ($sub->jabber || $sub->sms);
|
||||
}
|
||||
}
|
||||
|
||||
if ($apidata['content-type'] == 'xml') {
|
||||
$this->init_document('xml');
|
||||
$this->show_twitter_xml_user($twitter_user);
|
||||
$this->end_document('xml');
|
||||
} elseif ($apidata['content-type'] == 'json') {
|
||||
$this->init_document('json');
|
||||
$this->show_json_objects($twitter_user);
|
||||
$this->end_document('json');
|
||||
} else {
|
||||
|
||||
// This is in case 'show' was called via /account/verify_credentials
|
||||
// without a format (xml or json).
|
||||
// This is in case 'show' was called via /account/verify_credentials
|
||||
// without a format (xml or json).
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
print 'Authorized';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ class Fave extends Memcached_DataObject
|
||||
return $ids;
|
||||
}
|
||||
|
||||
function _streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since)
|
||||
function _streamDirect($user_id, $offset, $limit, $since_id, $max_id, $since)
|
||||
{
|
||||
$fav = new Fave();
|
||||
|
||||
@ -59,8 +59,8 @@ class Fave extends Memcached_DataObject
|
||||
$fav->whereAdd('notice_id > ' . $since_id);
|
||||
}
|
||||
|
||||
if ($before_id != 0) {
|
||||
$fav->whereAdd('notice_id < ' . $before_id);
|
||||
if ($max_id != 0) {
|
||||
$fav->whereAdd('notice_id <= ' . $max_id);
|
||||
}
|
||||
|
||||
if (!is_null($since)) {
|
||||
|
@ -239,8 +239,14 @@ class Memcached_DataObject extends DB_DataObject
|
||||
$result = parent::_connect();
|
||||
if (!$exists) {
|
||||
$DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5];
|
||||
if (common_config('db', 'utf8')) {
|
||||
$DB->query('SET NAMES "utf8"');
|
||||
if (common_config('db', 'type') == 'mysql' &&
|
||||
common_config('db', 'utf8')) {
|
||||
$conn = $DB->connection;
|
||||
if ($DB instanceof DB_mysqli) {
|
||||
mysqli_set_charset($conn, 'utf8');
|
||||
} else if ($DB instanceof DB_mysql) {
|
||||
mysql_set_charset('utf8', $conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
|
@ -124,6 +124,8 @@ class Notice extends Memcached_DataObject
|
||||
|
||||
$profile = Profile::staticGet($profile_id);
|
||||
|
||||
$final = common_shorten_links($content);
|
||||
|
||||
if (!$profile) {
|
||||
common_log(LOG_ERR, 'Problem saving notice. Unknown user.');
|
||||
return _('Problem saving notice. Unknown user.');
|
||||
@ -134,7 +136,7 @@ class Notice extends Memcached_DataObject
|
||||
return _('Too many notices too fast; take a breather and post again in a few minutes.');
|
||||
}
|
||||
|
||||
if (common_config('site', 'dupelimit') > 0 && !Notice::checkDupes($profile_id, $content)) {
|
||||
if (common_config('site', 'dupelimit') > 0 && !Notice::checkDupes($profile_id, $final)) {
|
||||
common_log(LOG_WARNING, 'Dupe posting by profile #' . $profile_id . '; throttled.');
|
||||
return _('Too many duplicate messages too quickly; take a breather and post again in a few minutes.');
|
||||
}
|
||||
@ -165,8 +167,8 @@ class Notice extends Memcached_DataObject
|
||||
|
||||
$notice->reply_to = $reply_to;
|
||||
$notice->created = common_sql_now();
|
||||
$notice->content = $content;
|
||||
$notice->rendered = common_render_content($content, $notice);
|
||||
$notice->content = $final;
|
||||
$notice->rendered = common_render_content($final, $notice);
|
||||
$notice->source = $source;
|
||||
$notice->uri = $uri;
|
||||
|
||||
@ -202,13 +204,9 @@ class Notice extends Memcached_DataObject
|
||||
|
||||
$notice->saveReplies();
|
||||
$notice->saveTags();
|
||||
$notice->saveGroups();
|
||||
|
||||
if (common_config('queue', 'enabled')) {
|
||||
$notice->addToAuthorInbox();
|
||||
} else {
|
||||
$notice->addToInboxes();
|
||||
}
|
||||
$notice->addToInboxes();
|
||||
$notice->saveGroups();
|
||||
|
||||
$notice->query('COMMIT');
|
||||
|
||||
@ -218,13 +216,7 @@ class Notice extends Memcached_DataObject
|
||||
# Clear the cache for subscribed users, so they'll update at next request
|
||||
# XXX: someone clever could prepend instead of clearing the cache
|
||||
|
||||
if (common_config('memcached', 'enabled')) {
|
||||
if (common_config('queue', 'enabled')) {
|
||||
$notice->blowAuthorCaches();
|
||||
} else {
|
||||
$notice->blowCaches();
|
||||
}
|
||||
}
|
||||
$notice->blowCaches();
|
||||
|
||||
return $notice;
|
||||
}
|
||||
@ -297,17 +289,6 @@ class Notice extends Memcached_DataObject
|
||||
$this->blowGroupCache($blowLast);
|
||||
}
|
||||
|
||||
function blowAuthorCaches($blowLast=false)
|
||||
{
|
||||
// Clear the user's cache
|
||||
$cache = common_memcache();
|
||||
if (!empty($cache)) {
|
||||
$cache->delete(common_cache_key('notice_inbox:by_user:'.$this->profile_id));
|
||||
}
|
||||
$this->blowNoticeCache($blowLast);
|
||||
$this->blowPublicCache($blowLast);
|
||||
}
|
||||
|
||||
function blowGroupCache($blowLast=false)
|
||||
{
|
||||
$cache = common_memcache();
|
||||
@ -443,22 +424,22 @@ class Notice extends Memcached_DataObject
|
||||
# XXX: too many args; we need to move to named params or even a separate
|
||||
# class for notice streams
|
||||
|
||||
static function getStream($qry, $cachekey, $offset=0, $limit=20, $since_id=0, $before_id=0, $order=null, $since=null) {
|
||||
static function getStream($qry, $cachekey, $offset=0, $limit=20, $since_id=0, $max_id=0, $order=null, $since=null) {
|
||||
|
||||
if (common_config('memcached', 'enabled')) {
|
||||
|
||||
# Skip the cache if this is a since, since_id or before_id qry
|
||||
if ($since_id > 0 || $before_id > 0 || $since) {
|
||||
return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order, $since);
|
||||
# Skip the cache if this is a since, since_id or max_id qry
|
||||
if ($since_id > 0 || $max_id > 0 || $since) {
|
||||
return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $max_id, $order, $since);
|
||||
} else {
|
||||
return Notice::getCachedStream($qry, $cachekey, $offset, $limit, $order);
|
||||
}
|
||||
}
|
||||
|
||||
return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order, $since);
|
||||
return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $max_id, $order, $since);
|
||||
}
|
||||
|
||||
static function getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order, $since) {
|
||||
static function getStreamDirect($qry, $offset, $limit, $since_id, $max_id, $order, $since) {
|
||||
|
||||
$needAnd = false;
|
||||
$needWhere = true;
|
||||
@ -480,7 +461,7 @@ class Notice extends Memcached_DataObject
|
||||
$qry .= ' notice.id > ' . $since_id;
|
||||
}
|
||||
|
||||
if ($before_id > 0) {
|
||||
if ($max_id > 0) {
|
||||
|
||||
if ($needWhere) {
|
||||
$qry .= ' WHERE ';
|
||||
@ -489,7 +470,7 @@ class Notice extends Memcached_DataObject
|
||||
$qry .= ' AND ';
|
||||
}
|
||||
|
||||
$qry .= ' notice.id < ' . $before_id;
|
||||
$qry .= ' notice.id <= ' . $max_id;
|
||||
}
|
||||
|
||||
if ($since) {
|
||||
@ -647,17 +628,17 @@ class Notice extends Memcached_DataObject
|
||||
}
|
||||
}
|
||||
|
||||
function publicStream($offset=0, $limit=20, $since_id=0, $before_id=0, $since=null)
|
||||
function publicStream($offset=0, $limit=20, $since_id=0, $max_id=0, $since=null)
|
||||
{
|
||||
$ids = Notice::stream(array('Notice', '_publicStreamDirect'),
|
||||
array(),
|
||||
'public',
|
||||
$offset, $limit, $since_id, $before_id, $since);
|
||||
$offset, $limit, $since_id, $max_id, $since);
|
||||
|
||||
return Notice::getStreamByIds($ids);
|
||||
}
|
||||
|
||||
function _publicStreamDirect($offset=0, $limit=20, $since_id=0, $before_id=0, $since=null)
|
||||
function _publicStreamDirect($offset=0, $limit=20, $since_id=0, $max_id=0, $since=null)
|
||||
{
|
||||
$notice = new Notice();
|
||||
|
||||
@ -681,8 +662,8 @@ class Notice extends Memcached_DataObject
|
||||
$notice->whereAdd('id > ' . $since_id);
|
||||
}
|
||||
|
||||
if ($before_id != 0) {
|
||||
$notice->whereAdd('id < ' . $before_id);
|
||||
if ($max_id != 0) {
|
||||
$notice->whereAdd('id <= ' . $max_id);
|
||||
}
|
||||
|
||||
if (!is_null($since)) {
|
||||
@ -726,33 +707,6 @@ class Notice extends Memcached_DataObject
|
||||
return;
|
||||
}
|
||||
|
||||
function addToAuthorInbox()
|
||||
{
|
||||
$enabled = common_config('inboxes', 'enabled');
|
||||
|
||||
if ($enabled === true || $enabled === 'transitional') {
|
||||
$user = User::staticGet('id', $this->profile_id);
|
||||
if (empty($user)) {
|
||||
return;
|
||||
}
|
||||
$inbox = new Notice_inbox();
|
||||
$UT = common_config('db','type')=='pgsql'?'"user"':'user';
|
||||
$qry = 'INSERT INTO notice_inbox (user_id, notice_id, created) ' .
|
||||
"SELECT $UT.id, " . $this->id . ", '" . $this->created . "' " .
|
||||
"FROM $UT " .
|
||||
"WHERE $UT.id = " . $this->profile_id . ' ' .
|
||||
'AND NOT EXISTS (SELECT user_id, notice_id ' .
|
||||
'FROM notice_inbox ' .
|
||||
"WHERE user_id = " . $this->profile_id . ' '.
|
||||
'AND notice_id = ' . $this->id . ' )';
|
||||
if ($enabled === 'transitional') {
|
||||
$qry .= " AND $UT.inboxed = 1";
|
||||
}
|
||||
$inbox->query($qry);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function saveGroups()
|
||||
{
|
||||
$enabled = common_config('inboxes', 'enabled');
|
||||
@ -1024,15 +978,15 @@ class Notice extends Memcached_DataObject
|
||||
}
|
||||
}
|
||||
|
||||
function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $before_id=0, $since=null, $tag=null)
|
||||
function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $max_id=0, $since=null)
|
||||
{
|
||||
$cache = common_memcache();
|
||||
|
||||
if (empty($cache) ||
|
||||
$since_id != 0 || $before_id != 0 || !is_null($since) ||
|
||||
$since_id != 0 || $max_id != 0 || (!is_null($since) && $since > 0) ||
|
||||
($offset + $limit) > NOTICE_CACHE_WINDOW) {
|
||||
return call_user_func_array($fn, array_merge($args, array($offset, $limit, $since_id,
|
||||
$before_id, $since, $tag)));
|
||||
$max_id, $since)));
|
||||
}
|
||||
|
||||
$idkey = common_cache_key($cachekey);
|
||||
|
@ -43,15 +43,15 @@ class Notice_inbox extends Memcached_DataObject
|
||||
/* the code above is auto generated do not remove the tag below */
|
||||
###END_AUTOCODE
|
||||
|
||||
function stream($user_id, $offset, $limit, $since_id, $before_id, $since)
|
||||
function stream($user_id, $offset, $limit, $since_id, $max_id, $since)
|
||||
{
|
||||
return Notice::stream(array('Notice_inbox', '_streamDirect'),
|
||||
array($user_id),
|
||||
'notice_inbox:by_user:'.$user_id,
|
||||
$offset, $limit, $since_id, $before_id, $since);
|
||||
$offset, $limit, $since_id, $max_id, $since);
|
||||
}
|
||||
|
||||
function _streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since)
|
||||
function _streamDirect($user_id, $offset, $limit, $since_id, $max_id, $since)
|
||||
{
|
||||
$inbox = new Notice_inbox();
|
||||
|
||||
@ -61,8 +61,8 @@ class Notice_inbox extends Memcached_DataObject
|
||||
$inbox->whereAdd('notice_id > ' . $since_id);
|
||||
}
|
||||
|
||||
if ($before_id != 0) {
|
||||
$inbox->whereAdd('notice_id < ' . $before_id);
|
||||
if ($max_id != 0) {
|
||||
$inbox->whereAdd('notice_id <= ' . $max_id);
|
||||
}
|
||||
|
||||
if (!is_null($since)) {
|
||||
|
@ -46,7 +46,7 @@ class Notice_tag extends Memcached_DataObject
|
||||
return Notice::getStreamByIds($ids);
|
||||
}
|
||||
|
||||
function _streamDirect($tag, $offset, $limit, $since_id, $before_id, $since)
|
||||
function _streamDirect($tag, $offset, $limit, $since_id, $max_id, $since)
|
||||
{
|
||||
$nt = new Notice_tag();
|
||||
|
||||
@ -59,8 +59,8 @@ class Notice_tag extends Memcached_DataObject
|
||||
$nt->whereAdd('notice_id > ' . $since_id);
|
||||
}
|
||||
|
||||
if ($before_id != 0) {
|
||||
$nt->whereAdd('notice_id < ' . $before_id);
|
||||
if ($max_id != 0) {
|
||||
$nt->whereAdd('notice_id < ' . $max_id);
|
||||
}
|
||||
|
||||
if (!is_null($since)) {
|
||||
|
@ -170,7 +170,7 @@ class Profile extends Memcached_DataObject
|
||||
$ids = Notice::stream(array($this, '_streamDirect'),
|
||||
array(),
|
||||
'profile:notice_ids:' . $this->id,
|
||||
$offset, $limit, $since_id, $before_id, $since);
|
||||
$offset, $limit, $since_id, $max_id, $since);
|
||||
|
||||
return Notice::getStreamByIds($ids);
|
||||
}
|
||||
@ -225,8 +225,8 @@ class Profile extends Memcached_DataObject
|
||||
$notice->whereAdd('id > ' . $since_id);
|
||||
}
|
||||
|
||||
if ($before_id != 0) {
|
||||
$notice->whereAdd('id < ' . $before_id);
|
||||
if ($max_id != 0) {
|
||||
$notice->whereAdd('id <= ' . $max_id);
|
||||
}
|
||||
|
||||
if (!is_null($since)) {
|
||||
|
@ -22,16 +22,16 @@ class Reply extends Memcached_DataObject
|
||||
/* the code above is auto generated do not remove the tag below */
|
||||
###END_AUTOCODE
|
||||
|
||||
function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
|
||||
function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null)
|
||||
{
|
||||
$ids = Notice::stream(array('Reply', '_streamDirect'),
|
||||
array($user_id),
|
||||
'reply:stream:' . $user_id,
|
||||
$offset, $limit, $since_id, $before_id, $since);
|
||||
$offset, $limit, $since_id, $max_id, $since);
|
||||
return $ids;
|
||||
}
|
||||
|
||||
function _streamDirect($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
|
||||
function _streamDirect($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null)
|
||||
{
|
||||
$reply = new Reply();
|
||||
$reply->profile_id = $user_id;
|
||||
@ -40,8 +40,8 @@ class Reply extends Memcached_DataObject
|
||||
$reply->whereAdd('notice_id > ' . $since_id);
|
||||
}
|
||||
|
||||
if ($before_id != 0) {
|
||||
$reply->whereAdd('notice_id < ' . $before_id);
|
||||
if ($max_id != 0) {
|
||||
$reply->whereAdd('notice_id < ' . $max_id);
|
||||
}
|
||||
|
||||
if (!is_null($since)) {
|
||||
|
@ -403,7 +403,6 @@ class User extends Memcached_DataObject
|
||||
function getReplies($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
|
||||
{
|
||||
$ids = Reply::stream($this->id, $offset, $limit, $since_id, $before_id, $since);
|
||||
common_debug("Ids = " . implode(',', $ids));
|
||||
return Notice::getStreamByIds($ids);
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ class User_group extends Memcached_DataObject
|
||||
return Notice::getStreamByIds($ids);
|
||||
}
|
||||
|
||||
function _streamDirect($offset, $limit, $since_id, $before_id, $since)
|
||||
function _streamDirect($offset, $limit, $since_id, $max_id, $since)
|
||||
{
|
||||
$inbox = new Group_inbox();
|
||||
|
||||
@ -71,8 +71,8 @@ class User_group extends Memcached_DataObject
|
||||
$inbox->whereAdd('notice_id > ' . $since_id);
|
||||
}
|
||||
|
||||
if ($before_id != 0) {
|
||||
$inbox->whereAdd('notice_id < ' . $before_id);
|
||||
if ($max_id != 0) {
|
||||
$inbox->whereAdd('notice_id <= ' . $max_id);
|
||||
}
|
||||
|
||||
if (!is_null($since)) {
|
||||
|
@ -2,7 +2,9 @@ INSERT INTO notice_source
|
||||
(code, name, url, created)
|
||||
VALUES
|
||||
('adium', 'Adium', 'http://www.adiumx.com/', now()),
|
||||
('Afficheur', 'Afficheur', 'http://afficheur.sourceforge.jp/', now()),
|
||||
('AgentSolo.com','AgentSolo.com','http://www.agentsolo.com/', now()),
|
||||
('anyio', 'Any.IO', 'http://any.io/', now()),
|
||||
('betwittered','BeTwittered','http://www.32hours.com/betwitteredinfo/', now()),
|
||||
('bti','bti','http://gregkh.github.com/bti/', now()),
|
||||
('cliqset', 'Cliqset', 'http://www.cliqset.com/', now()),
|
||||
@ -11,6 +13,7 @@ VALUES
|
||||
('eventbox','EventBox','http://thecosmicmachine.com/eventbox/ ', now()),
|
||||
('Facebook','Facebook','http://apps.facebook.com/identica/', now()),
|
||||
('feed2omb','feed2omb','http://projects.ciarang.com/p/feed2omb/', now()),
|
||||
('get2gnow', 'get2gnow', 'http://uberchicgeekchick.com/?projects=get2gnow', now()),
|
||||
('gravity', 'Gravity', 'http://mobileways.de/gravity', now()),
|
||||
('Gwibber','Gwibber','http://launchpad.net/gwibber', now()),
|
||||
('HelloTxt','HelloTxt','http://hellotxt.com/', now()),
|
||||
|
@ -335,6 +335,7 @@ function mail_broadcast_notice_sms($notice)
|
||||
"FROM $UT JOIN subscription " .
|
||||
"ON $UT.id = subscription.subscriber " .
|
||||
'WHERE subscription.subscribed = ' . $notice->profile_id . ' ' .
|
||||
'AND subscription.subscribed != subscription.subscriber ' .
|
||||
"AND $UT.smsemail IS NOT null " .
|
||||
"AND $UT.smsnotify = 1 " .
|
||||
'AND subscription.sms = 1 ');
|
||||
|
10
lib/omb.php
10
lib/omb.php
@ -159,13 +159,9 @@ function omb_post_notice($notice, $remote_profile, $subscription)
|
||||
|
||||
function omb_post_notice_keys($notice, $postnoticeurl, $tk, $secret)
|
||||
{
|
||||
|
||||
common_debug('Posting notice ' . $notice->id . ' to ' . $postnoticeurl, __FILE__);
|
||||
|
||||
$user = User::staticGet('id', $notice->profile_id);
|
||||
|
||||
if (!$user) {
|
||||
common_debug('Failed to get user for notice ' . $notice->id . ', profile = ' . $notice->profile_id, __FILE__);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -208,8 +204,6 @@ function omb_post_notice_keys($notice, $postnoticeurl, $tk, $secret)
|
||||
$req->to_postdata(),
|
||||
array('User-Agent: Laconica/' . LACONICA_VERSION));
|
||||
|
||||
common_debug('Got HTTP result "'.print_r($result,true).'"', __FILE__);
|
||||
|
||||
if ($result->status == 403) { # not authorized, don't send again
|
||||
common_debug('403 result, deleting subscription', __FILE__);
|
||||
# FIXME: figure out how to delete this
|
||||
@ -286,14 +280,10 @@ function omb_update_profile($profile, $remote_profile, $subscription)
|
||||
|
||||
$fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
|
||||
|
||||
common_debug('request URL = '.$req->get_normalized_http_url(), __FILE__);
|
||||
common_debug('postdata = '.$req->to_postdata(), __FILE__);
|
||||
$result = $fetcher->post($req->get_normalized_http_url(),
|
||||
$req->to_postdata(),
|
||||
array('User-Agent: Laconica/' . LACONICA_VERSION));
|
||||
|
||||
common_debug('Got HTTP result "'.print_r($result,true).'"', __FILE__);
|
||||
|
||||
if (empty($result) || !$result) {
|
||||
common_debug("Unable to contact " . $req->get_normalized_http_url());
|
||||
} else if ($result->status == 403) { # not authorized, don't send again
|
||||
|
@ -54,7 +54,7 @@ class TwitterapiAction extends Action
|
||||
/**
|
||||
* Overrides XMLOutputter::element to write booleans as strings (true|false).
|
||||
* See that method's documentation for more info.
|
||||
*
|
||||
*
|
||||
* @param string $tag Element type or tagname
|
||||
* @param array $attrs Array of element attributes, as
|
||||
* key-value pairs
|
||||
@ -70,24 +70,85 @@ class TwitterapiAction extends Action
|
||||
|
||||
return parent::element($tag, $attrs, $content);
|
||||
}
|
||||
|
||||
|
||||
function twitter_user_array($profile, $get_notice=false)
|
||||
{
|
||||
|
||||
$twitter_user = array();
|
||||
|
||||
$twitter_user['name'] = $profile->getBestName();
|
||||
$twitter_user['followers_count'] = $this->count_subscriptions($profile);
|
||||
$twitter_user['screen_name'] = $profile->nickname;
|
||||
$twitter_user['description'] = ($profile->bio) ? $profile->bio : null;
|
||||
$twitter_user['location'] = ($profile->location) ? $profile->location : null;
|
||||
$twitter_user['id'] = intval($profile->id);
|
||||
$twitter_user['name'] = $profile->getBestName();
|
||||
$twitter_user['screen_name'] = $profile->nickname;
|
||||
$twitter_user['location'] = ($profile->location) ? $profile->location : null;
|
||||
$twitter_user['description'] = ($profile->bio) ? $profile->bio : null;
|
||||
|
||||
$avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
|
||||
$twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() :
|
||||
Avatar::defaultImage(AVATAR_STREAM_SIZE);
|
||||
|
||||
$twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE);
|
||||
$twitter_user['protected'] = false; # not supported by Laconica yet
|
||||
$twitter_user['url'] = ($profile->homepage) ? $profile->homepage : null;
|
||||
$twitter_user['protected'] = false; # not supported by Laconica yet
|
||||
$twitter_user['followers_count'] = $this->count_subscriptions($profile);
|
||||
|
||||
// To be supported soon...
|
||||
$twitter_user['profile_background_color'] = '';
|
||||
$twitter_user['profile_text_color'] = '';
|
||||
$twitter_user['profile_link_color'] = '';
|
||||
$twitter_user['profile_sidebar_fill_color'] = '';
|
||||
$twitter_user['profile_sidebar_border_color'] = '';
|
||||
|
||||
$subbed = DB_DataObject::factory('subscription');
|
||||
$subbed->subscriber = $profile->id;
|
||||
$subbed_count = (int) $subbed->count() - 1;
|
||||
$twitter_user['friends_count'] = (is_int($subbed_count)) ? $subbed_count : 0;
|
||||
|
||||
$twitter_user['created_at'] = $this->date_twitter($profile->created);
|
||||
|
||||
$faves = DB_DataObject::factory('fave');
|
||||
$faves->user_id = $user->id;
|
||||
$faves_count = (int) $faves->count();
|
||||
$twitter_user['favourites_count'] = $faves_count; // British spelling!
|
||||
|
||||
// Need to pull up the user for some of this
|
||||
$user = User::staticGet($profile->id);
|
||||
|
||||
$timezone = 'UTC';
|
||||
|
||||
if ($user->timezone) {
|
||||
$timezone = $user->timezone;
|
||||
}
|
||||
|
||||
$t = new DateTime;
|
||||
$t->setTimezone(new DateTimeZone($timezone));
|
||||
|
||||
$twitter_user['utc_offset'] = $t->format('Z');
|
||||
$twitter_user['time_zone'] = $timezone;
|
||||
|
||||
// To be supported some day, perhaps
|
||||
$twitter_user['profile_background_image_url'] = '';
|
||||
$twitter_user['profile_background_tile'] = false;
|
||||
|
||||
$notices = DB_DataObject::factory('notice');
|
||||
$notices->profile_id = $profile->id;
|
||||
$notice_count = (int) $notices->count();
|
||||
|
||||
$twitter_user['statuses_count'] = (is_int($notice_count)) ? $notice_count : 0;
|
||||
|
||||
// Is the requesting user following this user?
|
||||
$twitter_user['following'] = false;
|
||||
$twitter_user['notifications'] = false;
|
||||
|
||||
if (isset($apidata['user'])) {
|
||||
|
||||
$twitter_user['following'] = $apidata['user']->isSubscribed($profile);
|
||||
|
||||
// Notifications on?
|
||||
$sub = Subscription::pkeyGet(array('subscriber' =>
|
||||
$apidata['user']->id, 'subscribed' => $profile->id));
|
||||
|
||||
if ($sub) {
|
||||
$twitter_user['notifications'] = ($sub->jabber || $sub->sms);
|
||||
}
|
||||
}
|
||||
|
||||
if ($get_notice) {
|
||||
$notice = $profile->getCurrentNotice();
|
||||
@ -612,7 +673,27 @@ class TwitterapiAction extends Action
|
||||
function get_user($id, $apidata=null)
|
||||
{
|
||||
if (!$id) {
|
||||
return $apidata['user'];
|
||||
|
||||
// Twitter supports these other ways of passing the user ID
|
||||
if (is_numeric($this->arg('id'))) {
|
||||
return User::staticGet($this->arg('id'));
|
||||
} else if ($this->arg('id')) {
|
||||
$nickname = common_canonical_nickname($this->arg('id'));
|
||||
return User::staticGet('nickname', $nickname);
|
||||
} else if ($this->arg('user_id')) {
|
||||
// This is to ensure that a non-numeric user_id still
|
||||
// overrides screen_name even if it doesn't get used
|
||||
if (is_numeric($this->arg('user_id'))) {
|
||||
return User::staticGet('id', $this->arg('user_id'));
|
||||
}
|
||||
} else if ($this->arg('screen_name')) {
|
||||
$nickname = common_canonical_nickname($this->arg('screen_name'));
|
||||
return User::staticGet('nickname', $nickname);
|
||||
} else {
|
||||
// Fall back to trying the currently authenticated user
|
||||
return $apidata['user'];
|
||||
}
|
||||
|
||||
} else if (is_numeric($id)) {
|
||||
return User::staticGet($id);
|
||||
} else {
|
||||
|
28
lib/util.php
28
lib/util.php
@ -900,6 +900,34 @@ function common_enqueue_notice($notice)
|
||||
return $result;
|
||||
}
|
||||
|
||||
function common_post_inbox_transports()
|
||||
{
|
||||
$transports = array('omb', 'sms');
|
||||
|
||||
if (common_config('xmpp', 'enabled')) {
|
||||
$transports = array_merge($transports, array('jabber', 'public'));
|
||||
}
|
||||
|
||||
return $transports;
|
||||
}
|
||||
|
||||
function common_enqueue_notice_transport($notice, $transport)
|
||||
{
|
||||
$qi = new Queue_item();
|
||||
$qi->notice_id = $notice->id;
|
||||
$qi->transport = $transport;
|
||||
$qi->created = $notice->created;
|
||||
$result = $qi->insert();
|
||||
if (!$result) {
|
||||
$last_error = &PEAR::getStaticProperty('DB_DataObject','lastError');
|
||||
common_log(LOG_ERR, 'DB error inserting queue item: ' . $last_error->message);
|
||||
throw new ServerException('DB error inserting queue item: ' . $last_error->message);
|
||||
>>>>>>> 0.7.x:lib/util.php
|
||||
}
|
||||
common_log(LOG_DEBUG, 'complete queueing notice ID = ' . $notice->id . ' for ' . $transport);
|
||||
return true;
|
||||
}
|
||||
|
||||
function common_real_broadcast($notice, $remote=false)
|
||||
{
|
||||
$success = true;
|
||||
|
@ -35,107 +35,334 @@ define('LACONICA', true);
|
||||
require_once(INSTALLDIR . '/lib/common.php');
|
||||
require_once('DB.php');
|
||||
|
||||
function fixup_utf8($id) {
|
||||
class UTF8FixerUpper
|
||||
{
|
||||
var $dbl = null;
|
||||
var $dbu = null;
|
||||
var $args = array();
|
||||
|
||||
$dbl = doConnect('latin1');
|
||||
function __construct($args)
|
||||
{
|
||||
$this->args = $args;
|
||||
|
||||
if (empty($dbl)) {
|
||||
return;
|
||||
if (array_key_exists('max_date', $args)) {
|
||||
$this->max_date = strftime('%Y-%m-%d %H:%M:%S', strtotime($args['max_date']));
|
||||
} else {
|
||||
$this->max_date = strftime('%Y-%m-%d %H:%M:%S', time());
|
||||
}
|
||||
|
||||
$this->dbl = $this->doConnect('latin1');
|
||||
|
||||
if (empty($this->dbl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->dbu = $this->doConnect('utf8');
|
||||
|
||||
if (empty($this->dbu)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$dbu = doConnect('utf8');
|
||||
function doConnect($charset)
|
||||
{
|
||||
$db = DB::connect(common_config('db', 'database'),
|
||||
array('persistent' => false));
|
||||
|
||||
if (empty($dbu)) {
|
||||
return;
|
||||
}
|
||||
if (PEAR::isError($db)) {
|
||||
echo "ERROR: " . $db->getMessage() . "\n";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Do a separate DB connection
|
||||
$conn = $db->connection;
|
||||
|
||||
$sth = $dbu->prepare("UPDATE notice SET content = UNHEX(?), rendered = UNHEX(?) WHERE id = ?");
|
||||
$succ = mysqli_set_charset($conn, $charset);
|
||||
|
||||
if (PEAR::isError($sth)) {
|
||||
echo "ERROR: " . $sth->getMessage() . "\n";
|
||||
return;
|
||||
}
|
||||
if (!$succ) {
|
||||
echo "ERROR: couldn't set charset\n";
|
||||
$db->disconnect();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$sql = 'SELECT id, content, rendered FROM notice ' .
|
||||
'WHERE LENGTH(content) != CHAR_LENGTH(content)';
|
||||
|
||||
if (!empty($id)) {
|
||||
$sql .= ' AND id < ' . $id;
|
||||
}
|
||||
|
||||
$sql .= ' ORDER BY id DESC';
|
||||
|
||||
$rn = $dbl->query($sql);
|
||||
|
||||
if (PEAR::isError($rn)) {
|
||||
echo "ERROR: " . $rn->getMessage() . "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
echo "Number of rows: " . $rn->numRows() . "\n";
|
||||
|
||||
$notice = array();
|
||||
|
||||
while (DB_OK == $rn->fetchInto($notice)) {
|
||||
|
||||
$id = ($notice[0])+0;
|
||||
$content = bin2hex($notice[1]);
|
||||
$rendered = bin2hex($notice[2]);
|
||||
|
||||
echo "$id...";
|
||||
|
||||
$result =& $dbu->execute($sth, array($content, $rendered, $id));
|
||||
$result = $db->autoCommit(true);
|
||||
|
||||
if (PEAR::isError($result)) {
|
||||
echo "ERROR: " . $result->getMessage() . "\n";
|
||||
continue;
|
||||
$db->disconnect();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$cnt = $dbu->affectedRows();
|
||||
return $db;
|
||||
}
|
||||
|
||||
if ($cnt != 1) {
|
||||
echo "ERROR: 0 rows affected\n";
|
||||
continue;
|
||||
function fixup()
|
||||
{
|
||||
$this->fixupNotices($this->args['max_notice'],
|
||||
$this->args['min_notice']);
|
||||
$this->fixupProfiles();
|
||||
$this->fixupGroups();
|
||||
$this->fixupMessages();
|
||||
}
|
||||
|
||||
function fixupNotices($max_id, $min_id) {
|
||||
|
||||
// Do a separate DB connection
|
||||
|
||||
$sth = $this->dbu->prepare("UPDATE notice SET content = UNHEX(?), rendered = UNHEX(?) WHERE id = ?");
|
||||
|
||||
if (PEAR::isError($sth)) {
|
||||
echo "ERROR: " . $sth->getMessage() . "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$notice = Notice::staticGet('id', $id);
|
||||
$notice->decache();
|
||||
$sql = 'SELECT id, content, rendered FROM notice ' .
|
||||
'WHERE LENGTH(content) != CHAR_LENGTH(content) '.
|
||||
'AND modified < "'.$this->max_date.'" ';
|
||||
|
||||
echo "OK\n";
|
||||
if (!empty($max_id)) {
|
||||
$sql .= ' AND id <= ' . $max_id;
|
||||
}
|
||||
|
||||
if (!empty($min_id)) {
|
||||
$sql .= ' AND id >= ' . $min_id;
|
||||
}
|
||||
|
||||
$sql .= ' ORDER BY id DESC';
|
||||
|
||||
$rn = $this->dbl->query($sql);
|
||||
|
||||
if (PEAR::isError($rn)) {
|
||||
echo "ERROR: " . $rn->getMessage() . "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
echo "Number of rows: " . $rn->numRows() . "\n";
|
||||
|
||||
$notice = array();
|
||||
|
||||
while (DB_OK == $rn->fetchInto($notice)) {
|
||||
|
||||
$id = ($notice[0])+0;
|
||||
$content = bin2hex($notice[1]);
|
||||
$rendered = bin2hex($notice[2]);
|
||||
|
||||
echo "$id...";
|
||||
|
||||
$result =& $this->dbu->execute($sth, array($content, $rendered, $id));
|
||||
|
||||
if (PEAR::isError($result)) {
|
||||
echo "ERROR: " . $result->getMessage() . "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$cnt = $this->dbu->affectedRows();
|
||||
|
||||
if ($cnt != 1) {
|
||||
echo "ERROR: 0 rows affected\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$notice = Notice::staticGet('id', $id);
|
||||
$notice->decache();
|
||||
$notice->free();
|
||||
|
||||
echo "OK\n";
|
||||
}
|
||||
}
|
||||
|
||||
function fixupProfiles()
|
||||
{
|
||||
// Do a separate DB connection
|
||||
|
||||
$sth = $this->dbu->prepare("UPDATE profile SET ".
|
||||
"fullname = UNHEX(?),".
|
||||
"location = UNHEX(?), ".
|
||||
"bio = UNHEX(?) ".
|
||||
"WHERE id = ?");
|
||||
|
||||
if (PEAR::isError($sth)) {
|
||||
echo "ERROR: " . $sth->getMessage() . "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$sql = 'SELECT id, fullname, location, bio FROM profile ' .
|
||||
'WHERE (LENGTH(fullname) != CHAR_LENGTH(fullname) '.
|
||||
'OR LENGTH(location) != CHAR_LENGTH(location) '.
|
||||
'OR LENGTH(bio) != CHAR_LENGTH(bio)) '.
|
||||
'AND modified < "'.$this->max_date.'" '.
|
||||
' ORDER BY modified DESC';
|
||||
|
||||
$rn = $this->dbl->query($sql);
|
||||
|
||||
if (PEAR::isError($rn)) {
|
||||
echo "ERROR: " . $rn->getMessage() . "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
echo "Number of rows: " . $rn->numRows() . "\n";
|
||||
|
||||
$profile = array();
|
||||
|
||||
while (DB_OK == $rn->fetchInto($profile)) {
|
||||
|
||||
$id = ($profile[0])+0;
|
||||
$fullname = bin2hex($profile[1]);
|
||||
$location = bin2hex($profile[2]);
|
||||
$bio = bin2hex($profile[3]);
|
||||
|
||||
echo "$id...";
|
||||
|
||||
$result =& $this->dbu->execute($sth, array($fullname, $location, $bio, $id));
|
||||
|
||||
if (PEAR::isError($result)) {
|
||||
echo "ERROR: " . $result->getMessage() . "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$cnt = $this->dbu->affectedRows();
|
||||
|
||||
if ($cnt != 1) {
|
||||
echo "ERROR: 0 rows affected\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$profile = Profile::staticGet('id', $id);
|
||||
$profile->decache();
|
||||
$profile->free();
|
||||
|
||||
echo "OK\n";
|
||||
}
|
||||
}
|
||||
|
||||
function fixupGroups()
|
||||
{
|
||||
// Do a separate DB connection
|
||||
|
||||
$sth = $this->dbu->prepare("UPDATE user_group SET ".
|
||||
"fullname = UNHEX(?),".
|
||||
"location = UNHEX(?), ".
|
||||
"description = UNHEX(?) ".
|
||||
"WHERE id = ?");
|
||||
|
||||
if (PEAR::isError($sth)) {
|
||||
echo "ERROR: " . $sth->getMessage() . "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$sql = 'SELECT id, fullname, location, description FROM user_group ' .
|
||||
'WHERE LENGTH(fullname) != CHAR_LENGTH(fullname) '.
|
||||
'OR LENGTH(location) != CHAR_LENGTH(location) '.
|
||||
'OR LENGTH(description) != CHAR_LENGTH(description) ';
|
||||
'AND modified < "'.$this->max_date.'" '.
|
||||
'ORDER BY modified DESC';
|
||||
|
||||
$rn = $this->dbl->query($sql);
|
||||
|
||||
if (PEAR::isError($rn)) {
|
||||
echo "ERROR: " . $rn->getMessage() . "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
echo "Number of rows: " . $rn->numRows() . "\n";
|
||||
|
||||
$user_group = array();
|
||||
|
||||
while (DB_OK == $rn->fetchInto($user_group)) {
|
||||
|
||||
$id = ($user_group[0])+0;
|
||||
$fullname = bin2hex($user_group[1]);
|
||||
$location = bin2hex($user_group[2]);
|
||||
$description = bin2hex($user_group[3]);
|
||||
|
||||
echo "$id...";
|
||||
|
||||
$result =& $this->dbu->execute($sth, array($fullname, $location, $description, $id));
|
||||
|
||||
if (PEAR::isError($result)) {
|
||||
echo "ERROR: " . $result->getMessage() . "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$cnt = $this->dbu->affectedRows();
|
||||
|
||||
if ($cnt != 1) {
|
||||
echo "ERROR: 0 rows affected\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$user_group = User_group::staticGet('id', $id);
|
||||
$user_group->decache();
|
||||
$user_group->free();
|
||||
|
||||
echo "OK\n";
|
||||
}
|
||||
}
|
||||
|
||||
function fixupMessages() {
|
||||
|
||||
// Do a separate DB connection
|
||||
|
||||
$sth = $this->dbu->prepare("UPDATE message SET content = UNHEX(?), rendered = UNHEX(?) WHERE id = ?");
|
||||
|
||||
if (PEAR::isError($sth)) {
|
||||
echo "ERROR: " . $sth->getMessage() . "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$sql = 'SELECT id, content, rendered FROM message ' .
|
||||
'WHERE LENGTH(content) != CHAR_LENGTH(content) '.
|
||||
'AND modified < "'.$this->max_date.'" '.
|
||||
'ORDER BY id DESC';
|
||||
|
||||
$rn = $this->dbl->query($sql);
|
||||
|
||||
if (PEAR::isError($rn)) {
|
||||
echo "ERROR: " . $rn->getMessage() . "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
echo "Number of rows: " . $rn->numRows() . "\n";
|
||||
|
||||
$message = array();
|
||||
|
||||
while (DB_OK == $rn->fetchInto($message)) {
|
||||
|
||||
$id = ($message[0])+0;
|
||||
$content = bin2hex($message[1]);
|
||||
$rendered = bin2hex($message[2]);
|
||||
|
||||
echo "$id...";
|
||||
|
||||
$result =& $this->dbu->execute($sth, array($content, $rendered, $id));
|
||||
|
||||
if (PEAR::isError($result)) {
|
||||
echo "ERROR: " . $result->getMessage() . "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$cnt = $this->dbu->affectedRows();
|
||||
|
||||
if ($cnt != 1) {
|
||||
echo "ERROR: 0 rows affected\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$message = Message::staticGet('id', $id);
|
||||
$message->decache();
|
||||
$message->free();
|
||||
|
||||
echo "OK\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doConnect($charset)
|
||||
{
|
||||
$db = DB::connect(common_config('db', 'database'),
|
||||
array('persistent' => false));
|
||||
$max_date = ($argc > 1) ? $argv[1] : null;
|
||||
$max_id = ($argc > 2) ? $argv[2] : null;
|
||||
$min_id = ($argc > 3) ? $argv[3] : null;
|
||||
|
||||
if (PEAR::isError($db)) {
|
||||
echo "ERROR: " . $db->getMessage() . "\n";
|
||||
return NULL;
|
||||
}
|
||||
$fixer = new UTF8FixerUpper(array('max_date' => $max_date,
|
||||
'max_notice' => $max_id,
|
||||
'min_notice' => $min_id));
|
||||
|
||||
$result = $db->query("SET NAMES $charset");
|
||||
$fixer->fixup();
|
||||
|
||||
if (PEAR::isError($result)) {
|
||||
echo "ERROR: " . $result->getMessage() . "\n";
|
||||
$db->disconnect();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$result = $db->autoCommit(true);
|
||||
|
||||
if (PEAR::isError($result)) {
|
||||
echo "ERROR: " . $result->getMessage() . "\n";
|
||||
$db->disconnect();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return $db;
|
||||
}
|
||||
|
||||
$id = ($argc > 1) ? $argv[1] : null;
|
||||
|
||||
fixup_utf8($id);
|
||||
|
@ -25,7 +25,6 @@
|
||||
* daemon names.
|
||||
*/
|
||||
|
||||
|
||||
# Abort if called from a web server
|
||||
if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
|
||||
print "This script must be run from the command line\n";
|
||||
@ -51,5 +50,4 @@ echo "ombqueuehandler.php ";
|
||||
echo "twitterqueuehandler.php ";
|
||||
echo "facebookqueuehandler.php ";
|
||||
echo "pingqueuehandler.php ";
|
||||
echo "inboxqueuehandler.php ";
|
||||
echo "smsqueuehandler.php ";
|
||||
|
@ -1,69 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/*
|
||||
* Laconica - a distributed open-source microblogging tool
|
||||
* Copyright (C) 2008,2009 Control Yourself, Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// Abort if called from a web server
|
||||
|
||||
if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
|
||||
print "This script must be run from the command line\n";
|
||||
exit();
|
||||
}
|
||||
|
||||
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
|
||||
define('LACONICA', true);
|
||||
|
||||
require_once(INSTALLDIR . '/lib/common.php');
|
||||
require_once(INSTALLDIR . '/lib/queuehandler.php');
|
||||
|
||||
set_error_handler('common_error_handler');
|
||||
|
||||
class InboxQueueHandler extends QueueHandler
|
||||
{
|
||||
function transport()
|
||||
{
|
||||
return 'inbox';
|
||||
}
|
||||
|
||||
function start() {
|
||||
$this->log(LOG_INFO, "INITIALIZE");
|
||||
return true;
|
||||
}
|
||||
|
||||
function handle_notice($notice)
|
||||
{
|
||||
$this->log(LOG_INFO, "Distributing notice to inboxes for $notice->id");
|
||||
$notice->addToInboxes();
|
||||
$notice->blowSubsCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
function finish() {
|
||||
}
|
||||
}
|
||||
|
||||
ini_set("max_execution_time", "0");
|
||||
ini_set("max_input_time", "0");
|
||||
set_time_limit(0);
|
||||
mb_internal_encoding('UTF-8');
|
||||
|
||||
$id = ($argc > 1) ? $argv[1] : null;
|
||||
|
||||
$handler = new InboxQueueHandler($id);
|
||||
|
||||
$handler->runOnce();
|
@ -1,70 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/*
|
||||
* Laconica - a distributed open-source microblogging tool
|
||||
* Copyright (C) 2008,2009 Control Yourself, Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// Abort if called from a web server
|
||||
|
||||
if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
|
||||
print "This script must be run from the command line\n";
|
||||
exit();
|
||||
}
|
||||
|
||||
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
|
||||
define('LACONICA', true);
|
||||
|
||||
require_once(INSTALLDIR . '/lib/common.php');
|
||||
require_once(INSTALLDIR . '/lib/queuehandler.php');
|
||||
|
||||
set_error_handler('common_error_handler');
|
||||
|
||||
class MemcachedQueueHandler extends QueueHandler
|
||||
{
|
||||
function transport()
|
||||
{
|
||||
return 'memcache';
|
||||
}
|
||||
|
||||
function start() {
|
||||
$this->log(LOG_INFO, "INITIALIZE");
|
||||
return true;
|
||||
}
|
||||
|
||||
function handle_notice($notice)
|
||||
{
|
||||
// XXX: fork here
|
||||
$this->log(LOG_INFO, "Blowing memcached for $notice->id");
|
||||
$notice->blowCaches();
|
||||
return true;
|
||||
}
|
||||
|
||||
function finish() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ini_set("max_execution_time", "0");
|
||||
ini_set("max_input_time", "0");
|
||||
set_time_limit(0);
|
||||
mb_internal_encoding('UTF-8');
|
||||
|
||||
$id = ($argc > 1) ? $argv[1] : null;
|
||||
|
||||
$handler = new MemcachedQueueHandler($id);
|
||||
|
||||
$handler->runOnce();
|
@ -24,8 +24,7 @@ SDIR=`dirname $0`
|
||||
DIR=`php $SDIR/getpiddir.php`
|
||||
|
||||
for f in jabberhandler ombhandler publichandler smshandler pinghandler \
|
||||
xmppconfirmhandler xmppdaemon twitterhandler facebookhandler \
|
||||
memcachehandler inboxhandler twitterstatusfetcher; do
|
||||
xmppconfirmhandler xmppdaemon twitterhandler facebookhandler; do
|
||||
|
||||
FILES="$DIR/$f.*.pid"
|
||||
for ff in "$FILES" ; do
|
||||
|
Loading…
Reference in New Issue
Block a user