]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - classes/Notice.php
Merge branch 'righttoleave' into 0.9.x
[quix0rs-gnu-social.git] / classes / Notice.php
index 46e1dca35e57f87022a2aab3230c53aa7a2b10e1..50909f97071e31f339b0b35d66921386c0a94014 100644 (file)
@@ -234,6 +234,8 @@ class Notice extends Memcached_DataObject
      *                           in place of extracting # tags from content
      *              array 'urls' list of attached/referred URLs to save with the
      *                           notice in place of extracting links from content
+     *              boolean 'distribute' whether to distribute the notice, default true
+     *                    
      * @fixme tag override
      *
      * @return Notice
@@ -243,7 +245,8 @@ class Notice extends Memcached_DataObject
         $defaults = array('uri' => null,
                           'url' => null,
                           'reply_to' => null,
-                          'repeat_of' => null);
+                          'repeat_of' => null,
+                          'distribute' => true);
 
         if (!empty($options)) {
             $options = $options + $defaults;
@@ -426,8 +429,10 @@ class Notice extends Memcached_DataObject
             $notice->saveUrls();
         }
 
-        // Prepare inbox delivery, may be queued to background.
-        $notice->distribute();
+        if ($distribute) {
+            // Prepare inbox delivery, may be queued to background.
+            $notice->distribute();
+        }
 
         return $notice;
     }
@@ -654,7 +659,7 @@ class Notice extends Memcached_DataObject
         $notice->selectAdd(); // clears it
         $notice->selectAdd('id');
 
-        $notice->orderBy('id DESC');
+        $notice->orderBy('created DESC, id DESC');
 
         if (!is_null($offset)) {
             $notice->limit($offset, $limit);
@@ -668,13 +673,8 @@ class Notice extends Memcached_DataObject
             $notice->whereAdd('is_local !='. Notice::GATEWAY);
         }
 
-        if ($since_id != 0) {
-            $notice->whereAdd('id > ' . $since_id);
-        }
-
-        if ($max_id != 0) {
-            $notice->whereAdd('id <= ' . $max_id);
-        }
+        Notice::addWhereSinceId($notice, $since_id);
+        Notice::addWhereMaxId($notice, $max_id);
 
         $ids = array();
 
@@ -709,19 +709,14 @@ class Notice extends Memcached_DataObject
 
         $notice->conversation = $id;
 
-        $notice->orderBy('id DESC');
+        $notice->orderBy('created DESC, 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);
-        }
+        Notice::addWhereSinceId($notice, $since_id);
+        Notice::addWhereMaxId($notice, $max_id);
 
         $ids = array();
 
@@ -1234,9 +1229,9 @@ class Notice extends Memcached_DataObject
      * @return Activity activity object representing this Notice.
      */
 
