function _fromRssItem($item, $channel) { $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); } if ($authorEl = $this->_child($item, self::AUTHOR, self::RSS)) { $this->actor = ActivityObject::fromRssAuthor($authorEl); } else { if ($dcCreatorEl = $this->_child($item, self::CREATOR, self::DC)) { $this->actor = ActivityObject::fromDcCreator($dcCreatorEl); } else { if ($posterousEl = $this->_child($item, ActivityObject::AUTHOR, ActivityObject::POSTEROUS)) { // Special case for Posterous.com $this->actor = ActivityObject::fromPosterousAuthor($posterousEl); } else { if (!empty($channel)) { $this->actor = ActivityObject::fromRssChannel($channel); } else { // No actor! } } } } $this->title = ActivityUtils::childContent($item, ActivityObject::TITLE, self::RSS); $contentEl = ActivityUtils::child($item, self::ENCODED, self::CONTENTNS); if (!empty($contentEl)) { // <content:encoded> XML node's text content is HTML; no further processing needed. $this->content = $contentEl->textContent; } else { $descriptionEl = ActivityUtils::child($item, self::DESCRIPTION, self::RSS); if (!empty($descriptionEl)) { // Per spec, <description> must be plaintext. // In practice, often there's HTML... but these days good // feeds are using <content:encoded> which is explicitly // real HTML. // We'll treat this following spec, and do HTML escaping // to convert from plaintext to HTML. $this->content = htmlspecialchars($descriptionEl->textContent); } } $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->objects[] = new ActivityObject($item); $this->context = new ActivityContext($item); }
/** * Look up and, if necessary, create an Ostatus_profile for the remote * profile with the given RSS feed - actually loaded from the feed. * This should never return null -- you will either get an object or * an exception will be thrown. * * @param DOMElement $feedEl root element of a loaded RSS feed * @param array $hints additional discovery information passed from higher levels * @todo FIXME: Should this be marked public? * @return Ostatus_profile * @throws Exception */ public static function ensureRssChannel(DOMElement $feedEl, array $hints) { // Special-case for Posterous. They have some nice metadata in their // posterous:author elements. We should use them instead of the channel. $items = $feedEl->getElementsByTagName('item'); if ($items->length > 0) { $item = $items->item(0); $authorEl = ActivityUtils::child($item, ActivityObject::AUTHOR, ActivityObject::POSTEROUS); if (!empty($authorEl)) { $obj = ActivityObject::fromPosterousAuthor($authorEl); // Posterous has multiple authors per feed, and multiple feeds // per author. We check if this is the "main" feed for this author. if (array_key_exists('profileurl', $hints) && !empty($obj->poco) && common_url_to_nickname($hints['profileurl']) == $obj->poco->preferredUsername) { return self::ensureActivityObjectProfile($obj, $hints); } } } $obj = ActivityUtils::getFeedAuthor($feedEl); // @todo FIXME: We should check whether this feed has elements // with different <author> or <dc:creator> elements, and... I dunno. // Do something about that. if (empty($obj)) { $obj = ActivityObject::fromRssChannel($feedEl); } return self::ensureActivityObjectProfile($obj, $hints); }