/** * 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 = null) { if (empty($element)) { return; } $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); } } // Some per-type attributes... if ($this->type == self::PERSON || $this->type == self::GROUP) { $this->displayName = $this->title; $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); } if ($this->type == self::PHOTO) { $this->thumbnail = ActivityUtils::getLink($element, 'preview'); $this->largerImage = ActivityUtils::getLink($element, 'enclosure'); $this->description = ActivityUtils::childContent($element, ActivityObject::MEDIA_DESCRIPTION, Activity::MEDIA); } if ($this->type == self::_LIST) { $owner = ActivityUtils::child($this->element, Activity::AUTHOR, Activity::SPEC); $this->owner = new ActivityObject($owner); } }
function _fromAtomEntry($entry, $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...? $updateEl = $this->_child($entry, self::UPDATED, self::ATOM); if (!empty($updateEl)) { $this->time = strtotime($updateEl->textContent); } else { $this->time = null; } } $this->link = ActivityUtils::getPermalink($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 } // get immediate object children $objectEls = ActivityUtils::children($entry, self::OBJECT, self::SPEC); if (count($objectEls) > 0) { foreach ($objectEls as $objectEl) { // Special case for embedded activities $objectType = ActivityUtils::childContent($objectEl, self::OBJECTTYPE, self::SPEC); if (!empty($objectType) && $objectType == ActivityObject::ACTIVITY) { $this->objects[] = new Activity($objectEl); } else { $this->objects[] = new ActivityObject($objectEl); } } } else { // XXX: really? $this->objects[] = new ActivityObject($entry); } $actorEl = $this->_child($entry, self::ACTOR); if (!empty($actorEl)) { // Standalone <activity:actor> elements are a holdover from older // versions of ActivityStreams. Newer feeds should have this data // integrated straight into <atom:author>. $this->actor = new ActivityObject($actorEl); // Cliqset has bad actor IDs (just nickname of user). We // work around it by getting the author data and using its // id instead if (!preg_match('/^\\w+:/', $this->actor->id)) { $authorEl = ActivityUtils::child($entry, 'author'); if (!empty($authorEl)) { $authorObj = new ActivityObject($authorEl); $this->actor->id = $authorObj->id; } } } else { if ($authorEl = $this->_child($entry, self::AUTHOR, self::ATOM)) { // An <atom:author> in the entry overrides any author info on // the surrounding feed. $this->actor = new ActivityObject($authorEl); } else { if (!empty($feed) && ($subjectEl = $this->_child($feed, self::SUBJECT))) { // Feed subject is used for things like groups. // Should actually possibly not be interpreted as an actor...? $this->actor = new ActivityObject($subjectEl); } else { if (!empty($feed) && ($authorEl = $this->_child($feed, self::AUTHOR, self::ATOM))) { // If there's no <atom:author> on the entry, it's safe to assume // the containing feed's authorship info applies. $this->actor = new ActivityObject($authorEl); } } } } $contextEl = $this->_child($entry, self::CONTEXT); if (!empty($contextEl)) { $this->context = new ActivityContext($contextEl); } else { $this->context = new ActivityContext($entry); } $targetEl = $this->_child($entry, self::TARGET); if (!empty($targetEl)) { $this->target = new ActivityObject($targetEl); } elseif (ActivityUtils::compareTypes($this->verb, array(ActivityVerb::FAVORITE))) { // StatusNet didn't send a 'target' for their Favorite atom entries $this->target = clone $this->objects[0]; } $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'); } // From APP. Might be useful. $this->selfLink = ActivityUtils::getLink($entry, 'self', 'application/atom+xml'); $this->editLink = ActivityUtils::getLink($entry, 'edit', 'application/atom+xml'); }
function _fromAtomEntry($entry, $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...? $updateEl = $this->_child($entry, self::UPDATED, self::ATOM); if (!empty($updateEl)) { $this->time = strtotime($updateEl->textContent); } else { $this->time = null; } } $this->link = ActivityUtils::getPermalink($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 } $objectEls = $entry->getElementsByTagNameNS(self::SPEC, self::OBJECT); if ($objectEls->length > 0) { for ($i = 0; $i < $objectEls->length; $i++) { $objectEl = $objectEls->item($i); $this->objects[] = new ActivityObject($objectEl); } } else { $this->objects[] = new ActivityObject($entry); } $actorEl = $this->_child($entry, self::ACTOR); if (!empty($actorEl)) { $this->actor = new ActivityObject($actorEl); // Cliqset has bad actor IDs (just nickname of user). We // work around it by getting the author data and using its // id instead if (!preg_match('/^\\w+:/', $this->actor->id)) { $authorEl = ActivityUtils::child($entry, 'author'); if (!empty($authorEl)) { $authorObj = new ActivityObject($authorEl); $this->actor->id = $authorObj->id; } } } 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); } else { if (!empty($feed) && ($authorEl = $this->_child($feed, self::AUTHOR, self::ATOM))) { $this->actor = new ActivityObject($authorEl); } } } } $contextEl = $this->_child($entry, self::CONTEXT); if (!empty($contextEl)) { $this->context = new ActivityContext($contextEl); } else { $this->context = new ActivityContext($entry); } $targetEl = $this->_child($entry, self::TARGET); if (!empty($targetEl)) { $this->target = new ActivityObject($targetEl); } $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'); } }
/** * Save a bookmark from an activity * * @param Activity $activity Activity to save * @param Profile $actor Profile to use as author * @param array $options Options to pass to bookmark-saving code * * @return Notice resulting notice */ function saveNoticeFromActivity(Activity $activity, Profile $actor, array $options = array()) { $bookmark = $activity->objects[0]; $relLinkEls = ActivityUtils::getLinks($bookmark->element, 'related'); if (count($relLinkEls) < 1) { // TRANS: Client exception thrown when a bookmark is formatted incorrectly. throw new ClientException(_m('Expected exactly 1 link ' . 'rel=related in a Bookmark.')); } if (count($relLinkEls) > 1) { common_log(LOG_WARNING, "Got too many link rel=related in a Bookmark."); } $linkEl = $relLinkEls[0]; $url = $linkEl->getAttribute('href'); $tags = array(); foreach ($activity->categories as $category) { $tags[] = common_canonical_tag($category->term); } if (!empty($activity->time)) { $options['created'] = common_sql_date($activity->time); } // Fill in location if available $location = $activity->context->location; if ($location) { $options['lat'] = $location->lat; $options['lon'] = $location->lon; if ($location->location_id) { $options['location_ns'] = $location->location_ns; $options['location_id'] = $location->location_id; } } $options['groups'] = array(); $options['replies'] = array(); // TODO: context->attention foreach ($activity->context->attention as $attnUrl => $type) { try { $other = Profile::fromUri($attnUrl); if ($other->isGroup()) { $options['groups'][] = $other->id; } else { $options['replies'][] = $attnUrl; } } catch (UnknownUriException $e) { // We simply don't know this URI, despite lookup attempts. } } // Maintain direct reply associations // @fixme what about conversation ID? if (!empty($activity->context->replyToID)) { $orig = Notice::getKV('uri', $activity->context->replyToID); if (!empty($orig)) { $options['reply_to'] = $orig->id; } } return Bookmark::saveNew($actor, $bookmark->title, $url, $tags, $bookmark->summary, $options); }
public function testBookmarkRelated() { global $_example11; $dom = new DOMDocument(); $dom->loadXML($_example11); $feed = $dom->documentElement; $entry = $dom->getElementsByTagName('entry')->item(0); $expected = 'http://blog.teambox.com/open-source-companies'; $links = ActivityUtils::getLinks($entry, 'related'); $this->assertFalse(empty($links)); $this->assertTrue(is_array($links)); $this->assertEquals(count($links), 1); $url = $links[0]->getAttribute('href'); $this->assertEquals($url, $expected); }
public function testMultipleGroupPostAttention() { $text = "!" . $this->targetGroup1->nickname . " !" . $this->targetGroup2->nickname . " reply text " . common_good_rand(4); $notice = Notice::saveNew($this->author1->id, $text, 'test', array('uri' => null)); $entry = $notice->asAtomEntry(); $element = $this->_entryToElement($entry, true); $links = ActivityUtils::getLinks($element, 'ostatus:attention'); $this->assertEquals(2, count($links)); $hrefs = array(); foreach ($links as $link) { $hrefs[] = $link->getAttribute('href'); } $this->assertTrue(in_array($this->targetGroup1->uri, $hrefs)); $this->assertTrue(in_array($this->targetGroup2->uri, $hrefs)); $links = ActivityUtils::getLinks($element, 'mentioned'); $this->assertEquals(2, count($links)); $hrefs = array(); foreach ($links as $link) { $hrefs[] = $link->getAttribute('href'); } $this->assertTrue(in_array($this->targetGroup1->uri, $hrefs)); $this->assertTrue(in_array($this->targetGroup2->uri, $hrefs)); }
/** * Save a bookmark from an activity * * @param Activity $activity Activity to save * @param Profile $profile Profile to use as author * @param array $options Options to pass to bookmark-saving code * * @return Notice resulting notice */ function saveNoticeFromActivity($activity, $profile, $options = array()) { $bookmark = $activity->objects[0]; $relLinkEls = ActivityUtils::getLinks($bookmark->element, 'related'); if (count($relLinkEls) < 1) { // TRANS: Client exception thrown when a bookmark is formatted incorrectly. throw new ClientException(_m('Expected exactly 1 link ' . 'rel=related in a Bookmark.')); } if (count($relLinkEls) > 1) { common_log(LOG_WARNING, "Got too many link rel=related in a Bookmark."); } $linkEl = $relLinkEls[0]; $url = $linkEl->getAttribute('href'); $tags = array(); foreach ($activity->categories as $category) { $tags[] = common_canonical_tag($category->term); } if (!empty($activity->time)) { $options['created'] = common_sql_date($activity->time); } // Fill in location if available $location = $activity->context->location; if ($location) { $options['lat'] = $location->lat; $options['lon'] = $location->lon; if ($location->location_id) { $options['location_ns'] = $location->location_ns; $options['location_id'] = $location->location_id; } } $replies = $activity->context->attention; $options['groups'] = array(); $options['replies'] = array(); foreach ($replies as $replyURI) { $other = Profile::fromURI($replyURI); if (!empty($other)) { $options['replies'][] = $replyURI; } else { $group = User_group::staticGet('uri', $replyURI); if (!empty($group)) { $options['groups'][] = $replyURI; } } } // Maintain direct reply associations // @fixme what about conversation ID? if (!empty($activity->context->replyToID)) { $orig = Notice::staticGet('uri', $activity->context->replyToID); if (!empty($orig)) { $options['reply_to'] = $orig->id; } } return Bookmark::saveNew($profile, $bookmark->title, $url, $tags, $bookmark->summary, $options); }