]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Most of the activityobject-saving for Favorite implemented
authorMikael Nordfeldth <mmn@hethane.se>
Tue, 1 Jul 2014 21:25:58 +0000 (23:25 +0200)
committerMikael Nordfeldth <mmn@hethane.se>
Wed, 2 Jul 2014 09:38:55 +0000 (11:38 +0200)
lib/activityhandlerplugin.php
plugins/Favorite/FavoritePlugin.php
plugins/Favorite/classes/Fave.php

index c8a46ae5efc4b55d9523a9bf387dc6b7c66adc97..d972d175520cbf82cd73f70cf6d31799af618626 100644 (file)
@@ -110,7 +110,8 @@ abstract class ActivityHandlerPlugin extends Plugin
      * and any additional data structures you require.
      *
      * This function is deprecated and in the future, Notice::saveActivity
-     * should be called from onStartHandleFeedEntryWithProfile in this class.
+     * should be called from onStartHandleFeedEntryWithProfile in this class
+     * (which instead turns to saveObjectFromActivity).
      *
      * @param Activity $activity
      * @param Profile $actor
@@ -121,7 +122,8 @@ abstract class ActivityHandlerPlugin extends Plugin
     public function saveNoticeFromActivity(Activity $activity, Profile $actor, array $options=array())
     {
         // Any plugin which has not implemented saveObjectFromActivity _must_
-        // override this function (which will be deleted when all plugins are migrated).
+        // override this function until they are migrated (this function will
+        // be deleted when all plugins are migrated to saveObjectFromActivity).
 
         if (isset($this->oldSaveNew)) {
             throw new ServerException('A function has been called for new saveActivity functionality, but is still set with an oldSaveNew configuration');
@@ -130,6 +132,37 @@ abstract class ActivityHandlerPlugin extends Plugin
         return Notice::saveActivity($activity, $actor, $options);
     }
 
+    /**
+    * Given a parsed ActivityStreams activity, your plugin gets
+    * to figure out itself how to store the additional data into
+    * the database, besides the base data stored by the core.
+    *
+    * This will handle just about all events where an activity
+    * object gets saved, whether it is via AtomPub, OStatus
+    * (PuSH and Salmon transports), or ActivityStreams-based
+    * backup/restore of account data.
+    *
+    * You should be able to accept as input the output from an
+    * asActivity() call on the stored object. Where applicable,
+    * try to use existing ActivityStreams structures and object
+    * types, and be liberal in accepting input from what might
+    * be other compatible apps.
+    *
+    * All micro-app classes must override this method.
+    *
+    * @fixme are there any standard options?
+    *
+    * @param Activity $activity
+    * @param Profile $actor
+    * @param array $options=array()
+    *
+    * @return Notice the resulting notice
+    */
+    public function saveObjectFromActivity(Activity $activity, Notice $stored, array $options=array())
+    {
+        throw new ServerException('This function should be abstract when all plugins have migrated to saveObjectFromActivity');
+    }
+
     /*
      * This usually gets called from Notice::saveActivity after a Notice object has been created,
      * so it contains a proper id and a uri for the object to be saved.
@@ -252,7 +285,11 @@ abstract class ActivityHandlerPlugin extends Plugin
             return true;
         }
 
-        $object = $this->activityObjectFromNotice($notice);
+        try {
+            $object = $this->activityObjectFromNotice($notice);
+        } catch (NoResultException $e) {
+            $object = null; // because getKV returns null on failure
+        }
         return false;
     }
 
index 6248b332c41d3fd6e5d704b8984d855dc437a661..18aa32738b6b866d8ba46d0f5d8e7e5ca519eb13 100644 (file)
@@ -151,12 +151,53 @@ class FavoritePlugin extends ActivityHandlerPlugin
     {
     }
 
+    // FIXME: Set this to abstract public when all plugins have migrated!
+    public function saveObjectFromActivity(Activity $activity, Notice $stored, array $options=array())  
+    {
+        assert($this->isMyActivity($act));
+        $actor = $stored->getProfile();
+        $uris = array();
+        if (count($act->objects) != 1) {
+            // TRANS: Exception thrown when a favor activity has anything but 1 object
+            throw new ClientException(_('Favoring activites can only be done one at a time'));
+        }
+
+        $obj = $act->objects[0];
+        $type = isset($obj->type) ? ActivityUtils::resolveUri($obj->type, true) : ActivityObject::NOTE;
+        $uris = $obj->getIdentifiers();
+        try {
+            $local = ActivityUtils::findLocalObject($uris, $type);
+        } catch (Exception $e) {
+            // TODO: if it's not available locally, we should import the favorited object!
+            common_debug('Could not find favored notice locally: '.var_export($uris,true));
+            return null;
+        }
+
+        if (!empty($act->time)) {
+            // This should reasonably mean that it was created on our instance.
+            $options['created'] = common_sql_date($act->time);
+        }
+
+        $options['uri'] = !empty($act->id) ? $act->id : $act->selfLink;
+        $object = Fave::saveNew($actor, $local, $type, $options);
+        return $object;
+    }
+
+
     public function activityObjectFromNotice(Notice $notice)
     {
+        $fave = Fave::fromStored($notice);
+        return $fave->asActivityObject();
     }
 
     public function deleteRelated(Notice $notice)
     {
+        try {
+            $fave = Fave::fromStored($notice);
+            $fave->delete();
+        } catch (NoResultException $e) {
+            // Cool, no problem. We wanted to get rid of it anyway.
+        }
     }
 
     // API stuff
@@ -196,15 +237,15 @@ class FavoritePlugin extends ActivityHandlerPlugin
     {
         parent::onNoticeDeleteRelated($notice);
 
-        // The below algorithm is because we have faves not stored as
-        // proper activities in Notice from legacy versions of SN/GNU social
+        // The below algorithm is because we want to delete fave
+        // activities on any notice which _has_ faves, and not as
+        // in the parent function only ones that _are_ faves.
 
         $fave = new Fave();
         $fave->notice_id = $notice->id;
 
         if ($fave->find()) {
             while ($fave->fetch()) {
-                Fave::blowCacheForProfileId($fave->user_id);
                 $fave->delete();
             }
         }
index 089cafc884e5edd9693a2a3560543368bfad6bd8..0801ef8717d3a8f569c3481fd44bf9fc0a778820 100644 (file)
@@ -2,22 +2,16 @@
 /**
  * Table Definition for fave
  */
-require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
 
 class Fave extends Managed_DataObject
 {
-    ###START_AUTOCODE
-    /* the code below is auto generated do not remove the above tag */
-
     public $__table = 'fave';                            // table name
     public $notice_id;                       // int(4)  primary_key not_null
     public $user_id;                         // int(4)  primary_key not_null
     public $uri;                             // varchar(255)
+    public $created;                         // datetime  multiple_key not_null
     public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 
-    /* the code above is auto generated do not remove the tag below */
-    ###END_AUTOCODE
-
     public static function schemaDef()
     {
         return array(
@@ -25,6 +19,7 @@ class Fave extends Managed_DataObject
                 'notice_id' => array('type' => 'int', 'not null' => true, 'description' => 'notice that is the favorite'),
                 'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user who likes this notice'),
                 'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universally unique identifier, usually a tag URI'),
+                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
                 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
             ),
             'primary key' => array('notice_id', 'user_id'),
@@ -61,11 +56,15 @@ class Fave extends Managed_DataObject
 
             $fave->user_id   = $profile->id;
             $fave->notice_id = $notice->id;
+            $fave->created   = common_sql_now();
             $fave->modified  = common_sql_now();
-            $fave->uri       = self::newURI($fave->user_id,
-                                            $fave->notice_id,
-                                            $fave->modified);
-            if (!$fave->insert()) {
+            $fave->uri       = self::newURI($profile,
+                                            $notice,
+                                            $fave->created);
+
+            try {
+                $fave->insert();
+            } catch (ServerException $e) {
                 common_log_db_error($fave, 'INSERT', __FILE__);
                 return false;
             }
@@ -79,7 +78,17 @@ class Fave extends Managed_DataObject
         return $fave;
     }
 
-    function delete($useWhere=false)
+    // exception throwing takeover!
+    public function insert() {
+        if (!parent::insert()) {
+            throw new ServerException(sprintf(_m('Could not store new object of type %s'), get_called_class()));
+        }
+        self::blowCacheForProfileId($this->user_id);
+        self::blowCacheForNoticeId($this->notice_id);
+        return $this;
+    }
+
+    public function delete($useWhere=false)
     {
         $profile = Profile::getKV('id', $this->user_id);
         $notice  = Notice::getKV('id', $this->notice_id);
@@ -215,24 +224,6 @@ class Fave extends Managed_DataObject
         return $cnt;
     }
 
-    function getURI()
-    {
-        if (!empty($this->uri)) {
-            return $this->uri;
-        } else {
-            return self::newURI($this->user_id, $this->notice_id, $this->modified);
-        }
-    }
-
-    static function newURI($profile_id, $notice_id, $modified)
-    {
-        return TagURI::mint('favor:%d:%d:%s',
-                            $profile_id,
-                            $notice_id,
-                            common_date_iso8601($modified));
-    }
-
-
     static protected $_faves = array();
 
     /**
@@ -276,4 +267,112 @@ class Fave extends Managed_DataObject
             $cache->delete(Cache::key('fave:list-ids:notice_id:'.$notice_id));
         }
     }
+
+    // Remember that we want the _activity_ notice here, not faves applied
+    // to the supplied Notice (as with byNotice)!
+    static public function fromStored(Notice $stored) {
+        $class = get_called_class();
+        $object = new $class;
+        $object->uri = $stored->uri;
+        if (!$object->find(true)) {
+            throw new NoResultException($object);
+        }
+        return $object;
+    }
+
+    static public function verbToTitle($verb) {
+        return ucfirst($verb);
+    }
+
+    static public function object_type()
+    {
+        return 'activity';
+    }
+
+    public function asActivityObject(Profile $scoped=null) {
+        $actobj = new ActivityObject();
+        $actobj->id = $this->getUri();
+        $actobj->type = ActivityUtils::resolveUri(ActivityObject::ACTIVITY);
+        $actobj->actor = $this->getActorObject();
+        $actobj->objects = array(clone($actobj->target));
+        $actobj->title = Stored_ActivityVerb::verbToTitle($this->verb);
+        //$actobj->verb = $this->verb;
+        //$actobj->target = $this->getTargetObject();
+        return $actobj;
+    }
+
+    static public function parseActivityObject(ActivityObject $actobj, Notice $stored) {
+        $actor = $stored->getProfile();
+        $object = new Fave();
+        $object->user_id = $actor->id;
+        $object->notice_id = $stored->id;
+        $object->object_uri = $stored->uri;
+        $object->created = $stored->created;
+        return $object;
+    }
+
+    static function saveActivityObject(ActivityObject $actobj, Notice $stored) {
+        $object = self::parseActivityObject($actobj, $stored);
+        $object->insert();  // exception throwing!
+        return $object;
+    }
+
+
+    public function getTarget() {
+        // throws exception on failure
+        return ActivityUtils::findLocalObject(array($this->uri), $this->type);
+    }
+
+    public function getTargetObject() {
+        return $this->getTarget()->asActivityObject();
+    }
+
+    protected $_stored = array();
+
+    public function getStored() {
+        if (!isset($this->_stored[$this->uri])) {
+            $stored = new Notice();
+            $stored->uri = $this->uri;
+            if (!$stored->find(true)) {
+                throw new NoResultException($stored);
+            }
+            $this->_stored[$this->uri] = $stored;
+        }
+        return $this->_stored[$this->uri];
+    }
+
+    public function getActor() {
+        $profile = new Profile();
+        $profile->id = $this->user_id;
+        if (!$profile->find(true)) {
+            throw new NoResultException($profile);
+        }
+        return $profile;
+    }
+
+    public function getActorObject() {
+        return $this->getActor()->asActivityObject();
+    }
+
+    public function getURI()
+    {
+        if (!empty($this->uri)) {
+            return $this->uri;
+        }
+
+        // We (should've in this case) created it ourselves, so we tag it ourselves
+        return self::newURI($this->getActor(), $this->getTarget(), $this->created);
+    }
+
+    static function newURI(Profile $actor, Managed_DataObject $target, $created=null)
+    {
+        if (is_null($created)) {
+            $created = common_sql_now();
+        }
+        return TagURI::mint(strtolower(get_called_class()).':%d:%s:%d:%s',
+                                        $actor->id,
+                                        ActivityUtils::resolveUri(self::object_type(), true),
+                                        $target->id,
+                                        common_date_iso8601($created));
+    }
 }