]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
update activity and salmon for previous commit
authorEvan Prodromou <evan@status.net>
Sun, 14 Feb 2010 17:12:47 +0000 (12:12 -0500)
committerEvan Prodromou <evan@status.net>
Sun, 14 Feb 2010 17:12:47 +0000 (12:12 -0500)
plugins/OStatus/actions/salmon.php
plugins/OStatus/lib/activity.php

index b616027a931e7b194a20fcaf1348abe433c0b864..c79d09c95aa692e30371c55c504895df350731b2 100644 (file)
@@ -61,7 +61,7 @@ class SalmonAction extends Action
         // XXX: check that document element is Atom entry
         // XXX: check the signature
 
-        $this->act = Activity::fromAtomEntry($dom->documentElement);
+        $this->act = new Activity($dom->documentElement);
     }
 
     function handle($args)
index 36e227913466932228a88bdad2a8df0d04e860a3..11aab2848650944cf0afcf4fad21581a26758845 100644 (file)
@@ -31,7 +31,72 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-class ActivityNoun
+/**
+ * Utilities for turning DOMish things into Activityish things
+ *
+ * Some common functions that I didn't have the bandwidth to try to factor
+ * into some kind of reasonable superclass, so just dumped here. Might
+ * be useful to have an ActivityObject parent class or something.
+ *
+ * @category  OStatus
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
+ * @link      http://status.net/
+ */
+
+class ActivityUtils
+{
+    const ATOM = 'http://www.w3.org/2005/Atom';
+
+    const LINK = 'link';
+    const REL  = 'rel';
+    const TYPE = 'type';
+    const HREF = 'href';
+
+    /**
+     * Get the permalink for an Activity object
+     *
+     * @param DOMElement $element A DOM element
+     *
+     * @return string related link, if any
+     */
+
+    static function getLink($element)
+    {
+        $links = $element->getElementsByTagnameNS(self::ATOM, self::LINK);
+
+        foreach ($links as $link) {
+            if ($link->getAttributeNS(self::ATOM, self::REL) == 'alternate' &&
+                $link->getAttributeNS(self::ATOM, self::TYPE) == 'text/html') {
+                return $link->getAttributeNS(self::ATOM, self::HREF);
+            }
+        }
+
+        return null;
+    }
+}
+
+/**
+ * A noun-ish thing in the activity universe
+ *
+ * The activity streams spec talks about activity objects, while also having
+ * a tag activity:object, which is in fact an activity object. Aaaaaah!
+ *
+ * This is just a thing in the activity universe. Can be the subject, object,
+ * or indirect object (target!) of an activity verb. Rotten name, and I'm
+ * propagating it. *sigh*
+ *
+ * @category  OStatus
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
+ * @link      http://status.net/
+ */
+
+class ActivityObject
 {
     const ARTICLE   = 'http://activitystrea.ms/schema/1.0/article';
     const BLOGENTRY = 'http://activitystrea.ms/schema/1.0/blog-entry';
@@ -47,19 +112,101 @@ class ActivityNoun
     const PERSON    = 'http://activitystrea.ms/schema/1.0/person';
     const GROUP     = 'http://activitystrea.ms/schema/1.0/group';
     const PLACE     = 'http://activitystrea.ms/schema/1.0/place';
-    const COMMENT   = 'http://activitystrea.ms/schema/1.0/comment'; // tea
+    const COMMENT   = 'http://activitystrea.ms/schema/1.0/comment';
+    // ^^^^^^^^^^ tea!
+
+    // Atom elements we snarf
+
+    const TITLE   = 'title';
+    const SUMMARY = 'summary';
+    const CONTENT = 'content';
+    const ID      = 'id';
+    const SOURCE  = 'source';
+
+    const NAME = 'name';
+    const URI  = 'uri';
 
     public $type;
     public $id;
     public $title;
     public $summary;
     public $content;
+    public $link;
+    public $source;
+
+    /**
+     * Constructor
+     *
+     * This probably needs to be refactored
+     * to generate a local class (ActivityPerson, ActivityFile, ...)
+     * based on the object type.
+     *
+     * @param DOMElement $element DOM thing to turn into an Activity thing
+     */
+
+    function __construct($element)
+    {
+        $this->source = $element;
+
+        if ($element->tagName == 'author') {
+
+            $this->type  = self::PERSON; // XXX: is this fair?
+            $this->title = $this->_childContent($element, self::NAME);
+            $this->id    = $this->_childContent($element, self::URI);
+
+        } else {
+
+            $this->type = $this->_childContent($element, Activity::OBJECTTYPE,
+                                               Activity::SPEC);
+
+            $this->id      = $this->_childContent($element, self::ID);
+            $this->title   = $this->_childContent($element, self::TITLE);
+            $this->summary = $this->_childContent($element, self::SUMMARY);
+            $this->content = $this->_childContent($element, self::CONTENT);
+            $this->source  = $this->_childContent($element, self::SOURCE);
+
+            $this->link = ActivityUtils::getLink($element);
+
+            // XXX: grab PoCo stuff
+        }
+    }
+
+    /**
+     * Grab the text content of a DOM element child of the current element
+     *
+     * @param DOMElement $element   Element whose children we examine
+     * @param string     $tag       Tag to look up
+     * @param string     $namespace Namespace to use, defaults to Atom
+     *
+     * @return string content of the child
+     */
+
+    private function _childContent($element, $tag, $namespace=Activity::ATOM)
+    {
+        $els = $element->getElementsByTagnameNS($namespace, $tag);
+
+        if (empty($els) || $els->length == 0) {
+            return null;
+        } else {
+            $el = $els->item(0);
+            return $el->textContent;
+        }
+    }
 }
 