-    function asActivity($cur = null, $source = false)
+    function asActivity()
     {
-        $act = self::cacheGet('notice:as-activity:'.$this->id);
+        $act = self::cacheGet(Cache::codeKey('notice:as-activity:'.$this->id));
 
         if (!empty($act)) {
             return $act;
@@ -1332,68 +1327,37 @@ class Notice extends Memcached_DataObject
            
             $act->context = $ctx;
 
-            $noticeInfoAttr = array('local_id' => $this->id); // local notice ID (useful to clients for ordering)
-
-            $ns = $this->getSource();
-
-            if (!empty($ns)) {
-                $noticeInfoAttr['source'] =  $ns->code;
-                if (!empty($ns->url)) {
-                    $noticeInfoAttr['source_link'] = $ns->url;
-                    if (!empty($ns->name)) {
-                        $noticeInfoAttr['source'] =  '<a href="'
-                            . htmlspecialchars($ns->url)
-                            . '" rel="nofollow">'
-                            . htmlspecialchars($ns->name)
-                            . '</a>';
-                    }
-                }
-            }
-
-            if (!empty($cur)) {
-                $noticeInfoAttr['favorite'] = ($cur->hasFave($this)) ? "true" : "false";
-                $cp = $cur->getProfile();
-                $noticeInfoAttr['repeated'] = ($cp->hasRepeated($this->id)) ? "true" : "false";
-            }
-
-            if (!empty($this->repeat_of)) {
-                $noticeInfoAttr['repeat_of'] = $this->repeat_of;
-            }
-
-            $act->extra[] = array('statusnet:notice_info', $noticeInfoAttr, null);
+            // Source
 
-            if ($source) {
-               
-                $atom_feed = $profile->getAtomFeed();
+            $atom_feed = $profile->getAtomFeed();
 
-                if (!empty($atom_feed)) {
+            if (!empty($atom_feed)) {
 
-                    $act->source = new ActivitySource();
+                $act->source = new ActivitySource();
                    
-                    // XXX: we should store the actual feed ID
+                // XXX: we should store the actual feed ID
 
-                    $act->source->id = $atom_feed;
+                $act->source->id = $atom_feed;
 
-                    // XXX: we should store the actual feed title
+                // XXX: we should store the actual feed title
 
-                    $act->source->title = $profile->getBestName();
+                $act->source->title = $profile->getBestName();
 
-                    $act->source->links['alternate'] = $profile->profileurl;
-                    $act->source->links['self']      = $atom_feed;
+                $act->source->links['alternate'] = $profile->profileurl;
+                $act->source->links['self']      = $atom_feed;
 
-                    $act->source->icon = $profile->avatarUrl(AVATAR_PROFILE_SIZE);
+                $act->source->icon = $profile->avatarUrl(AVATAR_PROFILE_SIZE);
                    
-                    $notice = $profile->getCurrentNotice();
+                $notice = $profile->getCurrentNotice();
 
-                    if (!empty($notice)) {
-                        $act->source->updated = self::utcDate($notice->created);
-                    }
+                if (!empty($notice)) {
+                    $act->source->updated = self::utcDate($notice->created);
+                }
 
-                    $user = User::staticGet('id', $profile->id);
+                $user = User::staticGet('id', $profile->id);
 
-                    if (!empty($user)) {
-                        $act->source->links['license'] = common_config('license', 'url');
-                    }
+                if (!empty($user)) {
+                    $act->source->links['license'] = common_config('license', 'url');
                 }
             }
 
@@ -1406,7 +1370,7 @@ class Notice extends Memcached_DataObject
             Event::handle('EndNoticeAsActivity', array($this, &$act));
         }
        
-        self::cacheSet('notice:as-activity:'.$this->id, $act);
+        self::cacheSet(Cache::codeKey('notice:as-activity:'.$this->id), $act);
 
         return $act;
     }
@@ -1414,12 +1378,65 @@ class Notice extends Memcached_DataObject
     // This has gotten way too long. Needs to be sliced up into functional bits
     // or ideally exported to a utility class.
 
-    function asAtomEntry($namespace=false, $source=false, $author=true, $cur=null)
+    function asAtomEntry($namespace=false,
+                         $source=false,
+                         $author=true, 
+                         $cur=null)
     {
-        $act = $this->asActivity($cur, $source);
-        return $act->asString($namespace, $author);
+        $act = $this->asActivity();
+        $act->extra[] = $this->noticeInfo($cur);
+        return $act->asString($namespace, $author, $source);
+    }
+
+    /**
+     * Extra notice info for atom entries
+     * 
+     * Clients use some extra notice info in the atom stream.
+     * This gives it to them.
+     *
+     * @param User $cur Current user
+     *
+     * @return array representation of <statusnet:notice_info> element
+     */
+
+    function noticeInfo($cur)
+    {
+        // local notice ID (useful to clients for ordering)
+
+        $noticeInfoAttr = array('local_id' => $this->id);
+
+        // notice source
+
+        $ns = $this->getSource();
+
+        if (!empty($ns)) {
+            $noticeInfoAttr['source'] =  $ns->code;
+            if (!empty($ns->url)) {
+                $noticeInfoAttr['source_link'] = $ns->url;
+                if (!empty($ns->name)) {
+                    $noticeInfoAttr['source'] =  '<a href="'
+                        . htmlspecialchars($ns->url)
+                        . '" rel="nofollow">'
+                        . htmlspecialchars($ns->name)
+                        . '</a>';
+                }
+            }
+        }
+
+        // favorite and repeated
+
+        if (!empty($cur)) {
+            $noticeInfoAttr['favorite'] = ($cur->hasFave($this)) ? "true" : "false";
+            $cp = $cur->getProfile();
+            $noticeInfoAttr['repeated'] = ($cp->hasRepeated($this->id)) ? "true" : "false";
+        }
+
+        if (!empty($this->repeat_of)) {
+            $noticeInfoAttr['repeat_of'] = $this->repeat_of;
+        }
+
+        return array('statusnet:notice_info', $noticeInfoAttr, null);
     }
-    
 
     /**
      * Returns an XML string fragment with a reference to a notice as an
@@ -1673,10 +1690,10 @@ class Notice extends Memcached_DataObject
 
         $notice->repeat_of = $this->id;
 
-        $notice->orderBy('created'); // NB: asc!
+        $notice->orderBy('created, id'); // NB: asc!
 
-        if (!is_null($offset)) {
-            $notice->limit($offset, $limit);
+        if (!is_null($limit)) {
+            $notice->limit(0, $limit);
         }
 
         $ids = array();
@@ -1956,4 +1973,108 @@ class Notice extends Memcached_DataObject
         $d = new DateTime($dateStr, new DateTimeZone('UTC'));
         return $d->format(DATE_W3C);
     }
+
+    /**
+     * Look up the creation timestamp for a given notice ID, even
+     * if it's been deleted.
+     *
+     * @param int $id
+     * @return mixed string recorded creation timestamp, or false if can't be found
+     */
+    public static function getAsTimestamp($id)
+    {
+        if (!$id) {
+            return false;
+        }
+
+        $notice = Notice::staticGet('id', $id);
+        if ($notice) {
+            return $notice->created;
+        }
+
+        $deleted = Deleted_notice::staticGet('id', $id);
+        if ($deleted) {
+            return $deleted->created;
+        }
+
+        return false;
+    }
+
+    /**
+     * Build an SQL 'where' fragment for timestamp-based sorting from a since_id
+     * parameter, matching notices posted after the given one (exclusive).
+     *
+     * If the referenced notice can't be found, will return false.
+     *
+     * @param int $id
+     * @param string $idField
+     * @param string $createdField
+     * @return mixed string or false if no match
+     */
+    public static function whereSinceId($id, $idField='id', $createdField='created')
+    {
+        $since = Notice::getAsTimestamp($id);
+        if ($since) {
+            return sprintf("($createdField = '%s' and $idField > %d) or ($createdField > '%s')", $since, $id, $since);
+        }
+        return false;
+    }
+
+    /**
+     * Build an SQL 'where' fragment for timestamp-based sorting from a since_id
+     * parameter, matching notices posted after the given one (exclusive), and
+     * if necessary add it to the data object's query.
+     *
+     * @param DB_DataObject $obj
+     * @param int $id
+     * @param string $idField
+     * @param string $createdField
+     * @return mixed string or false if no match
+     */
+    public static function addWhereSinceId(DB_DataObject $obj, $id, $idField='id', $createdField='created')
+    {
+        $since = self::whereSinceId($id);
+        if ($since) {
+            $obj->whereAdd($since);
+        }
+    }
+
+    /**
+     * Build an SQL 'where' fragment for timestamp-based sorting from a max_id
+     * parameter, matching notices posted before the given one (inclusive).
+     *
+     * If the referenced notice can't be found, will return false.
+     *
+     * @param int $id
+     * @param string $idField
+     * @param string $createdField
+     * @return mixed string or false if no match
+     */
+    public static function whereMaxId($id, $idField='id', $createdField='created')
+    {
+        $max = Notice::getAsTimestamp($id);
+        if ($max) {
+            return sprintf("($createdField < '%s') or ($createdField = '%s' and $idField <= %d)", $max, $max, $id);
+        }
+        return false;
+    }
+
+    /**
+     * Build an SQL 'where' fragment for timestamp-based sorting from a max_id
+     * parameter, matching notices posted before the given one (inclusive), and
+     * if necessary add it to the data object's query.
+     *
+     * @param DB_DataObject $obj
+     * @param int $id
+     * @param string $idField
+     * @param string $createdField
+     * @return mixed string or false if no match
+     */
+    public static function addWhereMaxId(DB_DataObject $obj, $id, $idField='id', $createdField='created')
+    {
+        $max = self::whereMaxId($id);
+        if ($max) {
+            $obj->whereAdd($max);
+        }
+    }
 }