]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
OStatus: prep work for sending notifications on sub/unsub/join/leave/favorite/unfavor...
authorBrion Vibber <brion@pobox.com>
Fri, 12 Feb 2010 18:54:48 +0000 (18:54 +0000)
committerBrion Vibber <brion@pobox.com>
Fri, 12 Feb 2010 18:54:48 +0000 (18:54 +0000)
classes/Profile.php
plugins/OStatus/classes/Ostatus_profile.php

index 3e5150c182b56030288cabe7619b46c9f3f0626d..ab05bb8546bfe83d22ce66ce6164e509d32b6bc4 100644 (file)
@@ -755,6 +755,14 @@ class Profile extends Memcached_DataObject
         return !empty($notice);
     }
 
+    /**
+     * Returns an XML string fragment with limited profile information
+     * as an Atom <author> element.
+     *
+     * Assumes that Atom has been previously set up as the base namespace.
+     *
+     * @return string
+     */
     function asAtomAuthor()
     {
         $xs = new XMLStringer(true);
@@ -767,11 +775,33 @@ class Profile extends Memcached_DataObject
         return $xs->getString();
     }
 
+    /**
+     * Returns an XML string fragment with profile information as an
+     * Activity Streams <activity:actor> element.
+     *
+     * Assumes that 'activity' namespace has been previously defined.
+     *
+     * @return string
+     */
     function asActivityActor()
+    {
+        return $this->asActivityNoun('actor');
+    }
+
+    /**
+     * Returns an XML string fragment with profile information as an
+     * Activity Streams noun object with the given element type.
+     *
+     * Assumes that 'activity' namespace has been previously defined.
+     *
+     * @param string $element one of 'actor', 'subject', 'object', 'target'
+     * @return string
+     */
+    function asActivityNoun($element)
     {
         $xs = new XMLStringer(true);
 
-        $xs->elementStart('activity:actor');
+        $xs->elementStart('activity:' . $element);
         $xs->element(
             'activity:object-type',
             null,
@@ -799,7 +829,7 @@ class Profile extends Memcached_DataObject
             ''
         );
 
-        $xs->elementEnd('activity:actor');
+        $xs->elementEnd('activity:' . $element);
 
         return $xs->getString();
     }
index f7bbcd02869393abb2cbd55e5794e50b281371fe..733d8843b89dba5e10aff298d19389c217f13bc1 100644 (file)
@@ -299,6 +299,71 @@ class Ostatus_profile extends Memcached_DataObject
         }
     }
 
+    /**
+     * Returns an XML string fragment with profile information as an
+     * Activity Streams noun object with the given element type.
+     *
+     * Assumes that 'activity' namespace has been previously defined.
+     *
+     * @param string $element one of 'actor', 'subject', 'object', 'target'
+     * @return string
+     */
+    function asActivityNoun($element)
+    {
+        $xs = new XMLStringer(true);
+
+        $avatarHref = Avatar::defaultImage(AVATAR_PROFILE_SIZE);
+        $avatarType = 'image/png';
+        if ($this->isGroup()) {
+            $type = 'http://activitystrea.ms/schema/1.0/group';
+            $self = $this->localGroup();
+
+            // @fixme put a standard getAvatar() interface on groups too
+            if ($self->homepage_logo) {
+                $avatarHref = $self->homepage_logo;
+                $map = array('png' => 'image/png',
+                             'jpg' => 'image/jpeg',
+                             'jpeg' => 'image/jpeg',
+                             'gif' => 'image/gif');
+                $extension = pathinfo(parse_url($avatarHref, PHP_URL_PATH), PATHINFO_EXTENSION);
+                if (isset($map[$extension])) {
+                    $avatarType = $map[$extension];
+                }
+            }
+        } else {
+            $type = 'http://activitystrea.ms/schema/1.0/person';
+            $self = $this->localProfile();
+            $avatar = $self->getAvatar(AVATAR_PROFILE_SIZE);
+            if ($avatar) {
+                $avatarHref = $avatar->
+                $avatarType = $avatar->mediatype;
+            }
+        }
+        $xs->elementStart('activity:' . $element);
+        $xs->element(
+            'activity:object-type',
+            null,
+            $type
+        );
+        $xs->element(
+            'id',
+            null,
+            $this->homeuri); // ?
+        $xs->element('title', null, $self->getBestName());
+
+        $xs->element(
+            'link', array(
+                'type' => $avatarType,
+                'href' => $avatarHref
+            ),
+            ''
+        );
+
+        $xs->elementEnd('activity:' . $element);
+
+        return $xs->getString();
+    }
+
     /**
      * Damn dirty hack!
      */