-class Activity
-{
-    const NAMESPACE = 'http://activitystrea.ms/schema/1.0/';
+/**
+ * Utility class to hold a bunch of constant defining default verb types
+ *
+ * @category  OStatus
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
+ * @link      http://status.net/
+ */
 
+class ActivityVerb
+{
     const POST     = 'http://activitystrea.ms/schema/1.0/post';
     const SHARE    = 'http://activitystrea.ms/schema/1.0/share';
     const SAVE     = 'http://activitystrea.ms/schema/1.0/save';
@@ -69,17 +216,151 @@ class Activity
     const FRIEND   = 'http://activitystrea.ms/schema/1.0/make-friend';
     const JOIN     = 'http://activitystrea.ms/schema/1.0/join';
     const TAG      = 'http://activitystrea.ms/schema/1.0/tag';
+}
+
+/**
+ * An activity in the ActivityStrea.ms world
+ *
+ * An activity is kind of like a sentence: someone did something
+ * to something else.
+ *
+ * 'someone' is the 'actor'; 'did something' is the verb;
+ * 'something else' is the object.
+ *
+ * @category  OStatus
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
+ * @link      http://status.net/
+ */
+
+class Activity
+{
+    const SPEC   = 'http://activitystrea.ms/spec/1.0/';
+    const SCHEMA = 'http://activitystrea.ms/schema/1.0/';
+
+    const VERB       = 'verb';
+    const OBJECT     = 'object';
+    const ACTOR      = 'actor';
+    const SUBJECT    = 'subject';
+    const OBJECTTYPE = 'object-type';
+    const CONTEXT    = 'context';
+    const TARGET     = 'target';
+
+    const ATOM = 'http://www.w3.org/2005/Atom';
 
-    public $actor; // an ActivityNoun
-    public $verb;  // a string (the URL)
-    public $object; // an ActivityNoun
-    public $target; // an ActivityNoun
+    const AUTHOR    = 'author';
+    const PUBLISHED = 'published';
 
-    static function fromAtomEntry($domEntry)
+    public $actor;   // an ActivityObject
+    public $verb;    // a string (the URL)
+    public $object;  // an ActivityObject
+    public $target;  // an ActivityObject
+    public $context; // an ActivityObject
+    public $time;    // Time of the activity
+    public $link;    // an ActivityObject
+    public $entry;   // the source entry
+    public $feed;    // the source feed
+
+    /**
+     * Turns a regular old Atom <entry> into a magical activity
+     *
+     * @param DOMElement $entry Atom entry to poke at
+     * @param DOMElement $feed  Atom feed, for context
+     */
+
+    function __construct($entry, $feed = null)
     {
+        $this->entry = $entry;
+        $this->feed  = $feed;
+
+        $pubEl = $this->_child($entry, self::PUBLISHED, self::ATOM);
+
+        if (!empty($pubEl)) {
+            $this->time = strtotime($pubEl->textContent);
+        } else {
+            // XXX technically an error; being liberal. Good idea...?
+            $this->time = null;
+        }
+
+        $this->link = ActivityUtils::getLink($entry);
+
+        $verbEl = $this->_child($entry, self::VERB);
+
+        if (!empty($verbEl)) {
+            $this->verb = trim($verbEl->textContent);
+        } else {
+            $this->verb = ActivityVerb::POST;
+            // XXX: do other implied stuff here
+        }
+
+        $objectEl = $this->_child($entry, self::OBJECT);
+
+        if (!empty($objectEl)) {
+            $this->object = new ActivityObject($objectEl);
+        } else {
+            $this->object = new ActivityObject($entry);
+        }
+
+        $actorEl = $this->_child($entry, self::ACTOR);
+
+        if (!empty($actorEl)) {
+
+            $this->actor = new ActivityObject($actorEl);
+
+        } else if (!empty($feed) &&
+                   $subjectEl = $this->_child($feed, self::SUBJECT)) {
+
+            $this->actor = new ActivityObject($subjectEl);
+
+        } else if ($authorEl = $this->_child($entry, self::AUTHOR, self::ATOM)) {
+
+            $this->actor = new ActivityObject($authorEl);
+        }
+
+        $contextEl = $this->_child($entry, self::CONTEXT);
+
+        if (!empty($contextEl)) {
+            $this->context = new ActivityObject($contextEl);
+        }
+
+        $targetEl = $this->_child($entry, self::TARGET);
+
+        if (!empty($targetEl)) {
+            $this->target = new ActivityObject($targetEl);
+        }
     }
 
+    /**
+     * Returns an Atom <entry> based on this activity
+     *
+     * @return DOMElement Atom entry
+     */
+
     function toAtomEntry()
     {
+        return null;
     }
-}
+
+    /**
+     * Gets the first child element with the given tag
+     *
+     * @param DOMElement $element   element to pick at
+     * @param string     $tag       tag to look for
+     * @param string     $namespace Namespace to look under
+     *
+     * @return DOMElement found element or null
+     */
+
+    private function _child($element, $tag, $namespace=self::SPEC)
+    {
+        $els = $element->getElementsByTagnameNS($namespace, $tag);
+
+        if (empty($els) || $els->length == 0) {
+            return null;
+        } else {
+            return $els->item(0);
+        }
+    }
+}
\ No newline at end of file