From 3081b2e31708520e6ed83041ce3ba04329d3ec90 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 16 Apr 2009 08:44:48 -0400 Subject: [PATCH 01/22] start of querybyid --- classes/User.php | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/classes/User.php b/classes/User.php index 3b9b5cd839..098381f738 100644 --- a/classes/User.php +++ b/classes/User.php @@ -444,21 +444,42 @@ class User extends Memcached_DataObject 'SELECT notice.* ' . 'FROM notice JOIN subscription ON notice.profile_id = subscription.subscribed ' . 'WHERE subscription.subscriber = %d '; - $order = null; + return Notice::getStream(sprintf($qry, $this->id), + 'user:notices_with_friends:' . $this->id, + $offset, $limit, $since_id, $before_id, + $order, $since); } else if ($enabled === true || ($enabled == 'transitional' && $this->inboxed == 1)) { - $qry = - 'SELECT notice.* ' . - 'FROM notice JOIN notice_inbox ON notice.id = notice_inbox.notice_id ' . - 'WHERE notice_inbox.user_id = %d '; - // NOTE: we override ORDER - $order = null; + $cache = common_memcache(); + + if (!empty($cache)) { + + # Get the notices out of the cache + + $notices = $cache->get(common_cache_key($cachekey)); + + # On a cache hit, return a DB-object-like wrapper + + if ($notices !== false) { + $wrapper = new ArrayWrapper(array_slice($notices, $offset, $limit)); + return $wrapper; + } + } + + $inbox = Notice_inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since); + + $ids = array(); + + while ($inbox->fetch()) { + $ids[] = $inbox->notice_id; + } + + $inbox->free(); + unset($inbox); + + return Notice::getStreamByIds($ids, 'user:notices_with_friends:' . $this->id); } - return Notice::getStream(sprintf($qry, $this->id), - 'user:notices_with_friends:' . $this->id, - $offset, $limit, $since_id, $before_id, - $order, $since); } function blowFavesCache() From 12867d114d8d40bf9a45b3e1eb9b0e50d736d333 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 24 Apr 2009 17:22:43 +0000 Subject: [PATCH 02/22] UI for server errors. --- js/util.js | 15 +++------------ theme/base/css/display.css | 11 +++++++++-- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/js/util.js b/js/util.js index 16422df579..15a14625c7 100644 --- a/js/util.js +++ b/js/util.js @@ -166,23 +166,14 @@ $(document).ready(function(){ $("#notice_action-submit").addClass("disabled"); return true; }, - timeout: 7000, error: function (xhr, textStatus, errorThrown) { $("#form_notice").removeClass("processing"); $("#notice_action-submit").removeAttr("disabled"); $("#notice_action-submit").removeClass("disabled"); - - if (textStatus == "timeout") { - alert ("Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists"); + if ($(".error", xhr.responseXML).length > 0) { + $('#form_notice').append(document._importNode($(".error", xhr.responseXML).get(0), true)); } else { - switch(xhr.status) { - default: case 404: - alert("Sorry! We had trouble sending your notice. Please report the problem to the site administrator if this happens again."); - break; - case 502: case 503: case 504: - alert("Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists."); - break; - } + alert("Sorry! We had trouble sending your notice ("+xhr.status+" "+xhr.statusText+"). Please report the problem to the site administrator if this happens again."); } }, success: function(xml) { if ($("#error", xml).length > 0) { diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 2fb1c007fc..0bc2e68b65 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -86,7 +86,7 @@ border:0; .error, .success { -padding:4px 7px; +padding:4px 1.55%; border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px; @@ -426,6 +426,7 @@ line-height:1; #form_notice fieldset { border:0; padding:0; +position:relative; } #form_notice legend { display:none; @@ -480,7 +481,13 @@ margin-bottom:7px; margin-left:18px; float:left; } - +#form_notice .error { +float:left; +clear:both; +width:96.9%; +margin-bottom:0; +line-height:1.618; +} /* entity_profile */ .entity_profile { From ecb09fb8646def7f6a7c5fc0fc2d4df6676edd06 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 24 Apr 2009 13:31:03 -0400 Subject: [PATCH 03/22] check for existence of xmlrpc extension in LinkbackPlugin --- plugins/LinkbackPlugin.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/LinkbackPlugin.php b/plugins/LinkbackPlugin.php index 881ead99ec..93a0294c4c 100644 --- a/plugins/LinkbackPlugin.php +++ b/plugins/LinkbackPlugin.php @@ -121,6 +121,12 @@ class LinkbackPlugin extends Plugin { $args = array($this->notice->uri, $url); + if (!extension_loaded('xmlrpc')) { + if (!dl('xmlrpc.so')) { + common_log(LOG_ERR, "Can't pingback; xmlrpc extension not available."); + } + } + $request = xmlrpc_encode_request('pingback.ping', $args); $context = stream_context_create(array('http' => array('method' => "POST", 'header' => @@ -141,7 +147,7 @@ class LinkbackPlugin extends Plugin } // Largely cadged from trackback_cls.php by - // Ran Aroussi , GPL2 + // Ran Aroussi , GPL2 or any later version // http://phptrackback.sourceforge.net/ function getTrackback($text, $url) From c008c0d4a56ec265ba6e10d208f9954510296f12 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 24 Apr 2009 20:01:03 +0000 Subject: [PATCH 04/22] fixed trac#1215, 1216, 1217 and 1219: subscribers/subscriptions people tagclouds. --- lib/subpeopletagcloudsection.php | 1 + lib/subscriberspeopleselftagcloudsection.php | 10 +++++++++- lib/subscriberspeopletagcloudsection.php | 5 +++-- lib/subscriptionspeopleselftagcloudsection.php | 9 ++++++++- lib/subscriptionspeopletagcloudsection.php | 4 +++- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lib/subpeopletagcloudsection.php b/lib/subpeopletagcloudsection.php index d98f28afa7..9f6948dc92 100644 --- a/lib/subpeopletagcloudsection.php +++ b/lib/subpeopletagcloudsection.php @@ -74,3 +74,4 @@ class SubPeopleTagCloudSection extends TagCloudSection $this->out->elementEnd('li'); } } + diff --git a/lib/subscriberspeopleselftagcloudsection.php b/lib/subscriberspeopleselftagcloudsection.php index b5a39c6de6..115241a53f 100644 --- a/lib/subscriberspeopleselftagcloudsection.php +++ b/lib/subscriberspeopleselftagcloudsection.php @@ -49,6 +49,14 @@ class SubscribersPeopleSelfTagCloudSection extends SubPeopleTagCloudSection } function query() { - return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged group by tag order by weight desc'; +// return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged group by tag order by weight desc'; + + + return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; + +// return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscribed where subscriber=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; + + } } + diff --git a/lib/subscriberspeopletagcloudsection.php b/lib/subscriberspeopletagcloudsection.php index 23011efdd3..4dafbc1c7d 100644 --- a/lib/subscriberspeopletagcloudsection.php +++ b/lib/subscriberspeopletagcloudsection.php @@ -53,8 +53,9 @@ class SubscribersPeopleTagCloudSection extends SubPeopleTagCloudSection return common_local_url('subscribers', array('nickname' => $nickname, 'tag' => $tag)); } - function query() { - return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed group by tag order by weight desc'; +// return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed group by tag order by weight desc'; + return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed and tag is not null group by tag order by weight desc'; } } + diff --git a/lib/subscriptionspeopleselftagcloudsection.php b/lib/subscriptionspeopleselftagcloudsection.php index 8ac65adb05..3896294d28 100644 --- a/lib/subscriptionspeopleselftagcloudsection.php +++ b/lib/subscriptionspeopleselftagcloudsection.php @@ -49,6 +49,13 @@ class SubscriptionsPeopleSelfTagCloudSection extends SubPeopleTagCloudSection } function query() { - return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscriber != subscribed and tagger = tagged group by tag order by weight desc'; +// return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscriber != subscribed and tagger = tagged group by tag order by weight desc'; + + + + return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscribed where subscriber=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; + +// return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; } } + diff --git a/lib/subscriptionspeopletagcloudsection.php b/lib/subscriptionspeopletagcloudsection.php index c3f7d1763e..f9c8672e36 100644 --- a/lib/subscriptionspeopletagcloudsection.php +++ b/lib/subscriptionspeopletagcloudsection.php @@ -54,6 +54,8 @@ class SubscriptionsPeopleTagCloudSection extends SubPeopleTagCloudSection } function query() { - return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed group by tag order by weight desc'; +// return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed group by tag order by weight desc'; + return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed and tag is not null group by tag order by weight desc'; } } + From d71fbe9d9693cd5426be74807ff8f18fc6376c56 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 24 Apr 2009 20:28:39 +0000 Subject: [PATCH 05/22] fixed subscriptions dropdown action --- lib/galleryaction.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/galleryaction.php b/lib/galleryaction.php index 0484918ce2..8fa11a7562 100644 --- a/lib/galleryaction.php +++ b/lib/galleryaction.php @@ -134,9 +134,11 @@ class GalleryAction extends Action $this->elementStart('li', array('id'=>'filter_tags_item')); $this->elementStart('form', array('name' => 'bytag', 'id' => 'bytag', + 'action' => common_path('?action=' . $this->trimmed('action')), 'method' => 'post')); $this->dropdown('tag', _('Tag'), $content, _('Choose a tag to narrow list'), false, $tag); + $this->hidden('nickname', $this->user->nickname); $this->submit('submit', _('Go')); $this->elementEnd('form'); $this->elementEnd('li'); @@ -169,4 +171,4 @@ class GalleryAction extends Action { return array(); } -} \ No newline at end of file +} From 84072aa5cf6124d59a06a7f0a7945c00ee2836da Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 26 Apr 2009 12:13:49 -0400 Subject: [PATCH 06/22] run 'set names' after each connection to deal with UTF8 correctly --- classes/Memcached_DataObject.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 5f71f716b3..877bbf2e0f 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -227,4 +227,20 @@ class Memcached_DataObject extends DB_DataObject $c->set($ckey, $cached, MEMCACHE_COMPRESSED, $expiry); return new ArrayWrapper($cached); } + + // We overload so that 'SET NAMES "utf8"' is called for + // each connection + + function _connect() + { + global $_DB_DATAOBJECT; + $exists = !empty($this->_database_dsn_md5) && + isset($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]); + $result = parent::_connect(); + if (!$exists) { + $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]; + $DB->query('SET NAMES "utf8"'); + } + return $result; + } } From 068f6801cc59488bfc50ef399a2a4d22b1b7e9c2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 26 Apr 2009 12:27:32 -0400 Subject: [PATCH 07/22] Revert "run 'set names' after each connection to deal with UTF8 correctly" This reverts commit 84072aa5cf6124d59a06a7f0a7945c00ee2836da. This commit caused grievous harm to old notices on identi.ca. Reverting until we figure out how to convert the old notices. --- classes/Memcached_DataObject.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 877bbf2e0f..5f71f716b3 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -227,20 +227,4 @@ class Memcached_DataObject extends DB_DataObject $c->set($ckey, $cached, MEMCACHE_COMPRESSED, $expiry); return new ArrayWrapper($cached); } - - // We overload so that 'SET NAMES "utf8"' is called for - // each connection - - function _connect() - { - global $_DB_DATAOBJECT; - $exists = !empty($this->_database_dsn_md5) && - isset($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]); - $result = parent::_connect(); - if (!$exists) { - $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]; - $DB->query('SET NAMES "utf8"'); - } - return $result; - } } From 7405d9dfa684975309150537069a1268a67ed6be Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 26 Apr 2009 21:16:09 -0400 Subject: [PATCH 08/22] Don't add a node if it's already there Try not to double-add a node on Ajax submit. Normally not a big deal, but may happen if the CometPlugin (or in the future Strophe or other auto-update plugins) is enabled. --- js/util.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/js/util.js b/js/util.js index 15a14625c7..f15c4f2bbf 100644 --- a/js/util.js +++ b/js/util.js @@ -188,11 +188,15 @@ $(document).ready(function(){ alert(result); } else { - $("#notices_primary .notices").prepend(document._importNode($("li", xml).get(0), true)); - $("#notices_primary .notice:first").css({display:"none"}); - $("#notices_primary .notice:first").fadeIn(2500); - NoticeHover(); - NoticeReply(); + li = $("li", xml).get(0); + id = li.id; + if ($("#"+li.id).length == 0) { + $("#notices_primary .notices").prepend(document._importNode(li, true)); + $("#notices_primary .notice:first").css({display:"none"}); + $("#notices_primary .notice:first").fadeIn(2500); + NoticeHover(); + NoticeReply(); + } } $("#notice_data-text").val(""); counter(); From efe8c47d7d9e91eb8308845b8b0717e84e36e346 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 27 Apr 2009 20:07:22 +0000 Subject: [PATCH 09/22] Minor CSS order/cleanup. --- theme/base/css/display.css | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 0bc2e68b65..dc6b4bc29a 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -842,23 +842,6 @@ text-transform:lowercase; } - -.notice-data { -position:absolute; -top:18px; -right:0; -min-height:50px; -margin-bottom:4px; -} -.notice .entry-content .notice-data dt { -display:none; -} - -.notice-data a { -display:block; -outline:none; -} - .notice-options { padding-left:2%; float:left; @@ -1036,6 +1019,8 @@ padding-right:30px; .hentry .entry-content p { margin-bottom:18px; } +.system_notice ul, +.instructions ul, .hentry entry-content ol, .hentry .entry-content ul { list-style-position:inside; @@ -1160,9 +1145,6 @@ clear:both; margin-bottom:0; } -.instructions ul { -list-style-position:inside; -} .instructions p, .instructions ul { margin-bottom:18px; From 6a20ef71d3b2b325ce24318e2ba4483d6c8732ce Mon Sep 17 00:00:00 2001 From: CiaranG Date: Tue, 28 Apr 2009 13:05:48 +0100 Subject: [PATCH 10/22] Fixed typo in stopdaemons.sh - was not stopping the new memcached queue handler --- scripts/stopdaemons.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/stopdaemons.sh b/scripts/stopdaemons.sh index 196991de0f..f6d71eddfb 100755 --- a/scripts/stopdaemons.sh +++ b/scripts/stopdaemons.sh @@ -25,7 +25,7 @@ DIR=`php $SDIR/getpiddir.php` for f in jabberhandler ombhandler publichandler smshandler pinghandler \ xmppconfirmhandler xmppdaemon twitterhandler facebookhandler \ - memcachedhandler inboxhandler; do + memcachehandler inboxhandler; do FILES="$DIR/$f.*.pid" for ff in "$FILES" ; do From 5b78f95e972f9f19ea46607e8b9544b8f7c4207a Mon Sep 17 00:00:00 2001 From: CiaranG Date: Tue, 28 Apr 2009 13:30:54 +0100 Subject: [PATCH 11/22] Only start daemons that are required, according to the site config. There is the potential to not start some more - see the checks in getvaliddaemons.php --- scripts/getvaliddaemons.php | 52 +++++++++++++++++++++++++++++++++++++ scripts/startdaemons.sh | 6 ++--- 2 files changed, 54 insertions(+), 4 deletions(-) create mode 100755 scripts/getvaliddaemons.php diff --git a/scripts/getvaliddaemons.php b/scripts/getvaliddaemons.php new file mode 100755 index 0000000000..482e63af70 --- /dev/null +++ b/scripts/getvaliddaemons.php @@ -0,0 +1,52 @@ +#!/usr/bin/env php +. + */ + +/** + * Utility script to get a list of daemons that should run, based on the + * current configuration. This is used by startdaemons.sh to determine what + * it should and shouldn't start up. The output is a list of space-separated + * 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"; + exit(); +} + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); +define('LACONICA', true); + +require_once(INSTALLDIR . '/lib/common.php'); + +if(common_config('xmpp','enabled')) { + echo "xmppdaemon.php jabberqueuehandler.php publicqueuehandler.php "; + echo "xmppconfirmhandler.php "; +} +if(common_config('memcached','enabled')) { + echo "memcachedqueuehandler.php "; +} +echo "ombqueuehandler.php "; +echo "twitterqueuehandler.php "; +echo "facebookqueuehandler.php "; +echo "pingqueuehandler.php "; +echo "inboxqueuehandler.php "; +echo "smsqueuehandler.php "; diff --git a/scripts/startdaemons.sh b/scripts/startdaemons.sh index 66f9ed4e0c..3869e95c4c 100755 --- a/scripts/startdaemons.sh +++ b/scripts/startdaemons.sh @@ -21,11 +21,9 @@ # Note that the 'maildaemon' needs to run as a mail filter. DIR=`dirname $0` +DAEMONS=`php $DIR/getvaliddaemons.php` -for f in xmppdaemon.php jabberqueuehandler.php publicqueuehandler.php \ - xmppconfirmhandler.php smsqueuehandler.php ombqueuehandler.php \ - twitterqueuehandler.php facebookqueuehandler.php pingqueuehandler.php \ - memcachedqueuehandler.php inboxqueuehandler.php; do +for f in $DAEMONS; do echo -n "Starting $f..."; php $DIR/$f From c7105c2af1ebe3cddd477265c6fea59a61d0c7e5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 28 Apr 2009 13:07:05 -0400 Subject: [PATCH 12/22] Change to avoid a join in notice inbox The join in notice_inbox is causing temp-table sorting on identi.ca, so I'm trying a finer-tuned approach. --- classes/Notice.php | 31 ++++++++++-- classes/Notice_inbox.php | 101 ++++++++++++++++++++++++++++++++++++++- classes/User.php | 29 +---------- 3 files changed, 127 insertions(+), 34 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 27b98de1cc..b087c94bc4 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -215,6 +215,7 @@ class Notice extends Memcached_DataObject if (common_config('queue', 'enabled')) { $notice->blowAuthorCaches(); } else { + common_debug("Blowing caches for new notice."); $notice->blowCaches(); } } @@ -285,7 +286,7 @@ class Notice extends Memcached_DataObject // Clear the user's cache $cache = common_memcache(); if (!empty($cache)) { - $cache->delete(common_cache_key('user:notices_with_friends:' . $this->profile_id)); + $cache->delete(common_cache_key('notice_inbox:by_user:'.$this->profile_id)); } $this->blowNoticeCache($blowLast); $this->blowPublicCache($blowLast); @@ -307,9 +308,9 @@ class Notice extends Memcached_DataObject $member->group_id = $group_inbox->group_id; if ($member->find()) { while ($member->fetch()) { - $cache->delete(common_cache_key('user:notices_with_friends:' . $member->profile_id)); + $cache->delete(common_cache_key('notice_inbox:by_user:' . $member->profile_id)); if ($blowLast) { - $cache->delete(common_cache_key('user:notices_with_friends:' . $member->profile_id . ';last')); + $cache->delete(common_cache_key('notice_inbox:by_user:' . $member->profile_id . ';last')); } } } @@ -352,9 +353,9 @@ class Notice extends Memcached_DataObject 'WHERE subscription.subscribed = ' . $this->profile_id); while ($user->fetch()) { - $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id)); + $cache->delete(common_cache_key('notice_inbox:by_user:'.$user_id)); if ($blowLast) { - $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id . ';last')); + $cache->delete(common_cache_key('notice_inbox:by_user:'.$user_id.';last')); } } $user->free(); @@ -613,6 +614,26 @@ class Notice extends Memcached_DataObject return $wrapper; } + function getStreamByIds($ids) + { + $cache = common_memcache(); + + if (!empty($cache)) { + $notices = array(); + foreach ($ids as $id) { + $notices[] = Notice::staticGet('id', $id); + } + return new ArrayWrapper($notices); + } else { + $notice = new Notice(); + $notice->whereAdd('id in (' . implode(', ', $ids) . ')'); + $notice->orderBy('id DESC'); + + $notice->find(); + return $notice; + } + } + function publicStream($offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) { diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php index 81ddb45385..162da74fee 100644 --- a/classes/Notice_inbox.php +++ b/classes/Notice_inbox.php @@ -1,7 +1,7 @@ INBOX_CACHE_WINDOW) { + common_debug('Doing direct DB hit for notice_inbox since the params are screwy.'); + return Notice_inbox::_streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since); + } + + $idkey = common_cache_key('notice_inbox:by_user:'.$user_id); + + $idstr = $cache->get($idkey); + + if (!empty($idstr)) { + // Cache hit! Woohoo! + common_debug('Cache hit for notice_inbox.'); + $window = explode(',', $idstr); + $ids = array_slice($window, $offset, $limit); + return $ids; + } + + $laststr = common_cache_key($idkey.';last'); + + if (!empty($laststr)) { + common_debug('Cache hit for notice_inbox on last item.'); + + $window = explode(',', $laststr); + $last_id = $window[0]; + $new_ids = Notice_inbox::_streamDirect($user_id, 0, INBOX_CACHE_WINDOW, + $last_id, null, null); + + $new_window = array_merge($new_ids, $window); + + $new_windowstr = implode(',', $new_window); + + $result = $cache->set($idkey, $new_windowstr); + $result = $cache->set($idkey . ';last', $new_windowstr); + + $ids = array_slice($new_window, $offset, $limit); + + return $ids; + } + + $window = Notice_inbox::_streamDirect($user_id, 0, INBOX_CACHE_WINDOW, + null, null, null); + + $windowstr = implode(',', $new_window); + + $result = $cache->set($idkey, $windowstr); + $result = $cache->set($idkey . ';last', $windowstr); + + $ids = array_slice($window, $offset, $limit); + + return $ids; + } + + function _streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since) + { + $inbox = new Notice_inbox(); + + $inbox->user_id = $user_id; + + if ($since_id != 0) { + $inbox->whereAdd('notice_id > ' . $since_id); + } + + if ($before_id != 0) { + $inbox->whereAdd('notice_id < ' . $before_id); + } + + if (!is_null($since)) { + $inbox->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\''); + } + + $inbox->orderBy('notice_id DESC'); + + if (!is_null($offset)) { + $inbox->limit($offset, $limit); + } + + $ids = array(); + + if ($inbox->find()) { + while ($inbox->fetch()) { + $ids[] = $inbox->notice_id; + } + } + + return $ids; + } } diff --git a/classes/User.php b/classes/User.php index 098381f738..ce7ea1464f 100644 --- a/classes/User.php +++ b/classes/User.php @@ -451,34 +451,9 @@ class User extends Memcached_DataObject } else if ($enabled === true || ($enabled == 'transitional' && $this->inboxed == 1)) { - $cache = common_memcache(); + $ids = Notice_inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since); - if (!empty($cache)) { - - # Get the notices out of the cache - - $notices = $cache->get(common_cache_key($cachekey)); - - # On a cache hit, return a DB-object-like wrapper - - if ($notices !== false) { - $wrapper = new ArrayWrapper(array_slice($notices, $offset, $limit)); - return $wrapper; - } - } - - $inbox = Notice_inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since); - - $ids = array(); - - while ($inbox->fetch()) { - $ids[] = $inbox->notice_id; - } - - $inbox->free(); - unset($inbox); - - return Notice::getStreamByIds($ids, 'user:notices_with_friends:' . $this->id); + return Notice::getStreamByIds($ids); } } From fe53e780be5db4ceb2831a1d69faec6130a10deb Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 28 Apr 2009 13:31:56 -0400 Subject: [PATCH 13/22] Remove some debug comments in query-by-id --- classes/Notice.php | 5 ++--- classes/Notice_inbox.php | 4 ---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index b087c94bc4..49d0939c1a 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -215,7 +215,6 @@ class Notice extends Memcached_DataObject if (common_config('queue', 'enabled')) { $notice->blowAuthorCaches(); } else { - common_debug("Blowing caches for new notice."); $notice->blowCaches(); } } @@ -353,9 +352,9 @@ class Notice extends Memcached_DataObject 'WHERE subscription.subscribed = ' . $this->profile_id); while ($user->fetch()) { - $cache->delete(common_cache_key('notice_inbox:by_user:'.$user_id)); + $cache->delete(common_cache_key('notice_inbox:by_user:'.$user->id)); if ($blowLast) { - $cache->delete(common_cache_key('notice_inbox:by_user:'.$user_id.';last')); + $cache->delete(common_cache_key('notice_inbox:by_user:'.$user->id.';last')); } } $user->free(); diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php index 162da74fee..f321370380 100644 --- a/classes/Notice_inbox.php +++ b/classes/Notice_inbox.php @@ -50,7 +50,6 @@ class Notice_inbox extends Memcached_DataObject if (empty($cache) || $since_id != 0 || $before_id != 0 || !is_null($since) || ($offset + $limit) > INBOX_CACHE_WINDOW) { - common_debug('Doing direct DB hit for notice_inbox since the params are screwy.'); return Notice_inbox::_streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since); } @@ -60,7 +59,6 @@ class Notice_inbox extends Memcached_DataObject if (!empty($idstr)) { // Cache hit! Woohoo! - common_debug('Cache hit for notice_inbox.'); $window = explode(',', $idstr); $ids = array_slice($window, $offset, $limit); return $ids; @@ -69,8 +67,6 @@ class Notice_inbox extends Memcached_DataObject $laststr = common_cache_key($idkey.';last'); if (!empty($laststr)) { - common_debug('Cache hit for notice_inbox on last item.'); - $window = explode(',', $laststr); $last_id = $window[0]; $new_ids = Notice_inbox::_streamDirect($user_id, 0, INBOX_CACHE_WINDOW, From e85cddba45c2ce02d135f00acdcfa37cb9168130 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 28 Apr 2009 23:31:00 -0700 Subject: [PATCH 14/22] Ticket #1428 - Changed replies API method to "mentions". --- actions/twitapistatuses.php | 38 ++++++++++++++++++++----------------- lib/router.php | 4 ++-- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php index 323c4f1f88..3abeba3672 100644 --- a/actions/twitapistatuses.php +++ b/actions/twitapistatuses.php @@ -144,10 +144,10 @@ class TwitapistatusesAction extends TwitterapiAction break; case 'atom': if (isset($apidata['api_arg'])) { - $selfuri = $selfuri = common_root_url() . + $selfuri = common_root_url() . 'api/statuses/friends_timeline/' . $apidata['api_arg'] . '.atom'; } else { - $selfuri = $selfuri = common_root_url() . + $selfuri = common_root_url() . 'api/statuses/friends_timeline.atom'; } $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, null, $selfuri); @@ -231,10 +231,10 @@ class TwitapistatusesAction extends TwitterapiAction break; case 'atom': if (isset($apidata['api_arg'])) { - $selfuri = $selfuri = common_root_url() . + $selfuri = common_root_url() . 'api/statuses/user_timeline/' . $apidata['api_arg'] . '.atom'; } else { - $selfuri = $selfuri = common_root_url() . + $selfuri = common_root_url() . 'api/statuses/user_timeline.atom'; } $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, $suplink, $selfuri); @@ -344,7 +344,7 @@ class TwitapistatusesAction extends TwitterapiAction $this->show($args, $apidata); } - function replies($args, $apidata) + function mentions($args, $apidata) { parent::handle($args); @@ -360,11 +360,13 @@ class TwitapistatusesAction extends TwitterapiAction $profile = $user->getProfile(); $sitename = common_config('site', 'name'); - $title = sprintf(_('%1$s / Updates replying to %2$s'), $sitename, $user->nickname); + $title = sprintf(_('%1$s / Updates mentioning %2$s'), + $sitename, $user->nickname); $taguribase = common_config('integration', 'taguri'); - $id = "tag:$taguribase:Replies:".$user->id; + $id = "tag:$taguribase:Mentions:".$user->id; $link = common_local_url('replies', array('nickname' => $user->nickname)); - $subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'), $sitename, $user->nickname, $profile->getBestName()); + $subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'), + $sitename, $user->nickname, $profile->getBestName()); if (!$page) { $page = 1; @@ -385,7 +387,8 @@ class TwitapistatusesAction extends TwitterapiAction $since = strtotime($this->arg('since')); - $notice = $user->getReplies((($page-1)*20), $count, $since_id, $before_id, $since); + $notice = $user->getReplies((($page-1)*20), + $count, $since_id, $before_id, $since); $notices = array(); while ($notice->fetch()) { @@ -400,14 +403,10 @@ class TwitapistatusesAction extends TwitterapiAction $this->show_rss_timeline($notices, $title, $link, $subtitle); break; case 'atom': - if (isset($apidata['api_arg'])) { - $selfuri = $selfuri = common_root_url() . - 'api/statuses/replies/' . $apidata['api_arg'] . '.atom'; - } else { - $selfuri = $selfuri = common_root_url() . - 'api/statuses/replies.atom'; - } - $this->show_atom_timeline($notices, $title, $id, $link, $subtitle, null, $selfuri); + $selfuri = common_root_url() . + ltrim($_SERVER['QUERY_STRING'], 'p='); + $this->show_atom_timeline($notices, $title, $id, $link, $subtitle, + null, $selfuri); break; case 'json': $this->show_json_timeline($notices); @@ -418,6 +417,11 @@ class TwitapistatusesAction extends TwitterapiAction } + function replies($args, $apidata) + { + call_user_func(array($this, 'mentions'), $args, $apidata); + } + function show($args, $apidata) { parent::handle($args); diff --git a/lib/router.php b/lib/router.php index 6fb2f94872..12590b790d 100644 --- a/lib/router.php +++ b/lib/router.php @@ -231,12 +231,12 @@ class Router $m->connect('api/statuses/:method', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(public_timeline|friends_timeline|user_timeline|update|replies|friends|followers|featured)(\.(atom|rss|xml|json))?')); + array('method' => '(public_timeline|friends_timeline|user_timeline|update|replies|mentions|friends|followers|featured)(\.(atom|rss|xml|json))?')); $m->connect('api/statuses/:method/:argument', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(user_timeline|friends_timeline|replies|show|destroy|friends|followers)')); + array('method' => '(user_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)')); // users From 10ef8a2f7112a83188e9702d480abd3c6062c26c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 29 Apr 2009 11:27:45 -0400 Subject: [PATCH 15/22] Move algorithm for caching to Notice class Moved the algorithm for notice stream caching to the Notice class. --- classes/Notice.php | 55 +++++++++++++++++++++++++++++++++++++++ classes/Notice_inbox.php | 56 ++++------------------------------------ 2 files changed, 60 insertions(+), 51 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 49d0939c1a..faabb1e140 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -967,4 +967,59 @@ class Notice extends Memcached_DataObject array('notice' => $this->id)); } } + + function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) + { + $cache = common_memcache(); + + if (empty($cache) || + $since_id != 0 || $before_id != 0 || !is_null($since) || + ($offset + $limit) > NOTICE_CACHE_WINDOW) { + return call_user_func_array($fn, array_merge($args, array($offset, $limit, $since_id, + $before_id, $since))); + } + + $idkey = common_cache_key($cachekey); + + $idstr = $cache->get($idkey); + + if (!empty($idstr)) { + // Cache hit! Woohoo! + $window = explode(',', $idstr); + $ids = array_slice($window, $offset, $limit); + return $ids; + } + + $laststr = common_cache_key($idkey.';last'); + + if (!empty($laststr)) { + $window = explode(',', $laststr); + $last_id = $window[0]; + $new_ids = call_user_func_array($fn, array_merge($args, array(0, NOTICE_CACHE_WINDOW, + $last_id, 0, null))); + + $new_window = array_merge($new_ids, $window); + + $new_windowstr = implode(',', $new_window); + + $result = $cache->set($idkey, $new_windowstr); + $result = $cache->set($idkey . ';last', $new_windowstr); + + $ids = array_slice($new_window, $offset, $limit); + + return $ids; + } + + $window = call_user_func_array($fn, array_merge($args, array(0, NOTICE_CACHE_WINDOW, + 0, 0, null))); + + $windowstr = implode(',', $new_window); + + $result = $cache->set($idkey, $windowstr); + $result = $cache->set($idkey . ';last', $windowstr); + + $ids = array_slice($window, $offset, $limit); + + return $ids; + } } diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php index f321370380..dec14b0d18 100644 --- a/classes/Notice_inbox.php +++ b/classes/Notice_inbox.php @@ -43,58 +43,12 @@ 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=0, $limit=20, $since_id=0, $before_id=0, $since=null) + function stream($user_id, $offset, $limit, $since_id, $before_id, $since) { - $cache = common_memcache(); - - if (empty($cache) || - $since_id != 0 || $before_id != 0 || !is_null($since) || - ($offset + $limit) > INBOX_CACHE_WINDOW) { - return Notice_inbox::_streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since); - } - - $idkey = common_cache_key('notice_inbox:by_user:'.$user_id); - - $idstr = $cache->get($idkey); - - if (!empty($idstr)) { - // Cache hit! Woohoo! - $window = explode(',', $idstr); - $ids = array_slice($window, $offset, $limit); - return $ids; - } - - $laststr = common_cache_key($idkey.';last'); - - if (!empty($laststr)) { - $window = explode(',', $laststr); - $last_id = $window[0]; - $new_ids = Notice_inbox::_streamDirect($user_id, 0, INBOX_CACHE_WINDOW, - $last_id, null, null); - - $new_window = array_merge($new_ids, $window); - - $new_windowstr = implode(',', $new_window); - - $result = $cache->set($idkey, $new_windowstr); - $result = $cache->set($idkey . ';last', $new_windowstr); - - $ids = array_slice($new_window, $offset, $limit); - - return $ids; - } - - $window = Notice_inbox::_streamDirect($user_id, 0, INBOX_CACHE_WINDOW, - null, null, null); - - $windowstr = implode(',', $new_window); - - $result = $cache->set($idkey, $windowstr); - $result = $cache->set($idkey . ';last', $windowstr); - - $ids = array_slice($window, $offset, $limit); - - return $ids; + return Notice::stream(array('Notice_inbox', '_streamDirect'), + array($user_id), + 'notice_inbox:by_user:'.$user_id, + $offset, $limit, $since_id, $before_id, $since); } function _streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since) From a4d959b8a2254d173bdf45f418f6add9f6f62cda Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 29 Apr 2009 12:05:31 -0400 Subject: [PATCH 16/22] Public stream uses IDs method Public stream now uses IDs method --- classes/Notice.php | 55 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index faabb1e140..6a7522bd32 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -635,25 +635,58 @@ class Notice extends Memcached_DataObject function publicStream($offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) { + $ids = Notice::stream(array('Notice', '_publicStreamDirect'), + array(), + 'public', + $offset, $limit, $since_id, $before_id, $since); - $parts = array(); + return Notice::getStreamByIds($ids); + } - $qry = 'SELECT * FROM notice '; + function _publicStreamDirect($offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) + { + $notice = new Notice(); + + $notice->selectAdd(); // clears it + $notice->selectAdd('id'); + + $notice->orderBy('id DESC'); + + if (!is_null($offset)) { + $notice->limit($offset, $limit); + } if (common_config('public', 'localonly')) { - $parts[] = 'is_local = 1'; + $notice->whereAdd('is_local = 1'); } else { # -1 == blacklisted - $parts[] = 'is_local != -1'; + $notice->whereAdd('is_local != -1'); } - if ($parts) { - $qry .= ' WHERE ' . implode(' AND ', $parts); + if ($since_id != 0) { + $notice->whereAdd('id > ' . $since_id); } - return Notice::getStream($qry, - 'public', - $offset, $limit, $since_id, $before_id, null, $since); + if ($before_id != 0) { + $notice->whereAdd('id < ' . $before_id); + } + + if (!is_null($since)) { + $notice->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\''); + } + + $ids = array(); + + if ($notice->find()) { + while ($notice->fetch()) { + $ids[] = $notice->id; + } + } + + $notice->free(); + $notice = NULL; + + return $ids; } function addToInboxes() @@ -990,7 +1023,7 @@ class Notice extends Memcached_DataObject return $ids; } - $laststr = common_cache_key($idkey.';last'); + $laststr = $cache->get($idkey.';last'); if (!empty($laststr)) { $window = explode(',', $laststr); @@ -1013,7 +1046,7 @@ class Notice extends Memcached_DataObject $window = call_user_func_array($fn, array_merge($args, array(0, NOTICE_CACHE_WINDOW, 0, 0, null))); - $windowstr = implode(',', $new_window); + $windowstr = implode(',', $window); $result = $cache->set($idkey, $windowstr); $result = $cache->set($idkey . ';last', $windowstr); From 8295402fb30a3854bae3b9d6c457c7c0e432c51a Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 29 Apr 2009 13:16:52 -0700 Subject: [PATCH 17/22] Added 'mentions' the the list of API methods requiring bare auth --- actions/api.php | 1 + 1 file changed, 1 insertion(+) diff --git a/actions/api.php b/actions/api.php index d2f0a2eff0..8762b4bcd3 100644 --- a/actions/api.php +++ b/actions/api.php @@ -130,6 +130,7 @@ class ApiAction extends Action 'statuses/friends_timeline', 'statuses/friends', 'statuses/replies', + 'statuses/mentions', 'statuses/followers', 'favorites/favorites'); From b79fef307481b36b4d04dbabb54e3f6d9edf6896 Mon Sep 17 00:00:00 2001 From: CiaranG Date: Wed, 29 Apr 2009 23:43:42 +0100 Subject: [PATCH 18/22] Fixed remote subscription, broken in fc6cedd2227d9d560736e494f431e2b40b26b45c --- actions/accesstoken.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/accesstoken.php b/actions/accesstoken.php index bb68d3314d..46b43c7021 100644 --- a/actions/accesstoken.php +++ b/actions/accesstoken.php @@ -59,7 +59,7 @@ class AccesstokenAction extends Action try { common_debug('getting request from env variables', __FILE__); common_remove_magic_from_request(); - $req = OAuthRequest::from_request('POST', common_locale_url('accesstoken')); + $req = OAuthRequest::from_request('POST', common_local_url('accesstoken')); common_debug('getting a server', __FILE__); $server = omb_oauth_server(); common_debug('fetching the access token', __FILE__); From 8a142b272c87678268106df48497b90664be323a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 1 May 2009 07:08:01 -0400 Subject: [PATCH 19/22] ignore Eclipse project files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 83a53dfa3f..da6947bfdc 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ dataobject.ini *.rej .#* *.swp +.buildpath +.project +.settings From 9cac6413a342445a998773458b215d129c2be2d1 Mon Sep 17 00:00:00 2001 From: Ori Avtalion Date: Fri, 1 May 2009 07:11:28 -0400 Subject: [PATCH 20/22] Add s to user favorite notices --- actions/favoritesrss.php | 2 +- actions/showfavorites.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/actions/favoritesrss.php b/actions/favoritesrss.php index f85bf1b190..6b46b8dec7 100644 --- a/actions/favoritesrss.php +++ b/actions/favoritesrss.php @@ -107,7 +107,7 @@ class FavoritesrssAction extends Rss10Action $c = array('url' => common_local_url('favoritesrss', array('nickname' => $user->nickname)), - 'title' => sprintf(_("%s favorite notices"), $user->nickname), + 'title' => sprintf(_("%s's favorite notices"), $user->nickname), 'link' => common_local_url('showfavorites', array('nickname' => $user->nickname)), diff --git a/actions/showfavorites.php b/actions/showfavorites.php index 6e011d5ca5..eed62a2ab3 100644 --- a/actions/showfavorites.php +++ b/actions/showfavorites.php @@ -74,9 +74,9 @@ class ShowfavoritesAction extends Action function title() { if ($this->page == 1) { - return sprintf(_("%s favorite notices"), $this->user->nickname); + return sprintf(_("%s's favorite notices"), $this->user->nickname); } else { - return sprintf(_("%s favorite notices, page %d"), + return sprintf(_("%s's favorite notices, page %d"), $this->user->nickname, $this->page); } From c5e72e248fa70b5e038c74b73b581884112706d5 Mon Sep 17 00:00:00 2001 From: Ori Avtalion Date: Fri, 1 May 2009 07:12:13 -0400 Subject: [PATCH 21/22] Several whitespace fixes --- actions/openidsettings.php | 4 ++-- actions/recoverpassword.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/actions/openidsettings.php b/actions/openidsettings.php index 92469d20f8..5f59ebc014 100644 --- a/actions/openidsettings.php +++ b/actions/openidsettings.php @@ -67,8 +67,8 @@ class OpenidsettingsAction extends AccountSettingsAction function getInstructions() { - return _('[OpenID](%%doc.openid%%) lets you log into many sites ' . - ' with the same user account. '. + return _('[OpenID](%%doc.openid%%) lets you log into many sites' . + ' with the same user account.'. ' Manage your associated OpenIDs from here.'); } diff --git a/actions/recoverpassword.php b/actions/recoverpassword.php index 620fe7eb8e..82263fcd59 100644 --- a/actions/recoverpassword.php +++ b/actions/recoverpassword.php @@ -151,11 +151,11 @@ class RecoverpasswordAction extends Action $this->element('p', null, _('If you\'ve forgotten or lost your' . ' password, you can get a new one sent to' . - ' the email address you have stored ' . + ' the email address you have stored' . ' in your account.')); } else if ($this->mode == 'reset') { $this->element('p', null, - _('You\'ve been identified. Enter a ' . + _('You\'ve been identified. Enter a' . ' new password below. ')); } $this->elementEnd('div'); From 609ac4c22463af88c206968134ab16e75e500edd Mon Sep 17 00:00:00 2001 From: Ori Avtalion Date: Fri, 1 May 2009 07:12:37 -0400 Subject: [PATCH 22/22] Fix link to identi.ca in JavaScript badge --- js/identica-badge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/identica-badge.js b/js/identica-badge.js index 869230b7a4..ffa55ae93e 100644 --- a/js/identica-badge.js +++ b/js/identica-badge.js @@ -128,7 +128,7 @@ var a = document.createElement('A'); a.innerHTML = 'get this'; a.target = '_blank'; - a.href = 'http://identica/doc/badge'; + a.href = 'http://identi.ca/doc/badge'; $.s.f.appendChild(a); $.s.appendChild($.s.f); $.f.getUser();