]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - classes/Notice.php
Try to get mime data before hashing (cpu intensive)
[quix0rs-gnu-social.git] / classes / Notice.php
index 6781918be4ae410e2b654466673ff0bbee31f859..c56d68578debef875a7d38bd1579c101bdc571a5 100644 (file)
@@ -88,7 +88,7 @@ class Notice extends Managed_DataObject
                 'reply_to' => array('type' => 'int', 'description' => 'notice replied to (usually a guess)'),
                 'is_local' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'notice was generated by a user'),
                 'source' => array('type' => 'varchar', 'length' => 32, 'description' => 'source of comment, like "web", "im", or "clientname"'),
-                'conversation' => array('type' => 'int', 'description' => 'id of root notice in this conversation'),
+                'conversation' => array('type' => 'int', 'description' => 'the local numerical conversation id'),
                 'repeat_of' => array('type' => 'int', 'description' => 'notice this is a repeat of'),
                 'object_type' => array('type' => 'varchar', 'length' => 191, 'description' => 'URI representing activity streams object type', 'default' => null),
                 'verb' => array('type' => 'varchar', 'length' => 191, 'description' => 'URI representing activity streams verb', 'default' => 'http://activitystrea.ms/schema/1.0/post'),
@@ -260,7 +260,8 @@ class Notice extends Managed_DataObject
 
     public function getRendered()
     {
-        if (is_null($this->rendered) || $this->rendered === '') {
+        // we test $this->id because if it's not inserted yet, we can't update the field
+        if (!empty($this->id) && (is_null($this->rendered) || $this->rendered === '')) {
             // update to include rendered content on-the-fly, so we don't have to have a fix-up script in upgrade.php
             common_debug('Rendering notice '.$this->getID().' as it had no rendered HTML content.');
             $orig = clone($this);
@@ -272,6 +273,21 @@ class Notice extends Managed_DataObject
         return $this->rendered;
     }
 
+    public function getCreated()
+    {
+        return $this->created;
+    }
+
+    public function getVerb($make_relative=false)
+    {
+        return ActivityUtils::resolveUri($this->verb, $make_relative);
+    }
+
+    public function isVerb(array $verbs)
+    {
+        return ActivityUtils::compareVerbs($this->getVerb(), $verbs);
+    }
+
     /*
      * Get the original representation URL of this notice.
      *
@@ -298,9 +314,21 @@ class Notice extends Managed_DataObject
     }
 
     public function getObjectType($canonical=false) {
+        if (is_null($this->object_type) || $this->object_type==='') {
+            throw new NoObjectTypeException($this);
+        }
         return ActivityUtils::resolveUri($this->object_type, $canonical);
     }
 
+    public function isObjectType(array $types)
+    {
+        try {
+            return ActivityUtils::compareTypes($this->getObjectType(), $types);
+        } catch (NoObjectTypeException $e) {
+            return false;
+        }
+    }
+
     public static function getByUri($uri)
     {
         $notice = new Notice();
@@ -749,7 +777,7 @@ class Notice extends Managed_DataObject
             $options['uri'] = $act->id;
             $options['url'] = $act->link;
         } else {
-            $actobj = count($act->objects)==1 ? $act->objects[0] : null;
+            $actobj = count($act->objects)===1 ? $act->objects[0] : null;
             if (!is_null($actobj) && !empty($actobj->id)) {
                 $options['uri'] = $actobj->id;
                 if ($actobj->link) {
@@ -821,15 +849,17 @@ class Notice extends Managed_DataObject
         $stored->url = $url;
         $stored->verb = $act->verb;
 
-        // Notice content. We trust local users to provide HTML we like, but of course not remote users.
-        // FIXME: What about local users importing feeds? Mirror functions must filter out bad HTML first...
         $content = $act->content ?: $act->summary;
         if (is_null($content) && !is_null($actobj)) {
             $content = $actobj->content ?: $actobj->summary;
         }
-        $stored->rendered = $actor->isLocal() ? $content : common_purify($content);
-        // yeah, just don't use getRendered() here since it's not inserted yet ;)
-        $stored->content = common_strip_html($stored->rendered);
+        // Strip out any bad HTML
+        $stored->rendered = common_purify($content);
+        $stored->content  = common_strip_html($stored->getRendered(), true, true);
+        if (trim($stored->content) === '') {
+            // TRANS: Error message when the plain text content of a notice has zero length.
+            throw new ClientException(_('Empty notice content, will not save this.'));
+        }
 
         // Maybe a missing act-time should be fatal if the actor is not local?
         if (!empty($act->time)) {
@@ -950,7 +980,7 @@ class Notice extends Managed_DataObject
                 $object = null;
                 Event::handle('StoreActivityObject', array($act, $stored, $options, &$object));
                 if (empty($object)) {
-                    throw new ServerException('Unsuccessful call to StoreActivityObject '.$stored->getUri() . ': '.$act->asString());
+                    throw new NoticeSaveException('Unsuccessful call to StoreActivityObject '._ve($stored->getUri()) . ': '._ve($act->asString()));
                 }
 
                 // If something changed in the Notice during StoreActivityObject
@@ -974,8 +1004,6 @@ class Notice extends Managed_DataObject
         // reasonably handle notifications themselves.
         if (ActivityUtils::compareVerbs($stored->verb, array(ActivityVerb::POST))) {
 
-            $stored->saveAttentions($act->context->attention);
-
             if (!empty($tags)) {
                 $stored->saveKnownTags($tags);
             } else {
@@ -984,7 +1012,7 @@ class Notice extends Managed_DataObject
 
             // Note: groups may save tags, so must be run after tags are saved
             // to avoid errors on duplicates.
-            // Note: groups should always be set.
+            $stored->saveAttentions($act->context->attention);
 
             if (!empty($urls)) {
                 $stored->saveKnownUrls($urls);
@@ -1581,14 +1609,27 @@ class Notice extends Managed_DataObject
                 continue;
             }
 
-            $this->saveAttention($target);
+            try {
+                $this->saveAttention($target);
+            } catch (AlreadyFulfilledException $e) {
+                common_debug('Attention already exists: '.var_export($e->getMessage(),true));
+            } catch (Exception $e) {
+                common_log(LOG_ERR, "Could not save notice id=={$this->getID()} attention for profile id=={$target->getID()}: {$e->getMessage()}");
+            }
         }
     }
 
+    /**
+     * Saves an attention for a profile (user or group) which means
+     * it shows up in their home feed and such.
+     */
     function saveAttention(Profile $target, $reason=null)
     {
         if ($target->isGroup()) {
-            // FIXME: Make sure we check that users are in the groups they send to!
+            // FIXME: Make sure we check (for both local and remote) users are in the groups they send to!
+
+            // legacy notification method, will still be in use for quite a while I think
+            $this->addToGroupInbox($target->getGroup());
         } else {
             if ($target->hasBlocked($this->getProfile())) {
                 common_log(LOG_INFO, "Not saving reply to profile {$target->id} ($uri) from sender {$sender->id} because of a block.");
@@ -1597,17 +1638,11 @@ class Notice extends Managed_DataObject
         }
 
         if ($target->isLocal()) {
-            // is local user
-            $this->saveReply($target->getID());   // since we still have the Reply table which some apparently use!
+            // legacy notification method, will still be in use for quite a while I think
+            $this->saveReply($target->getID());
         }
 
-        try {
-            $att = Attention::saveNew($this, $target, $reason);
-        } catch (AlreadyFulfilledException $e) {
-            common_debug('Could not save Attention: '.$e->getMessage());
-        } catch (Exception $e) {
-            common_log(LOG_ERR, 'Could not save Attention: '.$e->getMessage());
-        }
+        $att = Attention::saveNew($this, $target, $reason);
 
         self::blow('reply:stream:%d', $target->getID());
         return true;
@@ -1954,19 +1989,11 @@ class Notice extends Managed_DataObject
                 }
             }
 
-            $reply_ids = $this->getReplies();
-
-            foreach ($reply_ids as $id) {
-                $rprofile = Profile::getKV('id', $id);
-                if ($rprofile instanceof Profile) {
-                    $ctx->attention[$rprofile->getUri()] = ActivityObject::PERSON;
-                }
-            }
-
-            $groups = $this->getGroups();
-
-            foreach ($groups as $group) {
-                $ctx->attention[$group->getUri()] = ActivityObject::GROUP;
+            // This covers the legacy getReplies and getGroups too which get their data
+            // from entries stored via Notice::saveNew (which we want to move away from)...
+            foreach ($this->getAttentionProfiles() as $target) {
+                // User and group profiles which get the attention of this notice
+                $ctx->attention[$target->getUri()] = $target->getObjectType();
             }
 
             switch ($this->scope) {
@@ -2131,6 +2158,11 @@ class Notice extends Managed_DataObject
             Event::handle('EndActivityObjectFromNotice', array($this, &$object));
         }
 
+        if (!$object instanceof ActivityObject) {
+            common_log(LOG_ERR, 'Notice asActivityObject created something else for uri=='._ve($this->getUri()).': '._ve($object));
+            throw new ServerException('Notice asActivityObject created something else.');
+        }
+
         return $object;
     }
 
@@ -2618,21 +2650,21 @@ class Notice extends Managed_DataObject
      */
     public static function getAsTimestamp($id)
     {
-        if (!$id) {
-            return false;
+        if (empty($id)) {
+            throw new EmptyIdException('Notice');
         }
 
-        $notice = Notice::getKV('id', $id);
-        if ($notice) {
-            return $notice->created;
+        $timestamp = null;
+        if (Event::handle('GetNoticeSqlTimestamp', array($id, &$timestamp))) {
+            // getByID throws exception if $id isn't found
+            $notice = Notice::getByID($id);
+            $timestamp = $notice->created;
         }
 
-        $deleted = Deleted_notice::getKV('id', $id);
-        if ($deleted) {
-            return $deleted->created;
+        if (empty($timestamp)) {
+            throw new ServerException('No timestamp found for Notice with id=='._ve($id));
         }
-
-        return false;
+        return $timestamp;
     }
 
     /**
@@ -2648,11 +2680,12 @@ class Notice extends Managed_DataObject
      */
     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);
+        try {
+            $since = Notice::getAsTimestamp($id);
+        } catch (Exception $e) {
+            return false;
         }
-        return false;
+        return sprintf("($createdField = '%s' and $idField > %d) or ($createdField > '%s')", $since, $id, $since);
     }
 
     /**
@@ -2687,11 +2720,12 @@ class Notice extends Managed_DataObject
      */
     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);
+        try {
+            $max = Notice::getAsTimestamp($id);
+        } catch (Exception $e) {
+            return false;
         }
-        return false;
+        return sprintf("($createdField < '%s') or ($createdField = '%s' and $idField <= %d)", $max, $max, $id);
     }
 
     /**