@@ -397,7 +462,7 @@ class Ostatus_profile extends Memcached_DataObject
     }
 
     /**
-     * Send an unsubscription request to the hub for this feed.
+     * Send a PuSH unsubscription request to the hub for this feed.
      * The hub will later send us a confirmation POST to /main/push/callback.
      *
      * @return bool true on success, false on failure
@@ -406,6 +471,92 @@ class Ostatus_profile extends Memcached_DataObject
         return $this->subscribe('unsubscribe');
     }
 
+    /**
+     * Send an Activity Streams notification to the remote Salmon endpoint,
+     * if so configured.
+     *
+     * @param Profile $actor
+     * @param $verb eg Activity::SUBSCRIBE or Activity::JOIN
+     * @param $object object of the action; if null, the remote entity itself is assumed
+     */
+    public function notify(Profile $actor, $verb, $object=null)
+    {
+        if ($object == null) {
+            $object = $this;
+        }
+        if ($this->salmonuri) {
+            $text = 'update'; // @fixme
+            $id = 'tag:' . common_config('site', 'server') . 
+                ':' . $verb .
+                ':' . $actor->id .
+                ':' . time(); // @fixme
+
+            $entry = new Atom10Entry();
+            $entry->elementStart('entry');
+            $entry->element('id', null, $id);
+            $entry->element('title', null, $text);
+            $entry->element('summary', null, $text);
+            $entry->element('published', null, common_date_w3dtf());
+
+            $entry->element('activity:verb', null, $verb);
+            $entry->raw($profile->asAtomAuthor());
+            $entry->raw($profile->asActivityActor());
+            $entry->raw($object->asActivityNoun('object'));
+            $entry->elmentEnd('entry');
+
+            $feed = $this->atomFeed($actor);
+            $feed->initFeed();
+            $feed->addEntry($entry);
+            $feed->renderEntries();
+            $feed->endFeed();
+
+            $xml = $feed->getString();
+            common_log(LOG_INFO, "Posting to Salmon endpoint $salmon: $xml");
+
+            $salmon = new Salmon(); // ?
+            $salmon->post($this->salmonuri, $xml);
+        }
+    }
+
+    function getBestName()
+    {
+        if ($this->isGroup()) {
+            return $this->localGroup()->getBestName();
+        } else {
+            return $this->localProfile()->getBestName();
+        }
+    }
+
+    function atomFeed($actor)
+    {
+        $feed = new Atom10Feed();
+        // @fixme should these be set up somewhere else?
+        $feed->addNamespace('activity', 'http://activitystrea.ms/spec/1.0/');
+        $feed->addNamesapce('thr', 'http://purl.org/syndication/thread/1.0');
+        $feed->addNamespace('georss', 'http://www.georss.org/georss');
+        $feed->addNamespace('ostatus', 'http://ostatus.org/schema/1.0');
+
+        $taguribase = common_config('integration', 'taguri');
+        $feed->setId("tag:{$taguribase}:UserTimeline:{$actor->id}"); // ???
+
+        $feed->setTitle($actor->getBestName() . ' timeline'); // @fixme
+        $feed->setUpdated(time());
+        $feed->setPublished(time());
+
+        $feed->addLink(common_url('ApiTimelineUser',
+                                  array('id' => $actor->id,
+                                        'type' => 'atom')),
+                       array('rel' => 'self',
+                             'type' => 'application/atom+xml'));
+
+        $feed->addLink(common_url('userbyid',
+                                  array('id' => $actor->id)),
+                       array('rel' => 'alternate',
+                             'type' => 'text/html'));
+
+        return $feed;
+    }
+
     /**
      * Read and post notices for updates from the feed.
      * Currently assumes that all items in the feed are new,