Chris@0: getAuthors(); Chris@0: Chris@0: if (isset($authors[$index])) { Chris@0: return $authors[$index]; Chris@0: } Chris@0: Chris@0: return; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get an array with feed authors Chris@0: * Chris@0: * @return Collection\Author Chris@0: */ Chris@0: public function getAuthors() Chris@0: { Chris@0: if (array_key_exists('authors', $this->data)) { Chris@0: return $this->data['authors']; Chris@0: } Chris@0: Chris@0: $list = $this->xpath->query('//atom:author'); Chris@0: Chris@0: $authors = []; Chris@0: Chris@0: if ($list->length) { Chris@0: foreach ($list as $author) { Chris@0: $author = $this->getAuthorFromElement($author); Chris@12: if (! empty($author)) { Chris@0: $authors[] = $author; Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: if (count($authors) == 0) { Chris@0: $authors = new Collection\Author(); Chris@0: } else { Chris@0: $authors = new Collection\Author( Chris@0: Reader\Reader::arrayUnique($authors) Chris@0: ); Chris@0: } Chris@0: Chris@0: $this->data['authors'] = $authors; Chris@0: Chris@0: return $this->data['authors']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the copyright entry Chris@0: * Chris@0: * @return string|null Chris@0: */ Chris@0: public function getCopyright() Chris@0: { Chris@0: if (array_key_exists('copyright', $this->data)) { Chris@0: return $this->data['copyright']; Chris@0: } Chris@0: Chris@0: $copyright = null; Chris@0: Chris@0: if ($this->getType() === Reader\Reader::TYPE_ATOM_03) { Chris@0: $copyright = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:copyright)'); Chris@0: } else { Chris@0: $copyright = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:rights)'); Chris@0: } Chris@0: Chris@12: if (! $copyright) { Chris@0: $copyright = null; Chris@0: } Chris@0: Chris@0: $this->data['copyright'] = $copyright; Chris@0: Chris@0: return $this->data['copyright']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the feed creation date Chris@0: * Chris@0: * @return DateTime|null Chris@0: */ Chris@0: public function getDateCreated() Chris@0: { Chris@0: if (array_key_exists('datecreated', $this->data)) { Chris@0: return $this->data['datecreated']; Chris@0: } Chris@0: Chris@0: $date = null; Chris@0: Chris@0: if ($this->getType() === Reader\Reader::TYPE_ATOM_03) { Chris@0: $dateCreated = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:created)'); Chris@0: } else { Chris@0: $dateCreated = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:published)'); Chris@0: } Chris@0: Chris@0: if ($dateCreated) { Chris@0: $date = new DateTime($dateCreated); Chris@0: } Chris@0: Chris@0: $this->data['datecreated'] = $date; Chris@0: Chris@0: return $this->data['datecreated']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the feed modification date Chris@0: * Chris@0: * @return DateTime|null Chris@0: */ Chris@0: public function getDateModified() Chris@0: { Chris@0: if (array_key_exists('datemodified', $this->data)) { Chris@0: return $this->data['datemodified']; Chris@0: } Chris@0: Chris@0: $date = null; Chris@0: Chris@0: if ($this->getType() === Reader\Reader::TYPE_ATOM_03) { Chris@0: $dateModified = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:modified)'); Chris@0: } else { Chris@0: $dateModified = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:updated)'); Chris@0: } Chris@0: Chris@0: if ($dateModified) { Chris@0: $date = new DateTime($dateModified); Chris@0: } Chris@0: Chris@0: $this->data['datemodified'] = $date; Chris@0: Chris@0: return $this->data['datemodified']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the feed description Chris@0: * Chris@0: * @return string|null Chris@0: */ Chris@0: public function getDescription() Chris@0: { Chris@0: if (array_key_exists('description', $this->data)) { Chris@0: return $this->data['description']; Chris@0: } Chris@0: Chris@0: $description = null; Chris@0: Chris@0: if ($this->getType() === Reader\Reader::TYPE_ATOM_03) { Chris@0: $description = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:tagline)'); Chris@0: } else { Chris@0: $description = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:subtitle)'); Chris@0: } Chris@0: Chris@12: if (! $description) { Chris@0: $description = null; Chris@0: } Chris@0: Chris@0: $this->data['description'] = $description; Chris@0: Chris@0: return $this->data['description']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the feed generator entry Chris@0: * Chris@0: * @return string|null Chris@0: */ Chris@0: public function getGenerator() Chris@0: { Chris@0: if (array_key_exists('generator', $this->data)) { Chris@0: return $this->data['generator']; Chris@0: } Chris@0: // TODO: Add uri support Chris@0: $generator = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:generator)'); Chris@0: Chris@12: if (! $generator) { Chris@0: $generator = null; Chris@0: } Chris@0: Chris@0: $this->data['generator'] = $generator; Chris@0: Chris@0: return $this->data['generator']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the feed ID Chris@0: * Chris@0: * @return string|null Chris@0: */ Chris@0: public function getId() Chris@0: { Chris@0: if (array_key_exists('id', $this->data)) { Chris@0: return $this->data['id']; Chris@0: } Chris@0: Chris@0: $id = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:id)'); Chris@0: Chris@12: if (! $id) { Chris@0: if ($this->getLink()) { Chris@0: $id = $this->getLink(); Chris@0: } elseif ($this->getTitle()) { Chris@0: $id = $this->getTitle(); Chris@0: } else { Chris@0: $id = null; Chris@0: } Chris@0: } Chris@0: Chris@0: $this->data['id'] = $id; Chris@0: Chris@0: return $this->data['id']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the feed language Chris@0: * Chris@0: * @return string|null Chris@0: */ Chris@0: public function getLanguage() Chris@0: { Chris@0: if (array_key_exists('language', $this->data)) { Chris@0: return $this->data['language']; Chris@0: } Chris@0: Chris@0: $language = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:lang)'); Chris@0: Chris@12: if (! $language) { Chris@0: $language = $this->xpath->evaluate('string(//@xml:lang[1])'); Chris@0: } Chris@0: Chris@12: if (! $language) { Chris@0: $language = null; Chris@0: } Chris@0: Chris@0: $this->data['language'] = $language; Chris@0: Chris@0: return $this->data['language']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the feed image Chris@0: * Chris@0: * @return array|null Chris@0: */ Chris@0: public function getImage() Chris@0: { Chris@0: if (array_key_exists('image', $this->data)) { Chris@0: return $this->data['image']; Chris@0: } Chris@0: Chris@0: $imageUrl = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:logo)'); Chris@0: Chris@12: if (! $imageUrl) { Chris@0: $image = null; Chris@0: } else { Chris@0: $image = ['uri' => $imageUrl]; Chris@0: } Chris@0: Chris@0: $this->data['image'] = $image; Chris@0: Chris@0: return $this->data['image']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the base URI of the feed (if set). Chris@0: * Chris@0: * @return string|null Chris@0: */ Chris@0: public function getBaseUrl() Chris@0: { Chris@0: if (array_key_exists('baseUrl', $this->data)) { Chris@0: return $this->data['baseUrl']; Chris@0: } Chris@0: Chris@0: $baseUrl = $this->xpath->evaluate('string(//@xml:base[1])'); Chris@0: Chris@12: if (! $baseUrl) { Chris@0: $baseUrl = null; Chris@0: } Chris@0: $this->data['baseUrl'] = $baseUrl; Chris@0: Chris@0: return $this->data['baseUrl']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get a link to the source website Chris@0: * Chris@0: * @return string|null Chris@0: */ Chris@0: public function getLink() Chris@0: { Chris@0: if (array_key_exists('link', $this->data)) { Chris@0: return $this->data['link']; Chris@0: } Chris@0: Chris@0: $link = null; Chris@0: Chris@0: $list = $this->xpath->query( Chris@0: $this->getXpathPrefix() . '/atom:link[@rel="alternate"]/@href' . '|' . Chris@0: $this->getXpathPrefix() . '/atom:link[not(@rel)]/@href' Chris@0: ); Chris@0: Chris@0: if ($list->length) { Chris@0: $link = $list->item(0)->nodeValue; Chris@0: $link = $this->absolutiseUri($link); Chris@0: } Chris@0: Chris@0: $this->data['link'] = $link; Chris@0: Chris@0: return $this->data['link']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get a link to the feed's XML Url Chris@0: * Chris@0: * @return string|null Chris@0: */ Chris@0: public function getFeedLink() Chris@0: { Chris@0: if (array_key_exists('feedlink', $this->data)) { Chris@0: return $this->data['feedlink']; Chris@0: } Chris@0: Chris@0: $link = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:link[@rel="self"]/@href)'); Chris@0: Chris@0: $link = $this->absolutiseUri($link); Chris@0: Chris@0: $this->data['feedlink'] = $link; Chris@0: Chris@0: return $this->data['feedlink']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get an array of any supported Pusubhubbub endpoints Chris@0: * Chris@0: * @return array|null Chris@0: */ Chris@0: public function getHubs() Chris@0: { Chris@0: if (array_key_exists('hubs', $this->data)) { Chris@0: return $this->data['hubs']; Chris@0: } Chris@0: $hubs = []; Chris@0: Chris@0: $list = $this->xpath->query($this->getXpathPrefix() Chris@0: . '//atom:link[@rel="hub"]/@href'); Chris@0: Chris@0: if ($list->length) { Chris@0: foreach ($list as $uri) { Chris@0: $hubs[] = $this->absolutiseUri($uri->nodeValue); Chris@0: } Chris@0: } else { Chris@0: $hubs = null; Chris@0: } Chris@0: Chris@0: $this->data['hubs'] = $hubs; Chris@0: Chris@0: return $this->data['hubs']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the feed title Chris@0: * Chris@0: * @return string|null Chris@0: */ Chris@0: public function getTitle() Chris@0: { Chris@0: if (array_key_exists('title', $this->data)) { Chris@0: return $this->data['title']; Chris@0: } Chris@0: Chris@0: $title = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:title)'); Chris@0: Chris@12: if (! $title) { Chris@0: $title = null; Chris@0: } Chris@0: Chris@0: $this->data['title'] = $title; Chris@0: Chris@0: return $this->data['title']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get all categories Chris@0: * Chris@0: * @return Collection\Category Chris@0: */ Chris@0: public function getCategories() Chris@0: { Chris@0: if (array_key_exists('categories', $this->data)) { Chris@0: return $this->data['categories']; Chris@0: } Chris@0: Chris@0: if ($this->getType() == Reader\Reader::TYPE_ATOM_10) { Chris@0: $list = $this->xpath->query($this->getXpathPrefix() . '/atom:category'); Chris@0: } else { Chris@0: /** Chris@0: * Since Atom 0.3 did not support categories, it would have used the Chris@0: * Dublin Core extension. However there is a small possibility Atom 0.3 Chris@0: * may have been retrofittied to use Atom 1.0 instead. Chris@0: */ Chris@0: $this->xpath->registerNamespace('atom10', Reader\Reader::NAMESPACE_ATOM_10); Chris@0: $list = $this->xpath->query($this->getXpathPrefix() . '/atom10:category'); Chris@0: } Chris@0: Chris@0: if ($list->length) { Chris@0: $categoryCollection = new Collection\Category; Chris@0: foreach ($list as $category) { Chris@0: $categoryCollection[] = [ Chris@0: 'term' => $category->getAttribute('term'), Chris@0: 'scheme' => $category->getAttribute('scheme'), Chris@0: 'label' => $category->getAttribute('label') Chris@0: ]; Chris@0: } Chris@0: } else { Chris@0: return new Collection\Category; Chris@0: } Chris@0: Chris@0: $this->data['categories'] = $categoryCollection; Chris@0: Chris@0: return $this->data['categories']; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get an author entry in RSS format Chris@0: * Chris@0: * @param DOMElement $element Chris@0: * @return string Chris@0: */ Chris@0: protected function getAuthorFromElement(DOMElement $element) Chris@0: { Chris@0: $author = []; Chris@0: Chris@0: $emailNode = $element->getElementsByTagName('email'); Chris@0: $nameNode = $element->getElementsByTagName('name'); Chris@0: $uriNode = $element->getElementsByTagName('uri'); Chris@0: Chris@0: if ($emailNode->length && strlen($emailNode->item(0)->nodeValue) > 0) { Chris@0: $author['email'] = $emailNode->item(0)->nodeValue; Chris@0: } Chris@0: Chris@0: if ($nameNode->length && strlen($nameNode->item(0)->nodeValue) > 0) { Chris@0: $author['name'] = $nameNode->item(0)->nodeValue; Chris@0: } Chris@0: Chris@0: if ($uriNode->length && strlen($uriNode->item(0)->nodeValue) > 0) { Chris@0: $author['uri'] = $uriNode->item(0)->nodeValue; Chris@0: } Chris@0: Chris@0: if (empty($author)) { Chris@0: return; Chris@0: } Chris@0: return $author; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Attempt to absolutise the URI, i.e. if a relative URI apply the Chris@0: * xml:base value as a prefix to turn into an absolute URI. Chris@17: * Chris@17: * @param string $link Chris@17: * @return string|null Chris@0: */ Chris@0: protected function absolutiseUri($link) Chris@0: { Chris@12: if (! Uri::factory($link)->isAbsolute()) { Chris@0: if ($this->getBaseUrl() !== null) { Chris@0: $link = $this->getBaseUrl() . $link; Chris@12: if (! Uri::factory($link)->isValid()) { Chris@0: $link = null; Chris@0: } Chris@0: } Chris@0: } Chris@0: return $link; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Register the default namespaces for the current feed format Chris@0: */ Chris@0: protected function registerNamespaces() Chris@0: { Chris@0: if ($this->getType() == Reader\Reader::TYPE_ATOM_10 Chris@0: || $this->getType() == Reader\Reader::TYPE_ATOM_03 Chris@0: ) { Chris@0: return; // pre-registered at Feed level Chris@0: } Chris@0: $atomDetected = $this->getAtomType(); Chris@0: switch ($atomDetected) { Chris@0: case Reader\Reader::TYPE_ATOM_03: Chris@0: $this->xpath->registerNamespace('atom', Reader\Reader::NAMESPACE_ATOM_03); Chris@0: break; Chris@0: default: Chris@0: $this->xpath->registerNamespace('atom', Reader\Reader::NAMESPACE_ATOM_10); Chris@0: break; Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Detect the presence of any Atom namespaces in use Chris@0: */ Chris@0: protected function getAtomType() Chris@0: { Chris@0: $dom = $this->getDomDocument(); Chris@0: $prefixAtom03 = $dom->lookupPrefix(Reader\Reader::NAMESPACE_ATOM_03); Chris@0: $prefixAtom10 = $dom->lookupPrefix(Reader\Reader::NAMESPACE_ATOM_10); Chris@0: if ($dom->isDefaultNamespace(Reader\Reader::NAMESPACE_ATOM_10) Chris@12: || ! empty($prefixAtom10) Chris@0: ) { Chris@0: return Reader\Reader::TYPE_ATOM_10; Chris@0: } Chris@0: if ($dom->isDefaultNamespace(Reader\Reader::NAMESPACE_ATOM_03) Chris@12: || ! empty($prefixAtom03) Chris@0: ) { Chris@0: return Reader\Reader::TYPE_ATOM_03; Chris@0: } Chris@0: } Chris@0: }