3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Feed\Reader\Entry;
16 use Zend\Feed\Reader\Exception;
18 class Rss extends AbstractEntry implements EntryInterface
25 protected $xpathQueryRdf = '';
32 protected $xpathQueryRss = '';
37 * @param DOMElement $entry
38 * @param string $entryKey
41 public function __construct(DOMElement $entry, $entryKey, $type = null)
43 parent::__construct($entry, $entryKey, $type);
44 $this->xpathQueryRss = '//item[' . ($this->entryKey + 1) . ']';
45 $this->xpathQueryRdf = '//rss:item[' . ($this->entryKey + 1) . ']';
47 $manager = Reader\Reader::getExtensionManager();
52 'WellFormedWeb\Entry',
56 foreach ($extensions as $name) {
57 $extension = $manager->get($name);
58 $extension->setEntryElement($entry);
59 $extension->setEntryKey($entryKey);
60 $extension->setType($type);
61 $this->extensions[$name] = $extension;
71 public function getAuthor($index = 0)
73 $authors = $this->getAuthors();
75 if (isset($authors[$index])) {
76 return $authors[$index];
83 * Get an array with feed authors
87 public function getAuthors()
89 if (array_key_exists('authors', $this->data)) {
90 return $this->data['authors'];
94 $authorsDc = $this->getExtension('DublinCore')->getAuthors();
95 if (! empty($authorsDc)) {
96 foreach ($authorsDc as $author) {
98 'name' => $author['name']
103 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
104 && $this->getType() !== Reader\Reader::TYPE_RSS_090) {
105 $list = $this->xpath->query($this->xpathQueryRss . '//author');
107 $list = $this->xpath->query($this->xpathQueryRdf . '//rss:author');
110 foreach ($list as $author) {
111 $string = trim($author->nodeValue);
113 // Pretty rough parsing - but it's a catchall
114 if (preg_match("/^.*@[^ ]*/", $string, $matches)) {
115 $data['email'] = trim($matches[0]);
116 if (preg_match("/\((.*)\)$/", $string, $matches)) {
117 $data['name'] = $matches[1];
124 if (count($authors) == 0) {
125 $authors = $this->getExtension('Atom')->getAuthors();
127 $authors = new Reader\Collection\Author(
128 Reader\Reader::arrayUnique($authors)
132 if (count($authors) == 0) {
136 $this->data['authors'] = $authors;
138 return $this->data['authors'];
142 * Get the entry content
146 public function getContent()
148 if (array_key_exists('content', $this->data)) {
149 return $this->data['content'];
152 $content = $this->getExtension('Content')->getContent();
155 $content = $this->getDescription();
158 if (empty($content)) {
159 $content = $this->getExtension('Atom')->getContent();
162 $this->data['content'] = $content;
164 return $this->data['content'];
168 * Get the entry's date of creation
172 public function getDateCreated()
174 return $this->getDateModified();
178 * Get the entry's date of modification
180 * @throws Exception\RuntimeException
183 public function getDateModified()
185 if (array_key_exists('datemodified', $this->data)) {
186 return $this->data['datemodified'];
191 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
192 && $this->getType() !== Reader\Reader::TYPE_RSS_090
194 $dateModified = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/pubDate)');
196 $dateModifiedParsed = strtotime($dateModified);
197 if ($dateModifiedParsed) {
198 $date = new DateTime('@' . $dateModifiedParsed);
200 $dateStandards = [DateTime::RSS, DateTime::RFC822,
201 DateTime::RFC2822, null];
202 foreach ($dateStandards as $standard) {
204 $date = date_create_from_format($standard, $dateModified);
206 } catch (\Exception $e) {
207 if ($standard === null) {
208 throw new Exception\RuntimeException(
209 'Could not load date due to unrecognised'
210 .' format (should follow RFC 822 or 2822):'
223 $date = $this->getExtension('DublinCore')->getDate();
227 $date = $this->getExtension('Atom')->getDateModified();
234 $this->data['datemodified'] = $date;
236 return $this->data['datemodified'];
240 * Get the entry description
244 public function getDescription()
246 if (array_key_exists('description', $this->data)) {
247 return $this->data['description'];
252 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
253 && $this->getType() !== Reader\Reader::TYPE_RSS_090
255 $description = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/description)');
257 $description = $this->xpath->evaluate('string(' . $this->xpathQueryRdf . '/rss:description)');
260 if (! $description) {
261 $description = $this->getExtension('DublinCore')->getDescription();
264 if (empty($description)) {
265 $description = $this->getExtension('Atom')->getDescription();
268 if (! $description) {
272 $this->data['description'] = $description;
274 return $this->data['description'];
278 * Get the entry enclosure
281 public function getEnclosure()
283 if (array_key_exists('enclosure', $this->data)) {
284 return $this->data['enclosure'];
289 if ($this->getType() == Reader\Reader::TYPE_RSS_20) {
290 $nodeList = $this->xpath->query($this->xpathQueryRss . '/enclosure');
292 if ($nodeList->length > 0) {
293 $enclosure = new \stdClass();
294 $enclosure->url = $nodeList->item(0)->getAttribute('url');
295 $enclosure->length = $nodeList->item(0)->getAttribute('length');
296 $enclosure->type = $nodeList->item(0)->getAttribute('type');
301 $enclosure = $this->getExtension('Atom')->getEnclosure();
304 $this->data['enclosure'] = $enclosure;
306 return $this->data['enclosure'];
314 public function getId()
316 if (array_key_exists('id', $this->data)) {
317 return $this->data['id'];
322 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
323 && $this->getType() !== Reader\Reader::TYPE_RSS_090
325 $id = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/guid)');
329 $id = $this->getExtension('DublinCore')->getId();
333 $id = $this->getExtension('Atom')->getId();
337 if ($this->getPermalink()) {
338 $id = $this->getPermalink();
339 } elseif ($this->getTitle()) {
340 $id = $this->getTitle();
346 $this->data['id'] = $id;
348 return $this->data['id'];
352 * Get a specific link
357 public function getLink($index = 0)
359 if (! array_key_exists('links', $this->data)) {
363 if (isset($this->data['links'][$index])) {
364 return $this->data['links'][$index];
375 public function getLinks()
377 if (array_key_exists('links', $this->data)) {
378 return $this->data['links'];
383 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
384 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
385 $list = $this->xpath->query($this->xpathQueryRss . '//link');
387 $list = $this->xpath->query($this->xpathQueryRdf . '//rss:link');
390 if (! $list->length) {
391 $links = $this->getExtension('Atom')->getLinks();
393 foreach ($list as $link) {
394 $links[] = $link->nodeValue;
398 $this->data['links'] = $links;
400 return $this->data['links'];
406 * @return Reader\Collection\Category
408 public function getCategories()
410 if (array_key_exists('categories', $this->data)) {
411 return $this->data['categories'];
414 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
415 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
416 $list = $this->xpath->query($this->xpathQueryRss . '//category');
418 $list = $this->xpath->query($this->xpathQueryRdf . '//rss:category');
422 $categoryCollection = new Reader\Collection\Category;
423 foreach ($list as $category) {
424 $categoryCollection[] = [
425 'term' => $category->nodeValue,
426 'scheme' => $category->getAttribute('domain'),
427 'label' => $category->nodeValue,
431 $categoryCollection = $this->getExtension('DublinCore')->getCategories();
434 if (count($categoryCollection) == 0) {
435 $categoryCollection = $this->getExtension('Atom')->getCategories();
438 $this->data['categories'] = $categoryCollection;
440 return $this->data['categories'];
444 * Get a permalink to the entry
448 public function getPermalink()
450 return $this->getLink(0);
454 * Get the entry title
458 public function getTitle()
460 if (array_key_exists('title', $this->data)) {
461 return $this->data['title'];
466 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
467 && $this->getType() !== Reader\Reader::TYPE_RSS_090
469 $title = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/title)');
471 $title = $this->xpath->evaluate('string(' . $this->xpathQueryRdf . '/rss:title)');
475 $title = $this->getExtension('DublinCore')->getTitle();
479 $title = $this->getExtension('Atom')->getTitle();
486 $this->data['title'] = $title;
488 return $this->data['title'];
492 * Get the number of comments/replies for current entry
494 * @return string|null
496 public function getCommentCount()
498 if (array_key_exists('commentcount', $this->data)) {
499 return $this->data['commentcount'];
502 $commentcount = $this->getExtension('Slash')->getCommentCount();
504 if (! $commentcount) {
505 $commentcount = $this->getExtension('Thread')->getCommentCount();
508 if (! $commentcount) {
509 $commentcount = $this->getExtension('Atom')->getCommentCount();
512 if (! $commentcount) {
513 $commentcount = null;
516 $this->data['commentcount'] = $commentcount;
518 return $this->data['commentcount'];
522 * Returns a URI pointing to the HTML page where comments can be made on this entry
526 public function getCommentLink()
528 if (array_key_exists('commentlink', $this->data)) {
529 return $this->data['commentlink'];
534 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
535 && $this->getType() !== Reader\Reader::TYPE_RSS_090
537 $commentlink = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/comments)');
540 if (! $commentlink) {
541 $commentlink = $this->getExtension('Atom')->getCommentLink();
544 if (! $commentlink) {
548 $this->data['commentlink'] = $commentlink;
550 return $this->data['commentlink'];
554 * Returns a URI pointing to a feed of all comments for this entry
558 public function getCommentFeedLink()
560 if (array_key_exists('commentfeedlink', $this->data)) {
561 return $this->data['commentfeedlink'];
564 $commentfeedlink = $this->getExtension('WellFormedWeb')->getCommentFeedLink();
566 if (! $commentfeedlink) {
567 $commentfeedlink = $this->getExtension('Atom')->getCommentFeedLink('rss');
570 if (! $commentfeedlink) {
571 $commentfeedlink = $this->getExtension('Atom')->getCommentFeedLink('rdf');
574 if (! $commentfeedlink) {
575 $commentfeedlink = null;
578 $this->data['commentfeedlink'] = $commentfeedlink;
580 return $this->data['commentfeedlink'];
584 * Set the XPath query (incl. on all Extensions)
586 * @param DOMXPath $xpath
589 public function setXpath(DOMXPath $xpath)
591 parent::setXpath($xpath);
592 foreach ($this->extensions as $extension) {
593 $extension->setXpath($this->xpath);