Added the zend framework 2 library, the path is specified in line no.26 in zend_modul...
[openemr.git] / interface / modules / zend_modules / library / Zend / Feed / Reader / Feed / Rss.php
blob61ce229ba442b322fe41db83579367595bc3f400
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
10 namespace Zend\Feed\Reader\Feed;
12 use DateTime;
13 use DOMDocument;
14 use Zend\Feed\Reader;
15 use Zend\Feed\Reader\Collection;
16 use Zend\Feed\Reader\Exception;
18 /**
20 class Rss extends AbstractFeed
23 /**
24 * Constructor
26 * @param DOMDocument $dom
27 * @param string $type
29 public function __construct(DOMDocument $dom, $type = null)
31 parent::__construct($dom, $type);
33 $manager = Reader\Reader::getExtensionManager();
35 $feed = $manager->get('DublinCore\Feed');
36 $feed->setDomDocument($dom);
37 $feed->setType($this->data['type']);
38 $feed->setXpath($this->xpath);
39 $this->extensions['DublinCore\Feed'] = $feed;
41 $feed = $manager->get('Atom\Feed');
42 $feed->setDomDocument($dom);
43 $feed->setType($this->data['type']);
44 $feed->setXpath($this->xpath);
45 $this->extensions['Atom\Feed'] = $feed;
47 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
48 && $this->getType() !== Reader\Reader::TYPE_RSS_090
49 ) {
50 $xpathPrefix = '/rss/channel';
51 } else {
52 $xpathPrefix = '/rdf:RDF/rss:channel';
54 foreach ($this->extensions as $extension) {
55 $extension->setXpathPrefix($xpathPrefix);
59 /**
60 * Get a single author
62 * @param int $index
63 * @return string|null
65 public function getAuthor($index = 0)
67 $authors = $this->getAuthors();
69 if (isset($authors[$index])) {
70 return $authors[$index];
73 return null;
76 /**
77 * Get an array with feed authors
79 * @return array
81 public function getAuthors()
83 if (array_key_exists('authors', $this->data)) {
84 return $this->data['authors'];
87 $authors = array();
88 $authorsDc = $this->getExtension('DublinCore')->getAuthors();
89 if (!empty($authorsDc)) {
90 foreach ($authorsDc as $author) {
91 $authors[] = array(
92 'name' => $author['name']
97 /**
98 * Technically RSS doesn't specific author element use at the feed level
99 * but it's supported on a "just in case" basis.
101 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
102 && $this->getType() !== Reader\Reader::TYPE_RSS_090) {
103 $list = $this->xpath->query('//author');
104 } else {
105 $list = $this->xpath->query('//rss:author');
107 if ($list->length) {
108 foreach ($list as $author) {
109 $string = trim($author->nodeValue);
110 $email = null;
111 $name = null;
112 $data = array();
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];
119 $authors[] = $data;
124 if (count($authors) == 0) {
125 $authors = $this->getExtension('Atom')->getAuthors();
126 } else {
127 $authors = new Reader\Collection\Author(
128 Reader\Reader::arrayUnique($authors)
132 if (count($authors) == 0) {
133 $authors = null;
136 $this->data['authors'] = $authors;
138 return $this->data['authors'];
142 * Get the copyright entry
144 * @return string|null
146 public function getCopyright()
148 if (array_key_exists('copyright', $this->data)) {
149 return $this->data['copyright'];
152 $copyright = null;
154 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
155 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
156 $copyright = $this->xpath->evaluate('string(/rss/channel/copyright)');
159 if (!$copyright && $this->getExtension('DublinCore') !== null) {
160 $copyright = $this->getExtension('DublinCore')->getCopyright();
163 if (empty($copyright)) {
164 $copyright = $this->getExtension('Atom')->getCopyright();
167 if (!$copyright) {
168 $copyright = null;
171 $this->data['copyright'] = $copyright;
173 return $this->data['copyright'];
177 * Get the feed creation date
179 * @return string|null
181 public function getDateCreated()
183 return $this->getDateModified();
187 * Get the feed modification date
189 * @return DateTime
190 * @throws Exception\RuntimeException
192 public function getDateModified()
194 if (array_key_exists('datemodified', $this->data)) {
195 return $this->data['datemodified'];
198 $dateModified = null;
199 $date = null;
201 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
202 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
203 $dateModified = $this->xpath->evaluate('string(/rss/channel/pubDate)');
204 if (!$dateModified) {
205 $dateModified = $this->xpath->evaluate('string(/rss/channel/lastBuildDate)');
207 if ($dateModified) {
208 $dateModifiedParsed = strtotime($dateModified);
209 if ($dateModifiedParsed) {
210 $date = new DateTime('@' . $dateModifiedParsed);
211 } else {
212 $dateStandards = array(DateTime::RSS, DateTime::RFC822,
213 DateTime::RFC2822, null);
214 foreach ($dateStandards as $standard) {
215 try {
216 $date = DateTime::createFromFormat($standard, $dateModified);
217 break;
218 } catch (\Exception $e) {
219 if ($standard == null) {
220 throw new Exception\RuntimeException(
221 'Could not load date due to unrecognised'
222 .' format (should follow RFC 822 or 2822):'
223 . $e->getMessage(),
224 0, $e
233 if (!$date) {
234 $date = $this->getExtension('DublinCore')->getDate();
237 if (!$date) {
238 $date = $this->getExtension('Atom')->getDateModified();
241 if (!$date) {
242 $date = null;
245 $this->data['datemodified'] = $date;
247 return $this->data['datemodified'];
251 * Get the feed lastBuild date
253 * @throws Exception\RuntimeException
254 * @return DateTime
256 public function getLastBuildDate()
258 if (array_key_exists('lastBuildDate', $this->data)) {
259 return $this->data['lastBuildDate'];
262 $lastBuildDate = null;
263 $date = null;
265 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
266 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
267 $lastBuildDate = $this->xpath->evaluate('string(/rss/channel/lastBuildDate)');
268 if ($lastBuildDate) {
269 $lastBuildDateParsed = strtotime($lastBuildDate);
270 if ($lastBuildDateParsed) {
271 $date = new DateTime('@' . $lastBuildDateParsed);
272 } else {
273 $dateStandards = array(DateTime::RSS, DateTime::RFC822,
274 DateTime::RFC2822, null);
275 foreach ($dateStandards as $standard) {
276 try {
277 $date = DateTime::createFromFormat($standard, $lastBuildDateParsed);
278 break;
279 } catch (\Exception $e) {
280 if ($standard == null) {
281 throw new Exception\RuntimeException(
282 'Could not load date due to unrecognised'
283 .' format (should follow RFC 822 or 2822):'
284 . $e->getMessage(),
285 0, $e
294 if (!$date) {
295 $date = null;
298 $this->data['lastBuildDate'] = $date;
300 return $this->data['lastBuildDate'];
304 * Get the feed description
306 * @return string|null
308 public function getDescription()
310 if (array_key_exists('description', $this->data)) {
311 return $this->data['description'];
314 $description = null;
316 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
317 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
318 $description = $this->xpath->evaluate('string(/rss/channel/description)');
319 } else {
320 $description = $this->xpath->evaluate('string(/rdf:RDF/rss:channel/rss:description)');
323 if (!$description && $this->getExtension('DublinCore') !== null) {
324 $description = $this->getExtension('DublinCore')->getDescription();
327 if (empty($description)) {
328 $description = $this->getExtension('Atom')->getDescription();
331 if (!$description) {
332 $description = null;
335 $this->data['description'] = $description;
337 return $this->data['description'];
341 * Get the feed ID
343 * @return string|null
345 public function getId()
347 if (array_key_exists('id', $this->data)) {
348 return $this->data['id'];
351 $id = null;
353 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
354 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
355 $id = $this->xpath->evaluate('string(/rss/channel/guid)');
358 if (!$id && $this->getExtension('DublinCore') !== null) {
359 $id = $this->getExtension('DublinCore')->getId();
362 if (empty($id)) {
363 $id = $this->getExtension('Atom')->getId();
366 if (!$id) {
367 if ($this->getLink()) {
368 $id = $this->getLink();
369 } elseif ($this->getTitle()) {
370 $id = $this->getTitle();
371 } else {
372 $id = null;
376 $this->data['id'] = $id;
378 return $this->data['id'];
382 * Get the feed image data
384 * @return array|null
386 public function getImage()
388 if (array_key_exists('image', $this->data)) {
389 return $this->data['image'];
392 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
393 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
394 $list = $this->xpath->query('/rss/channel/image');
395 $prefix = '/rss/channel/image[1]';
396 } else {
397 $list = $this->xpath->query('/rdf:RDF/rss:channel/rss:image');
398 $prefix = '/rdf:RDF/rss:channel/rss:image[1]';
400 if ($list->length > 0) {
401 $image = array();
402 $value = $this->xpath->evaluate('string(' . $prefix . '/url)');
403 if ($value) {
404 $image['uri'] = $value;
406 $value = $this->xpath->evaluate('string(' . $prefix . '/link)');
407 if ($value) {
408 $image['link'] = $value;
410 $value = $this->xpath->evaluate('string(' . $prefix . '/title)');
411 if ($value) {
412 $image['title'] = $value;
414 $value = $this->xpath->evaluate('string(' . $prefix . '/height)');
415 if ($value) {
416 $image['height'] = $value;
418 $value = $this->xpath->evaluate('string(' . $prefix . '/width)');
419 if ($value) {
420 $image['width'] = $value;
422 $value = $this->xpath->evaluate('string(' . $prefix . '/description)');
423 if ($value) {
424 $image['description'] = $value;
426 } else {
427 $image = null;
430 $this->data['image'] = $image;
432 return $this->data['image'];
436 * Get the feed language
438 * @return string|null
440 public function getLanguage()
442 if (array_key_exists('language', $this->data)) {
443 return $this->data['language'];
446 $language = null;
448 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
449 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
450 $language = $this->xpath->evaluate('string(/rss/channel/language)');
453 if (!$language && $this->getExtension('DublinCore') !== null) {
454 $language = $this->getExtension('DublinCore')->getLanguage();
457 if (empty($language)) {
458 $language = $this->getExtension('Atom')->getLanguage();
461 if (!$language) {
462 $language = $this->xpath->evaluate('string(//@xml:lang[1])');
465 if (!$language) {
466 $language = null;
469 $this->data['language'] = $language;
471 return $this->data['language'];
475 * Get a link to the feed
477 * @return string|null
479 public function getLink()
481 if (array_key_exists('link', $this->data)) {
482 return $this->data['link'];
485 $link = null;
487 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
488 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
489 $link = $this->xpath->evaluate('string(/rss/channel/link)');
490 } else {
491 $link = $this->xpath->evaluate('string(/rdf:RDF/rss:channel/rss:link)');
494 if (empty($link)) {
495 $link = $this->getExtension('Atom')->getLink();
498 if (!$link) {
499 $link = null;
502 $this->data['link'] = $link;
504 return $this->data['link'];
508 * Get a link to the feed XML
510 * @return string|null
512 public function getFeedLink()
514 if (array_key_exists('feedlink', $this->data)) {
515 return $this->data['feedlink'];
518 $link = null;
520 $link = $this->getExtension('Atom')->getFeedLink();
522 if ($link === null || empty($link)) {
523 $link = $this->getOriginalSourceUri();
526 $this->data['feedlink'] = $link;
528 return $this->data['feedlink'];
532 * Get the feed generator entry
534 * @return string|null
536 public function getGenerator()
538 if (array_key_exists('generator', $this->data)) {
539 return $this->data['generator'];
542 $generator = null;
544 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
545 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
546 $generator = $this->xpath->evaluate('string(/rss/channel/generator)');
549 if (!$generator) {
550 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
551 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
552 $generator = $this->xpath->evaluate('string(/rss/channel/atom:generator)');
553 } else {
554 $generator = $this->xpath->evaluate('string(/rdf:RDF/rss:channel/atom:generator)');
558 if (empty($generator)) {
559 $generator = $this->getExtension('Atom')->getGenerator();
562 if (!$generator) {
563 $generator = null;
566 $this->data['generator'] = $generator;
568 return $this->data['generator'];
572 * Get the feed title
574 * @return string|null
576 public function getTitle()
578 if (array_key_exists('title', $this->data)) {
579 return $this->data['title'];
582 $title = null;
584 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
585 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
586 $title = $this->xpath->evaluate('string(/rss/channel/title)');
587 } else {
588 $title = $this->xpath->evaluate('string(/rdf:RDF/rss:channel/rss:title)');
591 if (!$title && $this->getExtension('DublinCore') !== null) {
592 $title = $this->getExtension('DublinCore')->getTitle();
595 if (!$title) {
596 $title = $this->getExtension('Atom')->getTitle();
599 if (!$title) {
600 $title = null;
603 $this->data['title'] = $title;
605 return $this->data['title'];
609 * Get an array of any supported Pusubhubbub endpoints
611 * @return array|null
613 public function getHubs()
615 if (array_key_exists('hubs', $this->data)) {
616 return $this->data['hubs'];
619 $hubs = $this->getExtension('Atom')->getHubs();
621 if (empty($hubs)) {
622 $hubs = null;
623 } else {
624 $hubs = array_unique($hubs);
627 $this->data['hubs'] = $hubs;
629 return $this->data['hubs'];
633 * Get all categories
635 * @return Reader\Collection\Category
637 public function getCategories()
639 if (array_key_exists('categories', $this->data)) {
640 return $this->data['categories'];
643 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
644 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
645 $list = $this->xpath->query('/rss/channel//category');
646 } else {
647 $list = $this->xpath->query('/rdf:RDF/rss:channel//rss:category');
650 if ($list->length) {
651 $categoryCollection = new Collection\Category;
652 foreach ($list as $category) {
653 $categoryCollection[] = array(
654 'term' => $category->nodeValue,
655 'scheme' => $category->getAttribute('domain'),
656 'label' => $category->nodeValue,
659 } else {
660 $categoryCollection = $this->getExtension('DublinCore')->getCategories();
663 if (count($categoryCollection) == 0) {
664 $categoryCollection = $this->getExtension('Atom')->getCategories();
667 $this->data['categories'] = $categoryCollection;
669 return $this->data['categories'];
673 * Read all entries to the internal entries array
676 protected function indexEntries()
678 $entries = array();
680 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && $this->getType() !== Reader\Reader::TYPE_RSS_090) {
681 $entries = $this->xpath->evaluate('//item');
682 } else {
683 $entries = $this->xpath->evaluate('//rss:item');
686 foreach ($entries as $index => $entry) {
687 $this->entries[$index] = $entry;
692 * Register the default namespaces for the current feed format
695 protected function registerNamespaces()
697 switch ($this->data['type']) {
698 case Reader\Reader::TYPE_RSS_10:
699 $this->xpath->registerNamespace('rdf', Reader\Reader::NAMESPACE_RDF);
700 $this->xpath->registerNamespace('rss', Reader\Reader::NAMESPACE_RSS_10);
701 break;
703 case Reader\Reader::TYPE_RSS_090:
704 $this->xpath->registerNamespace('rdf', Reader\Reader::NAMESPACE_RDF);
705 $this->xpath->registerNamespace('rss', Reader\Reader::NAMESPACE_RSS_090);
706 break;