diff options
Diffstat (limited to 'classes')
-rw-r--r-- | classes/Notice.php | 147 | ||||
-rw-r--r-- | classes/Profile.php | 11 | ||||
-rw-r--r-- | classes/User.php | 159 | ||||
-rw-r--r-- | classes/statusnet.ini | 2 |
4 files changed, 312 insertions, 7 deletions
diff --git a/classes/Notice.php b/classes/Notice.php index 4422866fa..7d2b898d2 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -55,13 +55,13 @@ class Notice extends Memcached_DataObject public $__table = 'notice'; // table name public $id; // int(4) primary_key not_null - public $profile_id; // int(4) not_null + public $profile_id; // int(4) multiple_key not_null public $uri; // varchar(255) unique_key - public $content; // text() - public $rendered; // text() + public $content; // text + public $rendered; // text public $url; // varchar(255) - public $created; // datetime() not_null - public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP + public $created; // datetime multiple_key not_null default_0000-00-00%2000%3A00%3A00 + public $modified; // timestamp not_null default_CURRENT_TIMESTAMP public $reply_to; // int(4) public $is_local; // tinyint(1) public $source; // varchar(32) @@ -70,9 +70,11 @@ class Notice extends Memcached_DataObject public $lon; // decimal(10,7) public $location_id; // int(4) public $location_ns; // int(4) + public $repeat_of; // int(4) /* Static get */ - function staticGet($k,$v=NULL) { + function staticGet($k,$v=NULL) + { return Memcached_DataObject::staticGet('Notice',$k,$v); } @@ -113,6 +115,12 @@ class Notice extends Memcached_DataObject //Null any notices that are replies to this notice $this->query(sprintf("UPDATE notice set reply_to = null WHERE reply_to = %d", $this->id)); + + //Null any notices that are repeats of this notice + //XXX: probably need to uncache these, too + + $this->query(sprintf("UPDATE notice set repeat_of = null WHERE repeat_of = %d", $this->id)); + $related = array('Reply', 'Fave', 'Notice_tag', @@ -234,7 +242,14 @@ class Notice extends Memcached_DataObject $notice->source = $source; $notice->uri = $uri; - $notice->reply_to = self::getReplyTo($reply_to, $profile_id, $source, $final); + // Handle repeat case + + if (isset($repeat_of)) { + $notice->repeat_of = $repeat_of; + $notice->reply_to = $repeat_of; + } else { + $notice->reply_to = self::getReplyTo($reply_to, $profile_id, $source, $final); + } if (!empty($notice->reply_to)) { $reply = Notice::staticGet('id', $notice->reply_to); @@ -432,10 +447,60 @@ class Notice extends Memcached_DataObject $this->blowTagCache($blowLast); $this->blowGroupCache($blowLast); $this->blowConversationCache($blowLast); + $this->blowRepeatCache(); $profile = Profile::staticGet($this->profile_id); $profile->blowNoticeCount(); } + function blowRepeatCache() + { + if (!empty($this->repeat_of)) { + $cache = common_memcache(); + if (!empty($cache)) { + // XXX: only blow if <100 in cache + $ck = common_cache_key('notice:repeats:'.$this->repeat_of); + $result = $cache->delete($ck); + + $user = User::staticGet('id', $this->profile_id); + + if (!empty($user)) { + $uk = common_cache_key('user:repeated_by_me:'.$user->id); + $cache->delete($uk); + $user->free(); + unset($user); + } + + $original = Notice::staticGet('id', $this->repeat_of); + + if (!empty($original)) { + $originalUser = User::staticGet('id', $original->profile_id); + if (!empty($originalUser)) { + $ouk = common_cache_key('user:repeats_of_me:'.$originalUser->id); + $cache->delete($ouk); + $originalUser->free(); + unset($originalUser); + } + $original->free(); + unset($original); + } + + $ni = new Notice_inbox(); + + $ni->notice_id = $this->id; + + if ($ni->find()) { + while ($ni->fetch()) { + $tmk = common_cache_key('user:repeated_to_me:'.$ni->user_id); + $cache->delete($tmk); + } + } + + $ni->free(); + unset($ni); + } + } + } + function blowConversationCache($blowLast=false) { $cache = common_memcache(); @@ -1432,4 +1497,72 @@ class Notice extends Memcached_DataObject return $location; } + + function repeat($repeater_id, $source) + { + $author = Profile::staticGet('id', $this->profile_id); + + // FIXME: truncate on long repeats...? + + $content = sprintf(_('RT @%1$s %2$s'), + $author->nickname, + $this->content); + + return self::saveNew($repeater_id, $content, $source, + array('repeat_of' => $this->id)); + } + + // These are supposed to be in chron order! + + function repeatStream($limit=100) + { + $cache = common_memcache(); + + if (empty($cache)) { + $ids = $this->_repeatStreamDirect($limit); + } else { + $idstr = $cache->get(common_cache_key('notice:repeats:'.$this->id)); + if (!empty($idstr)) { + $ids = explode(',', $idstr); + } else { + $ids = $this->_repeatStreamDirect(100); + $cache->set(common_cache_key('notice:repeats:'.$this->id), implode(',', $ids)); + } + if ($limit < 100) { + // We do a max of 100, so slice down to limit + $ids = array_slice($ids, 0, $limit); + } + } + + return Notice::getStreamByIds($ids); + } + + function _repeatStreamDirect($limit) + { + $notice = new Notice(); + + $notice->selectAdd(); // clears it + $notice->selectAdd('id'); + + $notice->repeat_of = $this->id; + + $notice->orderBy('created'); // NB: asc! + + if (!is_null($offset)) { + $notice->limit($offset, $limit); + } + + $ids = array(); + + if ($notice->find()) { + while ($notice->fetch()) { + $ids[] = $notice->id; + } + } + + $notice->free(); + $notice = NULL; + + return $ids; + } } diff --git a/classes/Profile.php b/classes/Profile.php index 4b2e09006..03196447b 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -716,4 +716,15 @@ class Profile extends Memcached_DataObject } return $result; } + + function hasRepeated($notice_id) + { + // XXX: not really a pkey, but should work + + $notice = Memcached_DataObject::pkeyGet('Notice', + array('profile_id' => $this->id, + 'repeat_of' => $notice_id)); + + return !empty($notice); + } } diff --git a/classes/User.php b/classes/User.php index 2a4fab7d4..9c071e06b 100644 --- a/classes/User.php +++ b/classes/User.php @@ -741,4 +741,163 @@ class User extends Memcached_DataObject $profile = $this->getProfile(); return $profile->isSilenced(); } + + function repeatedByMe($offset=0, $limit=20, $since_id=null, $max_id=null) + { + $ids = Notice::stream(array($this, '_repeatedByMeDirect'), + array(), + 'user:repeated_by_me:'.$this->id, + $offset, $limit, $since_id, $max_id, null); + + return Notice::getStreamByIds($ids); + } + + function _repeatedByMeDirect($offset, $limit, $since_id, $max_id, $since) + { + $notice = new Notice(); + + $notice->selectAdd(); // clears it + $notice->selectAdd('id'); + + $notice->profile_id = $this->id; + $notice->whereAdd('repeat_of IS NOT NULL'); + + $notice->orderBy('id DESC'); + + if (!is_null($offset)) { + $notice->limit($offset, $limit); + } + + if ($since_id != 0) { + $notice->whereAdd('id > ' . $since_id); + } + + if ($max_id != 0) { + $notice->whereAdd('id <= ' . $max_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 repeatsOfMe($offset=0, $limit=20, $since_id=null, $max_id=null) + { + $ids = Notice::stream(array($this, '_repeatsOfMeDirect'), + array(), + 'user:repeats_of_me:'.$this->id, + $offset, $limit, $since_id, $max_id, null); + + return Notice::getStreamByIds($ids); + } + + function _repeatsOfMeDirect($offset, $limit, $since_id, $max_id, $since) + { + $qry = + 'SELECT DISTINCT original.id AS id ' . + 'FROM notice original JOIN notice rept ON original.id = rept.repeat_of ' . + 'WHERE original.profile_id = ' . $this->id . ' '; + + if ($since_id != 0) { + $qry .= 'AND original.id > ' . $since_id . ' '; + } + + if ($max_id != 0) { + $qry .= 'AND original.id <= ' . $max_id . ' '; + } + + if (!is_null($since)) { + $qry .= 'AND original.modified > \'' . date('Y-m-d H:i:s', $since) . '\' '; + } + + // NOTE: we sort by fave time, not by notice time! + + $qry .= 'ORDER BY original.id DESC '; + + if (!is_null($offset)) { + $qry .= "LIMIT $limit OFFSET $offset"; + } + + $ids = array(); + + $notice = new Notice(); + + $notice->query($qry); + + while ($notice->fetch()) { + $ids[] = $notice->id; + } + + $notice->free(); + $notice = NULL; + + return $ids; + } + + function repeatedToMe($offset=0, $limit=20, $since_id=null, $max_id=null) + { + $ids = Notice::stream(array($this, '_repeatedToMeDirect'), + array(), + 'user:repeated_to_me:'.$this->id, + $offset, $limit, $since_id, $max_id, null); + + return Notice::getStreamByIds($ids); + } + + function _repeatedToMeDirect($offset, $limit, $since_id, $max_id, $since) + { + $qry = + 'SELECT notice.id AS id ' . + 'FROM notice JOIN notice_inbox ON notice.id = notice_inbox.notice_id ' . + 'WHERE notice_inbox.user_id = ' . $this->id . ' ' . + 'AND notice.repeat_of IS NOT NULL '; + + if ($since_id != 0) { + $qry .= 'AND notice.id > ' . $since_id . ' '; + } + + if ($max_id != 0) { + $qry .= 'AND notice.id <= ' . $max_id . ' '; + } + + if (!is_null($since)) { + $qry .= 'AND notice.modified > \'' . date('Y-m-d H:i:s', $since) . '\' '; + } + + // NOTE: we sort by fave time, not by notice time! + + $qry .= 'ORDER BY notice.id DESC '; + + if (!is_null($offset)) { + $qry .= "LIMIT $limit OFFSET $offset"; + } + + $ids = array(); + + $notice = new Notice(); + + $notice->query($qry); + + while ($notice->fetch()) { + $ids[] = $notice->id; + } + + $notice->free(); + $notice = NULL; + + return $ids; + } } diff --git a/classes/statusnet.ini b/classes/statusnet.ini index 835faeb0b..ff4ef2c14 100644 --- a/classes/statusnet.ini +++ b/classes/statusnet.ini @@ -1,3 +1,4 @@ + [avatar] profile_id = 129 original = 17 @@ -306,6 +307,7 @@ lat = 1 lon = 1 location_id = 1 location_ns = 1 +repeat_of = 1 [notice__keys] id = N |