update activity and salmon for previous commit

This commit is contained in:
Evan Prodromou 2010-02-14 12:12:47 -05:00
parent cea7d8018a
commit f78cf31303
2 changed files with 293 additions and 12 deletions

View File

@ -61,7 +61,7 @@ class SalmonAction extends Action
// XXX: check that document element is Atom entry // XXX: check that document element is Atom entry
// XXX: check the signature // XXX: check the signature
$this->act = Activity::fromAtomEntry($dom->documentElement); $this->act = new Activity($dom->documentElement);
} }
function handle($args) function handle($args)

View File

@ -31,7 +31,72 @@ if (!defined('STATUSNET')) {
exit(1); 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 ARTICLE = 'http://activitystrea.ms/schema/1.0/article';
const BLOGENTRY = 'http://activitystrea.ms/schema/1.0/blog-entry'; 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 PERSON = 'http://activitystrea.ms/schema/1.0/person';
const GROUP = 'http://activitystrea.ms/schema/1.0/group'; const GROUP = 'http://activitystrea.ms/schema/1.0/group';
const PLACE = 'http://activitystrea.ms/schema/1.0/place'; 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 $type;
public $id; public $id;
public $title; public $title;
public $summary; public $summary;
public $content; 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 /**
{ * Utility class to hold a bunch of constant defining default verb types
const NAMESPACE = 'http://activitystrea.ms/schema/1.0/'; *
* @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 POST = 'http://activitystrea.ms/schema/1.0/post';
const SHARE = 'http://activitystrea.ms/schema/1.0/share'; const SHARE = 'http://activitystrea.ms/schema/1.0/share';
const SAVE = 'http://activitystrea.ms/schema/1.0/save'; 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 FRIEND = 'http://activitystrea.ms/schema/1.0/make-friend';
const JOIN = 'http://activitystrea.ms/schema/1.0/join'; const JOIN = 'http://activitystrea.ms/schema/1.0/join';
const TAG = 'http://activitystrea.ms/schema/1.0/tag'; const TAG = 'http://activitystrea.ms/schema/1.0/tag';
}
public $actor; // an ActivityNoun /**
public $verb; // a string (the URL) * An activity in the ActivityStrea.ms world
public $object; // an ActivityNoun *
public $target; // an ActivityNoun * 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/
*/
static function fromAtomEntry($domEntry) 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';
const AUTHOR = 'author';
const PUBLISHED = 'published';
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() 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);
}
} }
} }