diff options
Diffstat (limited to '3rdparty/ZendFeed/Reader/Feed')
-rw-r--r-- | 3rdparty/ZendFeed/Reader/Feed/AbstractFeed.php | 307 | ||||
-rw-r--r-- | 3rdparty/ZendFeed/Reader/Feed/Atom.php | 409 | ||||
-rw-r--r-- | 3rdparty/ZendFeed/Reader/Feed/Atom/Source.php | 94 | ||||
-rw-r--r-- | 3rdparty/ZendFeed/Reader/Feed/FeedInterface.php | 111 | ||||
-rw-r--r-- | 3rdparty/ZendFeed/Reader/Feed/Rss.php | 707 |
5 files changed, 1628 insertions, 0 deletions
diff --git a/3rdparty/ZendFeed/Reader/Feed/AbstractFeed.php b/3rdparty/ZendFeed/Reader/Feed/AbstractFeed.php new file mode 100644 index 000000000..0d5f2b835 --- /dev/null +++ b/3rdparty/ZendFeed/Reader/Feed/AbstractFeed.php @@ -0,0 +1,307 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Feed; + +use DOMDocument; +use DOMElement; +use DOMXPath; +use Zend\Feed\Reader; +use Zend\Feed\Reader\Exception; + +/** +*/ +abstract class AbstractFeed implements FeedInterface +{ + /** + * Parsed feed data + * + * @var array + */ + protected $data = array(); + + /** + * Parsed feed data in the shape of a DOMDocument + * + * @var DOMDocument + */ + protected $domDocument = null; + + /** + * An array of parsed feed entries + * + * @var array + */ + protected $entries = array(); + + /** + * A pointer for the iterator to keep track of the entries array + * + * @var int + */ + protected $entriesKey = 0; + + /** + * The base XPath query used to retrieve feed data + * + * @var DOMXPath + */ + protected $xpath = null; + + /** + * Array of loaded extensions + * + * @var array + */ + protected $extensions = array(); + + /** + * Original Source URI (set if imported from a URI) + * + * @var string + */ + protected $originalSourceUri = null; + + /** + * Constructor + * + * @param DOMDocument $domDocument The DOM object for the feed's XML + * @param string $type Feed type + */ + public function __construct(DOMDocument $domDocument, $type = null) + { + $this->domDocument = $domDocument; + $this->xpath = new DOMXPath($this->domDocument); + + if ($type !== null) { + $this->data['type'] = $type; + } else { + $this->data['type'] = Reader\Reader::detectType($this->domDocument); + } + $this->registerNamespaces(); + $this->indexEntries(); + $this->loadExtensions(); + } + + /** + * Set an original source URI for the feed being parsed. This value + * is returned from getFeedLink() method if the feed does not carry + * a self-referencing URI. + * + * @param string $uri + */ + public function setOriginalSourceUri($uri) + { + $this->originalSourceUri = $uri; + } + + /** + * Get an original source URI for the feed being parsed. Returns null if + * unset or the feed was not imported from a URI. + * + * @return string|null + */ + public function getOriginalSourceUri() + { + return $this->originalSourceUri; + } + + /** + * Get the number of feed entries. + * Required by the Iterator interface. + * + * @return int + */ + public function count() + { + return count($this->entries); + } + + /** + * Return the current entry + * + * @return \Zend\Feed\Reader\Entry\EntryInterface + */ + public function current() + { + if (substr($this->getType(), 0, 3) == 'rss') { + $reader = new Reader\Entry\Rss($this->entries[$this->key()], $this->key(), $this->getType()); + } else { + $reader = new Reader\Entry\Atom($this->entries[$this->key()], $this->key(), $this->getType()); + } + + $reader->setXpath($this->xpath); + + return $reader; + } + + /** + * Get the DOM + * + * @return DOMDocument + */ + public function getDomDocument() + { + return $this->domDocument; + } + + /** + * Get the Feed's encoding + * + * @return string + */ + public function getEncoding() + { + $assumed = $this->getDomDocument()->encoding; + if (empty($assumed)) { + $assumed = 'UTF-8'; + } + return $assumed; + } + + /** + * Get feed as xml + * + * @return string + */ + public function saveXml() + { + return $this->getDomDocument()->saveXml(); + } + + /** + * Get the DOMElement representing the items/feed element + * + * @return DOMElement + */ + public function getElement() + { + return $this->getDomDocument()->documentElement; + } + + /** + * Get the DOMXPath object for this feed + * + * @return DOMXPath + */ + public function getXpath() + { + return $this->xpath; + } + + /** + * Get the feed type + * + * @return string + */ + public function getType() + { + return $this->data['type']; + } + + /** + * Return the current feed key + * + * @return int + */ + public function key() + { + return $this->entriesKey; + } + + /** + * Move the feed pointer forward + * + */ + public function next() + { + ++$this->entriesKey; + } + + /** + * Reset the pointer in the feed object + * + */ + public function rewind() + { + $this->entriesKey = 0; + } + + /** + * Check to see if the iterator is still valid + * + * @return bool + */ + public function valid() + { + return 0 <= $this->entriesKey && $this->entriesKey < $this->count(); + } + + public function getExtensions() + { + return $this->extensions; + } + + public function __call($method, $args) + { + foreach ($this->extensions as $extension) { + if (method_exists($extension, $method)) { + return call_user_func_array(array($extension, $method), $args); + } + } + throw new Exception\BadMethodCallException('Method: ' . $method + . 'does not exist and could not be located on a registered Extension'); + } + + /** + * Return an Extension object with the matching name (postfixed with _Feed) + * + * @param string $name + * @return \Zend\Feed\Reader\Extension\AbstractFeed + */ + public function getExtension($name) + { + if (array_key_exists($name . '\\Feed', $this->extensions)) { + return $this->extensions[$name . '\\Feed']; + } + return null; + } + + protected function loadExtensions() + { + $all = Reader\Reader::getExtensions(); + $manager = Reader\Reader::getExtensionManager(); + $feed = $all['feed']; + foreach ($feed as $extension) { + if (in_array($extension, $all['core'])) { + continue; + } + if (!$manager->has($extension)) { + throw new Exception\RuntimeException(sprintf('Unable to load extension "%s"; cannot find class', $extension)); + } + $plugin = $manager->get($extension); + $plugin->setDomDocument($this->getDomDocument()); + $plugin->setType($this->data['type']); + $plugin->setXpath($this->xpath); + $this->extensions[$extension] = $plugin; + } + } + + /** + * Read all entries to the internal entries array + * + */ + abstract protected function indexEntries(); + + /** + * Register the default namespaces for the current feed format + * + */ + abstract protected function registerNamespaces(); +} diff --git a/3rdparty/ZendFeed/Reader/Feed/Atom.php b/3rdparty/ZendFeed/Reader/Feed/Atom.php new file mode 100644 index 000000000..251ad03ce --- /dev/null +++ b/3rdparty/ZendFeed/Reader/Feed/Atom.php @@ -0,0 +1,409 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Feed; + +use DOMDocument; +use Zend\Feed\Reader; + +/** +*/ +class Atom extends AbstractFeed +{ + + /** + * Constructor + * + * @param DOMDocument $dom + * @param string $type + */ + public function __construct(DOMDocument $dom, $type = null) + { + parent::__construct($dom, $type); + $manager = Reader\Reader::getExtensionManager(); + + $atomFeed = $manager->get('Atom\Feed'); + $atomFeed->setDomDocument($dom); + $atomFeed->setType($this->data['type']); + $atomFeed->setXpath($this->xpath); + $this->extensions['Atom\\Feed'] = $atomFeed; + + $atomFeed = $manager->get('DublinCore\Feed'); + $atomFeed->setDomDocument($dom); + $atomFeed->setType($this->data['type']); + $atomFeed->setXpath($this->xpath); + $this->extensions['DublinCore\\Feed'] = $atomFeed; + + foreach ($this->extensions as $extension) { + $extension->setXpathPrefix('/atom:feed'); + } + } + + /** + * Get a single author + * + * @param int $index + * @return string|null + */ + public function getAuthor($index = 0) + { + $authors = $this->getAuthors(); + + if (isset($authors[$index])) { + return $authors[$index]; + } + + return null; + } + + /** + * Get an array with feed authors + * + * @return array + */ + public function getAuthors() + { + if (array_key_exists('authors', $this->data)) { + return $this->data['authors']; + } + + $authors = $this->getExtension('Atom')->getAuthors(); + + $this->data['authors'] = $authors; + + return $this->data['authors']; + } + + /** + * Get the copyright entry + * + * @return string|null + */ + public function getCopyright() + { + if (array_key_exists('copyright', $this->data)) { + return $this->data['copyright']; + } + + $copyright = $this->getExtension('Atom')->getCopyright(); + + if (!$copyright) { + $copyright = null; + } + + $this->data['copyright'] = $copyright; + + return $this->data['copyright']; + } + + /** + * Get the feed creation date + * + * @return string|null + */ + public function getDateCreated() + { + if (array_key_exists('datecreated', $this->data)) { + return $this->data['datecreated']; + } + + $dateCreated = $this->getExtension('Atom')->getDateCreated(); + + if (!$dateCreated) { + $dateCreated = null; + } + + $this->data['datecreated'] = $dateCreated; + + return $this->data['datecreated']; + } + + /** + * Get the feed modification date + * + * @return string|null + */ + public function getDateModified() + { + if (array_key_exists('datemodified', $this->data)) { + return $this->data['datemodified']; + } + + $dateModified = $this->getExtension('Atom')->getDateModified(); + + if (!$dateModified) { + $dateModified = null; + } + + $this->data['datemodified'] = $dateModified; + + return $this->data['datemodified']; + } + + /** + * Get the feed lastBuild date. This is not implemented in Atom. + * + * @return string|null + */ + public function getLastBuildDate() + { + return null; + } + + /** + * Get the feed description + * + * @return string|null + */ + public function getDescription() + { + if (array_key_exists('description', $this->data)) { + return $this->data['description']; + } + + $description = $this->getExtension('Atom')->getDescription(); + + if (!$description) { + $description = null; + } + + $this->data['description'] = $description; + + return $this->data['description']; + } + + /** + * Get the feed generator entry + * + * @return string|null + */ + public function getGenerator() + { + if (array_key_exists('generator', $this->data)) { + return $this->data['generator']; + } + + $generator = $this->getExtension('Atom')->getGenerator(); + + $this->data['generator'] = $generator; + + return $this->data['generator']; + } + + /** + * Get the feed ID + * + * @return string|null + */ + public function getId() + { + if (array_key_exists('id', $this->data)) { + return $this->data['id']; + } + + $id = $this->getExtension('Atom')->getId(); + + $this->data['id'] = $id; + + return $this->data['id']; + } + + /** + * Get the feed language + * + * @return string|null + */ + public function getLanguage() + { + if (array_key_exists('language', $this->data)) { + return $this->data['language']; + } + + $language = $this->getExtension('Atom')->getLanguage(); + + if (!$language) { + $language = $this->xpath->evaluate('string(//@xml:lang[1])'); + } + + if (!$language) { + $language = null; + } + + $this->data['language'] = $language; + + return $this->data['language']; + } + + /** + * Get a link to the source website + * + * @return string|null + */ + public function getBaseUrl() + { + if (array_key_exists('baseUrl', $this->data)) { + return $this->data['baseUrl']; + } + + $baseUrl = $this->getExtension('Atom')->getBaseUrl(); + + $this->data['baseUrl'] = $baseUrl; + + return $this->data['baseUrl']; + } + + /** + * Get a link to the source website + * + * @return string|null + */ + public function getLink() + { + if (array_key_exists('link', $this->data)) { + return $this->data['link']; + } + + $link = $this->getExtension('Atom')->getLink(); + + $this->data['link'] = $link; + + return $this->data['link']; + } + + /** + * Get feed image data + * + * @return array|null + */ + public function getImage() + { + if (array_key_exists('image', $this->data)) { + return $this->data['image']; + } + + $link = $this->getExtension('Atom')->getImage(); + + $this->data['image'] = $link; + + return $this->data['image']; + } + + /** + * Get a link to the feed's XML Url + * + * @return string|null + */ + public function getFeedLink() + { + if (array_key_exists('feedlink', $this->data)) { + return $this->data['feedlink']; + } + + $link = $this->getExtension('Atom')->getFeedLink(); + + if ($link === null || empty($link)) { + $link = $this->getOriginalSourceUri(); + } + + $this->data['feedlink'] = $link; + + return $this->data['feedlink']; + } + + /** + * Get the feed title + * + * @return string|null + */ + public function getTitle() + { + if (array_key_exists('title', $this->data)) { + return $this->data['title']; + } + + $title = $this->getExtension('Atom')->getTitle(); + + $this->data['title'] = $title; + + return $this->data['title']; + } + + /** + * Get an array of any supported Pusubhubbub endpoints + * + * @return array|null + */ + public function getHubs() + { + if (array_key_exists('hubs', $this->data)) { + return $this->data['hubs']; + } + + $hubs = $this->getExtension('Atom')->getHubs(); + + $this->data['hubs'] = $hubs; + + return $this->data['hubs']; + } + + /** + * Get all categories + * + * @return Reader\Collection\Category + */ + public function getCategories() + { + if (array_key_exists('categories', $this->data)) { + return $this->data['categories']; + } + + $categoryCollection = $this->getExtension('Atom')->getCategories(); + + if (count($categoryCollection) == 0) { + $categoryCollection = $this->getExtension('DublinCore')->getCategories(); + } + + $this->data['categories'] = $categoryCollection; + + return $this->data['categories']; + } + + /** + * Read all entries to the internal entries array + * + * @return void + */ + protected function indexEntries() + { + if ($this->getType() == Reader\Reader::TYPE_ATOM_10 || + $this->getType() == Reader\Reader::TYPE_ATOM_03) { + $entries = $this->xpath->evaluate('//atom:entry'); + + foreach ($entries as $index => $entry) { + $this->entries[$index] = $entry; + } + } + } + + /** + * Register the default namespaces for the current feed format + * + */ + protected function registerNamespaces() + { + switch ($this->data['type']) { + case Reader\Reader::TYPE_ATOM_03: + $this->xpath->registerNamespace('atom', Reader\Reader::NAMESPACE_ATOM_03); + break; + case Reader\Reader::TYPE_ATOM_10: + default: + $this->xpath->registerNamespace('atom', Reader\Reader::NAMESPACE_ATOM_10); + } + } +} diff --git a/3rdparty/ZendFeed/Reader/Feed/Atom/Source.php b/3rdparty/ZendFeed/Reader/Feed/Atom/Source.php new file mode 100644 index 000000000..fada12859 --- /dev/null +++ b/3rdparty/ZendFeed/Reader/Feed/Atom/Source.php @@ -0,0 +1,94 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Feed\Atom; + +use DOMElement; +use DOMXPath; +use Zend\Feed\Reader; +use Zend\Feed\Reader\Feed; + +/** +*/ +class Source extends Feed\Atom +{ + + /** + * Constructor: Create a Source object which is largely just a normal + * Zend\Feed\Reader\AbstractFeed object only designed to retrieve feed level + * metadata from an Atom entry's source element. + * + * @param DOMElement $source + * @param string $xpathPrefix Passed from parent Entry object + * @param string $type Nearly always Atom 1.0 + */ + public function __construct(DOMElement $source, $xpathPrefix, $type = Reader\Reader::TYPE_ATOM_10) + { + $this->domDocument = $source->ownerDocument; + $this->xpath = new DOMXPath($this->domDocument); + $this->data['type'] = $type; + $this->registerNamespaces(); + $this->loadExtensions(); + + $manager = Reader\Reader::getExtensionManager(); + $extensions = array('Atom\Feed', 'DublinCore\Feed'); + + foreach ($extensions as $name) { + $extension = $manager->get($name); + $extension->setDomDocument($this->domDocument); + $extension->setType($this->data['type']); + $extension->setXpath($this->xpath); + $this->extensions[$name] = $extension; + } + + foreach ($this->extensions as $extension) { + $extension->setXpathPrefix(rtrim($xpathPrefix, '/') . '/atom:source'); + } + } + + /** + * Since this is not an Entry carrier but a vehicle for Feed metadata, any + * applicable Entry methods are stubbed out and do nothing. + */ + + /** + * @return void + */ + public function count() {} + + /** + * @return void + */ + public function current() {} + + /** + * @return void + */ + public function key() {} + + /** + * @return void + */ + public function next() {} + + /** + * @return void + */ + public function rewind() {} + + /** + * @return void + */ + public function valid() {} + + /** + * @return void + */ + protected function indexEntries() {} +} diff --git a/3rdparty/ZendFeed/Reader/Feed/FeedInterface.php b/3rdparty/ZendFeed/Reader/Feed/FeedInterface.php new file mode 100644 index 000000000..4ba3293d4 --- /dev/null +++ b/3rdparty/ZendFeed/Reader/Feed/FeedInterface.php @@ -0,0 +1,111 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Feed; + +use Countable; +use Iterator; + +/** +*/ +interface FeedInterface extends Iterator, Countable +{ + /** + * Get a single author + * + * @param int $index + * @return string|null + */ + public function getAuthor($index = 0); + + /** + * Get an array with feed authors + * + * @return array + */ + public function getAuthors(); + + /** + * Get the copyright entry + * + * @return string|null + */ + public function getCopyright(); + + /** + * Get the feed creation date + * + * @return string|null + */ + public function getDateCreated(); + + /** + * Get the feed modification date + * + * @return string|null + */ + public function getDateModified(); + + /** + * Get the feed description + * + * @return string|null + */ + public function getDescription(); + + /** + * Get the feed generator entry + * + * @return string|null + */ + public function getGenerator(); + + /** + * Get the feed ID + * + * @return string|null + */ + public function getId(); + + /** + * Get the feed language + * + * @return string|null + */ + public function getLanguage(); + + /** + * Get a link to the HTML source + * + * @return string|null + */ + public function getLink(); + + /** + * Get a link to the XML feed + * + * @return string|null + */ + public function getFeedLink(); + + /** + * Get the feed title + * + * @return string|null + */ + public function getTitle(); + + /** + * Get all categories + * + * @return \Zend\Feed\Reader\Collection\Category + */ + public function getCategories(); + +} diff --git a/3rdparty/ZendFeed/Reader/Feed/Rss.php b/3rdparty/ZendFeed/Reader/Feed/Rss.php new file mode 100644 index 000000000..fc7baa131 --- /dev/null +++ b/3rdparty/ZendFeed/Reader/Feed/Rss.php @@ -0,0 +1,707 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Feed; + +use DateTime; +use DOMDocument; +use Zend\Feed\Reader; +use Zend\Feed\Reader\Collection; +use Zend\Feed\Reader\Exception; + +/** +*/ +class Rss extends AbstractFeed +{ + + /** + * Constructor + * + * @param DOMDocument $dom + * @param string $type + */ + public function __construct(DOMDocument $dom, $type = null) + { + parent::__construct($dom, $type); + + $manager = Reader\Reader::getExtensionManager(); + + $feed = $manager->get('DublinCore\Feed'); + $feed->setDomDocument($dom); + $feed->setType($this->data['type']); + $feed->setXpath($this->xpath); + $this->extensions['DublinCore\Feed'] = $feed; + + $feed = $manager->get('Atom\Feed'); + $feed->setDomDocument($dom); + $feed->setType($this->data['type']); + $feed->setXpath($this->xpath); + $this->extensions['Atom\Feed'] = $feed; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 + && $this->getType() !== Reader\Reader::TYPE_RSS_090 + ) { + $xpathPrefix = '/rss/channel'; + } else { + $xpathPrefix = '/rdf:RDF/rss:channel'; + } + foreach ($this->extensions as $extension) { + $extension->setXpathPrefix($xpathPrefix); + } + } + + /** + * Get a single author + * + * @param int $index + * @return string|null + */ + public function getAuthor($index = 0) + { + $authors = $this->getAuthors(); + + if (isset($authors[$index])) { + return $authors[$index]; + } + + return null; + } + + /** + * Get an array with feed authors + * + * @return array + */ + public function getAuthors() + { + if (array_key_exists('authors', $this->data)) { + return $this->data['authors']; + } + + $authors = array(); + $authorsDc = $this->getExtension('DublinCore')->getAuthors(); + if (!empty($authorsDc)) { + foreach ($authorsDc as $author) { + $authors[] = array( + 'name' => $author['name'] + ); + } + } + + /** + * Technically RSS doesn't specific author element use at the feed level + * but it's supported on a "just in case" basis. + */ + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 + && $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $list = $this->xpath->query('//author'); + } else { + $list = $this->xpath->query('//rss:author'); + } + if ($list->length) { + foreach ($list as $author) { + $string = trim($author->nodeValue); + $email = null; + $name = null; + $data = array(); + // Pretty rough parsing - but it's a catchall + if (preg_match("/^.*@[^ ]*/", $string, $matches)) { + $data['email'] = trim($matches[0]); + if (preg_match("/\((.*)\)$/", $string, $matches)) { + $data['name'] = $matches[1]; + } + $authors[] = $data; + } + } + } + + if (count($authors) == 0) { + $authors = $this->getExtension('Atom')->getAuthors(); + } else { + $authors = new Reader\Collection\Author( + Reader\Reader::arrayUnique($authors) + ); + } + + if (count($authors) == 0) { + $authors = null; + } + + $this->data['authors'] = $authors; + + return $this->data['authors']; + } + + /** + * Get the copyright entry + * + * @return string|null + */ + public function getCopyright() + { + if (array_key_exists('copyright', $this->data)) { + return $this->data['copyright']; + } + + $copyright = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $copyright = $this->xpath->evaluate('string(/rss/channel/copyright)'); + } + + if (!$copyright && $this->getExtension('DublinCore') !== null) { + $copyright = $this->getExtension('DublinCore')->getCopyright(); + } + + if (empty($copyright)) { + $copyright = $this->getExtension('Atom')->getCopyright(); + } + + if (!$copyright) { + $copyright = null; + } + + $this->data['copyright'] = $copyright; + + return $this->data['copyright']; + } + + /** + * Get the feed creation date + * + * @return string|null + */ + public function getDateCreated() + { + return $this->getDateModified(); + } + + /** + * Get the feed modification date + * + * @return DateTime |