diff --git a/classes/Notice.php b/classes/Notice.php index de45bdaae1..70036fa8fb 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -802,30 +802,65 @@ class Notice extends Memcached_DataObject * * @return Notice or null */ - function conversationRoot() + function conversationRoot($profile=-1) { - if (!empty($this->conversation)) { - $c = self::memcache(); + // XXX: can this happen? - $key = Cache::key('notice:conversation_root:' . $this->conversation); - $notice = $c->get($key); - if ($notice) { - return $notice; - } - - $notice = new Notice(); - $notice->conversation = $this->conversation; - $notice->orderBy('CREATED'); - $notice->limit(1); - $notice->find(true); - - if ($notice->N) { - $c->set($key, $notice); - return $notice; - } + if (empty($this->conversation)) { + return null; } - return null; + + // Get the current profile if not specified + + if (is_int($profile) && $profile == -1) { + $profile = Profile::current(); + } + + // If this notice is out of scope, no root for you! + + if (!$this->inScope($profile)) { + return null; + } + + // If this isn't a reply to anything, then it's its own + // root. + + if (empty($this->reply_to)) { + return $this; + } + + if (is_null($profile)) { + $keypart = sprintf('notice:conversation_root:%d:null', $this->id); + } else { + $keypart = sprintf('notice:conversation_root:%d:%d', + $this->id, + $profile->id); + } + + $root = self::cacheGet($keypart); + + if ($root !== false && $root->inScope($profile)) { + return $root; + } else { + $last = $this; + + do { + $parent = $last->getOriginal(); + if (!empty($parent) && $parent->inScope($profile)) { + $last = $parent; + continue; + } else { + $root = $last; + break; + } + } while (!empty($parent)); + + self::cacheSet($keypart, $root); + } + + return $root; } + /** * Pull up a full list of local recipients who will be getting * this notice in their inbox. Results will be cached, so don't @@ -2420,4 +2455,18 @@ class Notice extends Memcached_DataObject return $groups; } + + protected $_original = -1; + + function getOriginal() + { + if (is_int($this->_original) && $this->_original == -1) { + if (empty($this->reply_to)) { + $this->_original = null; + } else { + $this->_original = Notice::staticGet('id', $this->reply_to); + } + } + return $this->_original; + } } diff --git a/lib/threadednoticelist.php b/lib/threadednoticelist.php index 372791c3e5..3725ff0535 100644 --- a/lib/threadednoticelist.php +++ b/lib/threadednoticelist.php @@ -52,9 +52,12 @@ class ThreadedNoticeList extends NoticeList { protected $userProfile; - function __construct($notice, $out=null, $profile=null) + function __construct($notice, $out=null, $profile=-1) { parent::__construct($notice, $out); + if (is_int($profile) && $profile == -1) { + $profile = Profile::current(); + } $this->userProfile = $profile; } @@ -98,7 +101,7 @@ class ThreadedNoticeList extends NoticeList $conversations[$convo] = true; // Get the convo's root notice - $root = $notice->conversationRoot(); + $root = $notice->conversationRoot($this->userProfile); if ($root) { $notice = $root; }