if (!empty($this->formatted)) {
$xs = new XMLStringer(true);
$xs->elementStart('poco:address');
- $xs->element('poco:formatted', null, $this->formatted);
+ $xs->element('poco:formatted', null, common_xml_safe_str($this->formatted));
$xs->elementEnd('poco:address');
return $xs->getString();
}
PoCo::NS
);
- array_push($urls, new PoCoURL($type, $value, $primary));
+ $isPrimary = false;
+
+ if (isset($primary) && $primary == 'true') {
+ $isPrimary = true;
+ }
+
+ // @todo check to make sure a primary hasn't already been added
+
+ array_push($urls, new PoCoURL($type, $value, $isPrimary));
}
return $urls;
}
PoCo::NS
);
- $formatted = ActivityUtils::childContent(
- $addressEl,
- PoCoAddress::FORMATTED,
- self::NS
- );
+ if (!empty($addressEl)) {
+ $formatted = ActivityUtils::childContent(
+ $addressEl,
+ PoCoAddress::FORMATTED,
+ self::NS
+ );
- if (!empty($formatted)) {
- $address = new PoCoAddress();
- $address->formatted = $formatted;
- return $address;
+ if (!empty($formatted)) {
+ $address = new PoCoAddress();
+ $address->formatted = $formatted;
+ return $address;
+ }
}
return null;
return $poco;
}
+ function fromGroup($group)
+ {
+ if (empty($group)) {
+ return null;
+ }
+
+ $poco = new PoCo();
+
+ $poco->preferredUsername = $group->nickname;
+ $poco->displayName = $group->getBestName();
+
+ $poco->note = $group->description;
+
+ $paddy = new PoCoAddress();
+ $paddy->formatted = $group->location;
+ $poco->address = $paddy;
+
+ if (!empty($group->homepage)) {
+ array_push(
+ $poco->urls,
+ new PoCoURL(
+ 'homepage',
+ $group->homepage,
+ true
+ )
+ );
+ }
+
+ return $poco;
+ }
+
+ function getPrimaryURL()
+ {
+ foreach ($this->urls as $url) {
+ if ($url->primary) {
+ return $url;
+ }
+ }
+ }
+
function asString()
{
$xs = new XMLStringer(true);
);
if (!empty($this->note)) {
- $xs->element('poco:note', null, $this->note);
+ $xs->element('poco:note', null, common_xml_safe_str($this->note));
}
if (!empty($this->address)) {
* @return string related link, if any
*/
- static function getLink($element, $rel, $type=null)
+ static function getLink(DOMNode $element, $rel, $type=null)
{
- $links = $element->getElementsByTagnameNS(self::ATOM, self::LINK);
+ $els = $element->childNodes;
- foreach ($links as $link) {
+ foreach ($els as $link) {
+
+ if (!($link instanceof DOMElement)) {
+ continue;
+ }
- $linkRel = $link->getAttribute(self::REL);
- $linkType = $link->getAttribute(self::TYPE);
+ if ($link->localName == self::LINK && $link->namespaceURI == self::ATOM) {
- if ($linkRel == $rel &&
- (is_null($type) || $linkType == $type)) {
- return $link->getAttribute(self::HREF);
+ $linkRel = $link->getAttribute(self::REL);
+ $linkType = $link->getAttribute(self::TYPE);
+
+ if ($linkRel == $rel &&
+ (is_null($type) || $linkType == $type)) {
+ return $link->getAttribute(self::HREF);
+ }
}
}
return null;
}
+ static function getLinks(DOMNode $element, $rel, $type=null)
+ {
+ $els = $element->childNodes;
+ $out = array();
+
+ foreach ($els as $link) {
+ if ($link->localName == self::LINK && $link->namespaceURI == self::ATOM) {
+
+ $linkRel = $link->getAttribute(self::REL);
+ $linkType = $link->getAttribute(self::TYPE);
+
+ if ($linkRel == $rel &&
+ (is_null($type) || $linkType == $type)) {
+ $out[] = $link;
+ }
+ }
+ }
+
+ return $out;
+ }
+
/**
* Gets the first child element with the given tag
*
* @return DOMElement found element or null
*/
- static function child($element, $tag, $namespace=self::ATOM)
+ static function child(DOMNode $element, $tag, $namespace=self::ATOM)
{
$els = $element->childNodes;
if (empty($els) || $els->length == 0) {
* @return string content of the child
*/
- static function childContent($element, $tag, $namespace=self::ATOM)
+ static function childContent(DOMNode $element, $tag, $namespace=self::ATOM)
{
$el = self::child($element, $tag, $namespace);
// slavishly following http://atompub.org/rfc4287.html#rfc.section.4.1.3.3
- if ($type == 'text') {
- return $contentEl->textContent;
+ if (empty($type) || $type == 'text') {
+ // Plain text source -- let's turn it into HTML!
+ return htmlspecialchars($contentEl->textContent);
} else if ($type == 'html') {
- $text = $contentEl->textContent;
- return htmlspecialchars_decode($text, ENT_QUOTES);
+ // The XML text decoding gives us an HTML string ready to roll.
+ return $contentEl->textContent;
} else if ($type == 'xhtml') {
- $divEl = ActivityUtils::child($contentEl, 'div');
+ // Embedded XHTML; we have to pull it out of the document tree,
+ // then serialize it back out to an HTML fragment string.
+ $divEl = ActivityUtils::child($contentEl, 'div', 'http://www.w3.org/1999/xhtml');
if (empty($divEl)) {
return null;
}
$text .= $doc->saveXML($child);
}
return trim($text);
- } else if (in_array(array('text/xml', 'application/xml'), $type) ||
+ } else if (in_array($type, array('text/xml', 'application/xml')) ||
preg_match('#(+|/)xml$#', $type)) {
throw new ClientException(_("Can't handle embedded XML content yet."));
} else if (strncasecmp($type, 'text/', 5)) {
}
}
+// XXX: Arg! This wouldn't be necessary if we used Avatars conistently
+class AvatarLink
+{
+ public $url;
+ public $type;
+ public $size;
+ public $width;
+ public $height;
+
+ function __construct($element=null)
+ {
+ if ($element) {
+ // @fixme use correct namespaces
+ $this->url = $element->getAttribute('href');
+ $this->type = $element->getAttribute('type');
+ $width = $element->getAttribute('media:width');
+ if ($width != null) {
+ $this->width = intval($width);
+ }
+ $height = $element->getAttribute('media:height');
+ if ($height != null) {
+ $this->height = intval($height);
+ }
+ }
+ }
+
+ static function fromAvatar($avatar)
+ {
+ if (empty($avatar)) {
+ return null;
+ }
+ $alink = new AvatarLink();
+ $alink->type = $avatar->mediatype;
+ $alink->height = $avatar->height;
+ $alink->width = $avatar->width;
+ $alink->url = $avatar->displayUrl();
+ return $alink;
+ }
+
+ static function fromFilename($filename, $size)
+ {
+ $alink = new AvatarLink();
+ $alink->url = $filename;
+ $alink->height = $size;
+ if (!empty($filename)) {
+ $alink->width = $size;
+ $alink->type = self::mediatype($filename);
+ } else {
+ $alink->url = User_group::defaultLogo($size);
+ $alink->type = 'image/png';
+ }
+ return $alink;
+ }
+
+ // yuck!
+ static function mediatype($filename) {
+ $ext = strtolower(end(explode('.', $filename)));
+ if ($ext == 'jpeg') {
+ $ext = 'jpg';
+ }
+ // hope we don't support any others
+ $types = array('png', 'gif', 'jpg', 'jpeg');
+ if (in_array($ext, $types)) {
+ return 'image/' . $ext;
+ }
+ return null;
+ }
+}
+
/**
* A noun-ish thing in the activity universe
*
public $content;
public $link;
public $source;
- public $avatar;
+ public $avatarLinks = array();
public $geopoint;
public $poco;
public $displayName;
$this->element = $element;
+ $this->geopoint = $this->_childContent(
+ $element,
+ ActivityContext::POINT,
+ ActivityContext::GEORSS
+ );
+
if ($element->tagName == 'author') {
+ $this->_fromAuthor($element);
+ } else if ($element->tagName == 'item') {
+ $this->_fromRssItem($element);
+ } else {
+ $this->_fromAtomEntry($element);
+ }
- $this->type = self::PERSON; // XXX: is this fair?
- $this->title = $this->_childContent($element, self::NAME);
- $this->id = $this->_childContent($element, self::URI);
+ // Some per-type attributes...
+ if ($this->type == self::PERSON || $this->type == self::GROUP) {
+ $this->displayName = $this->title;
- if (empty($this->id)) {
- $email = $this->_childContent($element, self::EMAIL);
- if (!empty($email)) {
- // XXX: acct: ?
- $this->id = 'mailto:'.$email;
+ $photos = ActivityUtils::getLinks($element, 'photo');
+ if (count($photos)) {
+ foreach ($photos as $link) {
+ $this->avatarLinks[] = new AvatarLink($link);
+ }
+ } else {
+ $avatars = ActivityUtils::getLinks($element, 'avatar');
+ foreach ($avatars as $link) {
+ $this->avatarLinks[] = new AvatarLink($link);
}
}
+ $this->poco = new PoCo($element);
+ }
+ }
+
+ private function _fromAuthor($element)
+ {
+ $this->type = self::PERSON; // XXX: is this fair?
+ $this->title = $this->_childContent($element, self::NAME);
+ $this->id = $this->_childContent($element, self::URI);
+
+ if (empty($this->id)) {
+ $email = $this->_childContent($element, self::EMAIL);
+ if (!empty($email)) {
+ // XXX: acct: ?
+ $this->id = 'mailto:'.$email;
+ }
+ }
+ }
+
+ private function _fromAtomEntry($element)
+ {
+ $this->type = $this->_childContent($element, Activity::OBJECTTYPE,
+ Activity::SPEC);
+
+ if (empty($this->type)) {
+ $this->type = ActivityObject::NOTE;
+ }
+
+ $this->id = $this->_childContent($element, self::ID);
+ $this->title = $this->_childContent($element, self::TITLE);
+ $this->summary = $this->_childContent($element, self::SUMMARY);
+
+ $this->source = $this->_getSource($element);
+
+ $this->content = ActivityUtils::getContent($element);
+
+ $this->link = ActivityUtils::getPermalink($element);
+ }
+
+ // @fixme rationalize with Activity::_fromRssItem()
+
+ private function _fromRssItem($item)
+ {
+ $this->title = ActivityUtils::childContent($item, ActivityObject::TITLE, Activity::RSS);
+
+ $contentEl = ActivityUtils::child($item, ActivityUtils::CONTENT, Activity::CONTENTNS);
+
+ if (!empty($contentEl)) {
+ $this->content = htmlspecialchars_decode($contentEl->textContent, ENT_QUOTES);
} else {
+ $descriptionEl = ActivityUtils::child($item, Activity::DESCRIPTION, Activity::RSS);
+ if (!empty($descriptionEl)) {
+ $this->content = htmlspecialchars_decode($descriptionEl->textContent, ENT_QUOTES);
+ }
+ }
+
+ $this->link = ActivityUtils::childContent($item, ActivityUtils::LINK, Activity::RSS);
- $this->type = $this->_childContent($element, Activity::OBJECTTYPE,
- Activity::SPEC);
+ $guidEl = ActivityUtils::child($item, Activity::GUID, Activity::RSS);
- if (empty($this->type)) {
- $this->type = ActivityObject::NOTE;
+ if (!empty($guidEl)) {
+ $this->id = $guidEl->textContent;
+
+ if ($guidEl->hasAttribute('isPermaLink')) {
+ // overwrites <link>
+ $this->link = $this->id;
}
+ }
+ }
+
+ public static function fromRssAuthor($el)
+ {
+ $text = $el->textContent;
+
+ if (preg_match('/^(.*?) \((.*)\)$/', $text, $match)) {
+ $email = $match[1];
+ $name = $match[2];
+ } else if (preg_match('/^(.*?) <(.*)>$/', $text, $match)) {
+ $name = $match[1];
+ $email = $match[2];
+ } else if (preg_match('/.*@.*/', $text)) {
+ $email = $text;
+ $name = null;
+ } else {
+ $name = $text;
+ $email = null;
+ }
- $this->id = $this->_childContent($element, self::ID);
- $this->title = $this->_childContent($element, self::TITLE);
- $this->summary = $this->_childContent($element, self::SUMMARY);
+ // Not really enough info
- $this->source = $this->_getSource($element);
+ $obj = new ActivityObject();
- $this->content = ActivityUtils::getContent($element);
+ $obj->element = $el;
- $this->link = ActivityUtils::getPermalink($element);
+ $obj->type = ActivityObject::PERSON;
+ $obj->title = $name;
+ if (!empty($email)) {
+ $obj->id = 'mailto:'.$email;
}
- // Some per-type attributes...
- if ($this->type == self::PERSON || $this->type == self::GROUP) {
- $this->displayName = $this->title;
+ return $obj;
+ }
- // @fixme we may have multiple avatars with different resolutions specified
- $this->avatar = ActivityUtils::getLink($element, 'avatar');
+ public static function fromDcCreator($el)
+ {
+ // Not really enough info
- $this->poco = new PoCo($element);
+ $text = $el->textContent;
+
+ $obj = new ActivityObject();
+
+ $obj->element = $el;
+
+ $obj->title = $text;
+ $obj->type = ActivityObject::PERSON;
+
+ return $obj;
+ }
+
+ public static function fromRssChannel($el)
+ {
+ $obj = new ActivityObject();
+
+ $obj->element = $el;
+
+ $obj->type = ActivityObject::PERSON; // @fixme guess better
+
+ $obj->title = ActivityUtils::childContent($el, ActivityObject::TITLE, self::RSS);
+ $obj->link = ActivityUtils::childContent($el, ActivityUtils::LINK, self::RSS);
+ $obj->id = ActivityUtils::getLink($el, self::SELF);
+
+ $desc = ActivityUtils::childContent($el, self::DESCRIPTION, self::RSS);
+
+ if (!empty($desc)) {
+ $obj->content = htmlspecialchars_decode($desc, ENT_QUOTES);
}
+
+ $imageEl = ActivityUtils::child($el, self::IMAGE, self::RSS);
+
+ if (!empty($imageEl)) {
+ $obj->avatarLinks[] = ActivityUtils::childContent($imageEl, self::URL, self::RSS);
+ }
+
+ return $obj;
}
private function _childContent($element, $tag, $namespace=ActivityUtils::ATOM)
}
}
- static function fromNotice($notice)
+ static function fromNotice(Notice $notice)
{
$object = new ActivityObject();
return $object;
}
- static function fromProfile($profile)
+ static function fromProfile(Profile $profile)
{
$object = new ActivityObject();
$object->id = $profile->getUri();
$object->title = $profile->getBestName();
$object->link = $profile->profileurl;
- $object->avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
+
+ $orig = $profile->getOriginalAvatar();
+
+ if (!empty($orig)) {
+ $object->avatarLinks[] = AvatarLink::fromAvatar($orig);
+ }
+
+ $sizes = array(
+ AVATAR_PROFILE_SIZE,
+ AVATAR_STREAM_SIZE,
+ AVATAR_MINI_SIZE
+ );
+
+ foreach ($sizes as $size) {
+
+ $alink = null;
+ $avatar = $profile->getAvatar($size);
+
+ if (!empty($avatar)) {
+ $alink = AvatarLink::fromAvatar($avatar);
+ } else {
+ $alink = new AvatarLink();
+ $alink->type = 'image/png';
+ $alink->height = $size;
+ $alink->width = $size;
+ $alink->url = Avatar::defaultImage($size);
+ }
+
+ $object->avatarLinks[] = $alink;
+ }
if (isset($profile->lat) && isset($profile->lon)) {
- $object->geopoint = (float)$profile->lat . ' ' . (float)$profile->lon;
+ $object->geopoint = (float)$profile->lat
+ . ' ' . (float)$profile->lon;
}
$object->poco = PoCo::fromProfile($profile);
return $object;
}
+ static function fromGroup($group)
+ {
+ $object = new ActivityObject();
+
+ $object->type = ActivityObject::GROUP;
+ $object->id = $group->getUri();
+ $object->title = $group->getBestName();
+ $object->link = $group->getUri();
+
+ $object->avatarLinks[] = AvatarLink::fromFilename(
+ $group->homepage_logo,
+ AVATAR_PROFILE_SIZE
+ );
+
+ $object->avatarLinks[] = AvatarLink::fromFilename(
+ $group->stream_logo,
+ AVATAR_STREAM_SIZE
+ );
+
+ $object->avatarLinks[] = AvatarLink::fromFilename(
+ $group->mini_logo,
+ AVATAR_MINI_SIZE
+ );
+
+ $object->poco = PoCo::fromGroup($group);
+
+ return $object;
+ }
+
function asString($tag='activity:object')
{
$xs = new XMLStringer(true);
$xs->element(self::ID, null, $this->id);
if (!empty($this->title)) {
- $xs->element(self::TITLE, null, $this->title);
+ $xs->element(
+ self::TITLE,
+ null,
+ common_xml_safe_str($this->title)
+ );
}
if (!empty($this->summary)) {
- $xs->element(self::SUMMARY, null, $this->summary);
+ $xs->element(
+ self::SUMMARY,
+ null,
+ common_xml_safe_str($this->summary)
+ );
}
if (!empty($this->content)) {
// XXX: assuming HTML content here
- $xs->element(ActivityUtils::CONTENT, array('type' => 'html'), $this->content);
+ $xs->element(
+ ActivityUtils::CONTENT,
+ array('type' => 'html'),
+ common_xml_safe_str($this->content)
+ );
}
if (!empty($this->link)) {
if ($this->type == ActivityObject::PERSON
|| $this->type == ActivityObject::GROUP) {
- $xs->element(
- 'link', array(
- 'type' => empty($this->avatar) ? 'image/png' : $this->avatar->mediatype,
- 'rel' => 'avatar',
- 'href' => empty($this->avatar)
- ? Avatar::defaultImage(AVATAR_PROFILE_SIZE)
- : $this->avatar->displayUrl()
- ),
- null
- );
+
+ foreach ($this->avatarLinks as $avatar) {
+ $xs->element(
+ 'link', array(
+ 'rel' => 'avatar',
+ 'type' => $avatar->type,
+ 'media:width' => $avatar->width,
+ 'media:height' => $avatar->height,
+ 'href' => $avatar->url
+ ),
+ null
+ );
+ }
}
if (!empty($this->geopoint)) {
const UNFAVORITE = 'http://ostatus.org/schema/1.0/unfavorite';
const UNFOLLOW = 'http://ostatus.org/schema/1.0/unfollow';
const LEAVE = 'http://ostatus.org/schema/1.0/leave';
+
+ // For simple profile-update pings; no content to share.
+ const UPDATE_PROFILE = 'http://ostatus.org/schema/1.0/update-profile';
}
class ActivityContext
for ($i = 0; $i < $points->length; $i++) {
$point = $points->item($i)->textContent;
- $point = str_replace(',', ' ', $point); // per spec "treat commas as whitespace"
- $point = preg_replace('/\s+/', ' ', $point);
- $point = trim($point);
- $coords = explode(' ', $point);
- if (count($coords) == 2) {
- list($lat, $lon) = $coords;
- if (is_numeric($lat) && is_numeric($lon)) {
- common_log(LOG_INFO, "Looking up location for $lat $lon from georss");
- return Location::fromLatLon($lat, $lon);
- }
- }
- common_log(LOG_ERR, "Ignoring bogus georss:point value $point");
+ return self::locationFromPoint($point);
}
return null;
}
+
+ // XXX: Move to ActivityUtils or Location?
+ static function locationFromPoint($point)
+ {
+ $point = str_replace(',', ' ', $point); // per spec "treat commas as whitespace"
+ $point = preg_replace('/\s+/', ' ', $point);
+ $point = trim($point);
+ $coords = explode(' ', $point);
+ if (count($coords) == 2) {
+ list($lat, $lon) = $coords;
+ if (is_numeric($lat) && is_numeric($lon)) {
+ common_log(LOG_INFO, "Looking up location for $lat $lon from georss point");
+ return Location::fromLatLon($lat, $lon);
+ }
+ }
+ common_log(LOG_ERR, "Ignoring bogus georss:point value $point");
+ return null;
+ }
}
/**
const PUBLISHED = 'published';
const UPDATED = 'updated';
+ const RSS = null; // no namespace!
+
+ const PUBDATE = 'pubDate';
+ const DESCRIPTION = 'description';
+ const GUID = 'guid';
+ const SELF = 'self';
+ const IMAGE = 'image';
+ const URL = 'url';
+
+ const DC = 'http://purl.org/dc/elements/1.1/';
+
+ const CREATOR = 'creator';
+
+ const CONTENTNS = 'http://purl.org/rss/1.0/modules/content/';
+
public $actor; // an ActivityObject
public $verb; // a string (the URL)
public $object; // an ActivityObject
public $content; // HTML content of activity
public $id; // ID of the activity
public $title; // title of the activity
+ public $categories = array(); // list of AtomCategory objects
+ public $enclosures = array(); // list of enclosure URL references
/**
* Turns a regular old Atom <entry> into a magical activity
return;
}
+ // Insist on a feed's root DOMElement; don't allow a DOMDocument
+ if ($feed instanceof DOMDocument) {
+ throw new ClientException(
+ _("Expecting a root feed element but got a whole XML document.")
+ );
+ }
+
$this->entry = $entry;
$this->feed = $feed;
+ if ($entry->namespaceURI == Activity::ATOM &&
+ $entry->localName == 'entry') {
+ $this->_fromAtomEntry($entry, $feed);
+ } else if ($entry->namespaceURI == Activity::RSS &&
+ $entry->localName == 'item') {
+ $this->_fromRssItem($entry, $feed);
+ } else {
+ throw new Exception("Unknown DOM element: {$entry->namespaceURI} {$entry->localName}");
+ }
+ }
+
+ function _fromAtomEntry($entry, $feed)
+ {
$pubEl = $this->_child($entry, self::PUBLISHED, self::ATOM);
if (!empty($pubEl)) {
$this->summary = ActivityUtils::childContent($entry, 'summary');
$this->id = ActivityUtils::childContent($entry, 'id');
$this->content = ActivityUtils::getContent($entry);
+
+ $catEls = $entry->getElementsByTagNameNS(self::ATOM, 'category');
+ if ($catEls) {
+ for ($i = 0; $i < $catEls->length; $i++) {
+ $catEl = $catEls->item($i);
+ $this->categories[] = new AtomCategory($catEl);
+ }
+ }
+
+ foreach (ActivityUtils::getLinks($entry, 'enclosure') as $link) {
+ $this->enclosures[] = $link->getAttribute('href');
+ }
+ }
+
+ function _fromRssItem($item, $rss)
+ {
+ $verbEl = $this->_child($item, self::VERB);
+
+ if (!empty($verbEl)) {
+ $this->verb = trim($verbEl->textContent);
+ } else {
+ $this->verb = ActivityVerb::POST;
+ // XXX: do other implied stuff here
+ }
+
+ $pubDateEl = $this->_child($item, self::PUBDATE, self::RSS);
+
+ if (!empty($pubDateEl)) {
+ $this->time = strtotime($pubDateEl->textContent);
+ }
+
+ $authorEl = $this->_child($item, self::AUTHOR, self::RSS);
+
+ if (!empty($authorEl)) {
+ $this->actor = ActivityObject::fromRssAuthor($authorEl);
+ } else {
+ $dcCreatorEl = $this->_child($item, self::CREATOR, self::DC);
+ if (!empty($dcCreatorEl)) {
+ $this->actor = ActivityObject::fromDcCreator($dcCreatorEl);
+ } else if (!empty($rss)) {
+ $this->actor = ActivityObject::fromRssChannel($rss);
+ }
+ }
+
+ $this->title = ActivityUtils::childContent($item, ActivityObject::TITLE, self::RSS);
+
+ $contentEl = ActivityUtils::child($item, ActivityUtils::CONTENT, self::CONTENTNS);
+
+ if (!empty($contentEl)) {
+ $this->content = htmlspecialchars_decode($contentEl->textContent, ENT_QUOTES);
+ } else {
+ $descriptionEl = ActivityUtils::child($item, self::DESCRIPTION, self::RSS);
+ if (!empty($descriptionEl)) {
+ $this->content = htmlspecialchars_decode($descriptionEl->textContent, ENT_QUOTES);
+ }
+ }
+
+ $this->link = ActivityUtils::childContent($item, ActivityUtils::LINK, self::RSS);
+
+ // @fixme enclosures
+ // @fixme thumbnails... maybe
+
+ $guidEl = ActivityUtils::child($item, self::GUID, self::RSS);
+
+ if (!empty($guidEl)) {
+ $this->id = $guidEl->textContent;
+
+ if ($guidEl->hasAttribute('isPermaLink') && $guidEl->getAttribute('isPermaLink') != 'false') {
+ // overwrites <link>
+ $this->link = $this->id;
+ }
+ }
+
+ $this->object = new ActivityObject($item);
+ $this->context = new ActivityContext($item);
}
/**
'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/',
'xmlns:georss' => 'http://www.georss.org/georss',
'xmlns:ostatus' => 'http://ostatus.org/schema/1.0',
- 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0');
+ 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0',
+ 'xmlns:media' => 'http://purl.org/syndication/atommedia');
} else {
$attrs = array();
}
}
// XXX: add context
- // XXX: add target
+ $xs->elementStart('author');
+ $xs->element('uri', array(), $this->actor->id);
+ if ($this->actor->title) {
+ $xs->element('name', array(), $this->actor->title);
+ }
+ $xs->elementEnd('author');
$xs->raw($this->actor->asString('activity:actor'));
+
$xs->element('activity:verb', null, $this->verb);
- $xs->raw($this->object->asString());
+
+ if ($this->object) {
+ $xs->raw($this->object->asString());
+ }
+
+ if ($this->target) {
+ $xs->raw($this->target->asString('activity:target'));
+ }
+
+ foreach ($this->categories as $cat) {
+ $xs->raw($cat->asString());
+ }
$xs->elementEnd('entry');
{
return ActivityUtils::child($element, $tag, $namespace);
}
-}
\ No newline at end of file
+}
+
+class AtomCategory
+{
+ public $term;
+ public $scheme;
+ public $label;
+
+ function __construct($element=null)
+ {
+ if ($element && $element->attributes) {
+ $this->term = $this->extract($element, 'term');
+ $this->scheme = $this->extract($element, 'scheme');
+ $this->label = $this->extract($element, 'label');
+ }
+ }
+
+ protected function extract($element, $attrib)
+ {
+ $node = $element->attributes->getNamedItemNS(Activity::ATOM, $attrib);
+ if ($node) {
+ return trim($node->textContent);
+ }
+ $node = $element->attributes->getNamedItem($attrib);
+ if ($node) {
+ return trim($node->textContent);
+ }
+ return null;
+ }
+
+ function asString()
+ {
+ $attribs = array();
+ if ($this->term !== null) {
+ $attribs['term'] = $this->term;
+ }
+ if ($this->scheme !== null) {
+ $attribs['scheme'] = $this->scheme;
+ }
+ if ($this->label !== null) {
+ $attribs['label'] = $this->label;
+ }
+ $xs = new XMLStringer();
+ $xs->element('category', $attribs);
+ return $xs->asString();
+ }
+}