File indexing completed on 2025-01-19 05:21:05

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Feed_Reader
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0019  * @version    $Id$
0020  */
0021 
0022 /**
0023  * @see Zend_Feed_Reader
0024  */
0025 // require_once 'Zend/Feed/Reader.php';
0026 
0027 /**
0028  * @see Zend_Feed_Reader_EntryInterface
0029  */
0030 // require_once 'Zend/Feed/Reader/EntryInterface.php';
0031 
0032 /**
0033  * @see Zend_Feed_Reader_EntryAbstract
0034  */
0035 // require_once 'Zend/Feed/Reader/EntryAbstract.php';
0036 
0037 /**
0038  * @see Zend_Feed_Reader_Extension_DublinCore_Entry
0039  */
0040 // require_once 'Zend/Feed/Reader/Extension/DublinCore/Entry.php';
0041 
0042 /**
0043  * @see Zend_Feed_Reader_Extension_Content_Entry
0044  */
0045 // require_once 'Zend/Feed/Reader/Extension/Content/Entry.php';
0046 
0047 /**
0048  * @see Zend_Feed_Reader_Extension_Atom_Entry
0049  */
0050 // require_once 'Zend/Feed/Reader/Extension/Atom/Entry.php';
0051 
0052 /**
0053  * @see Zend_Feed_Reader_Extension_WellformedWeb_Entry
0054  */
0055 // require_once 'Zend/Feed/Reader/Extension/WellFormedWeb/Entry.php';
0056 
0057 /**
0058  * @see Zend_Feed_Reader_Extension_Slash_Entry
0059  */
0060 // require_once 'Zend/Feed/Reader/Extension/Slash/Entry.php';
0061 
0062 /**
0063  * @see Zend_Feed_Reader_Extension_Thread_Entry
0064  */
0065 // require_once 'Zend/Feed/Reader/Extension/Thread/Entry.php';
0066 
0067 /**
0068  * @see Zend_Date
0069  */
0070 // require_once 'Zend/Date.php';
0071 
0072 /**
0073  * @see Zend_Feed_Reader_Collection_Category
0074  */
0075 // require_once 'Zend/Feed/Reader/Collection/Category.php';
0076 
0077 /**
0078  * @category   Zend
0079  * @package    Zend_Feed_Reader
0080  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0081  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0082  */
0083 class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_EntryAbstract implements Zend_Feed_Reader_EntryInterface
0084 {
0085 
0086     /**
0087      * XPath query for RDF
0088      *
0089      * @var string
0090      */
0091     protected $_xpathQueryRdf = '';
0092 
0093     /**
0094      * XPath query for RSS
0095      *
0096      * @var string
0097      */
0098     protected $_xpathQueryRss = '';
0099 
0100     /**
0101      * Constructor
0102      *
0103      * @param  Zend_Feed_Entry_Abstract $entry
0104      * @param  string $entryKey
0105      * @param  string $type
0106      * @return void
0107      */
0108     public function __construct(DOMElement $entry, $entryKey, $type = null)
0109     {
0110         parent::__construct($entry, $entryKey, $type);
0111         $this->_xpathQueryRss = '//item[' . ($this->_entryKey+1) . ']';
0112         $this->_xpathQueryRdf = '//rss:item[' . ($this->_entryKey+1) . ']';
0113 
0114         $pluginLoader = Zend_Feed_Reader::getPluginLoader();
0115 
0116         $dublinCoreClass = $pluginLoader->getClassName('DublinCore_Entry');
0117         $this->_extensions['DublinCore_Entry'] = new $dublinCoreClass($entry, $entryKey, $type);
0118 
0119         $contentClass   = $pluginLoader->getClassName('Content_Entry');
0120         $this->_extensions['Content_Entry'] = new $contentClass($entry, $entryKey, $type);
0121 
0122         $atomClass   = $pluginLoader->getClassName('Atom_Entry');
0123         $this->_extensions['Atom_Entry'] = new $atomClass($entry, $entryKey, $type);
0124 
0125         $wfwClass   = $pluginLoader->getClassName('WellFormedWeb_Entry');
0126         $this->_extensions['WellFormedWeb_Entry'] = new $wfwClass($entry, $entryKey, $type);
0127 
0128         $slashClass   = $pluginLoader->getClassName('Slash_Entry');
0129         $this->_extensions['Slash_Entry'] = new $slashClass($entry, $entryKey, $type);
0130 
0131         $threadClass   = $pluginLoader->getClassName('Thread_Entry');
0132         $this->_extensions['Thread_Entry'] = new $threadClass($entry, $entryKey, $type);
0133     }
0134 
0135     /**
0136      * Get an author entry
0137      *
0138      * @param DOMElement $element
0139      * @return string
0140      */
0141     public function getAuthor($index = 0)
0142     {
0143         $authors = $this->getAuthors();
0144 
0145         if (isset($authors[$index])) {
0146             return $authors[$index];
0147         }
0148 
0149         return null;
0150     }
0151 
0152     /**
0153      * Get an array with feed authors
0154      *
0155      * @return array
0156      */
0157     public function getAuthors()
0158     {
0159         if (array_key_exists('authors', $this->_data)) {
0160             return $this->_data['authors'];
0161         }
0162 
0163         $authors = array();
0164         $authors_dc = $this->getExtension('DublinCore')->getAuthors();
0165         if (!empty($authors_dc)) {
0166             foreach ($authors_dc as $author) {
0167                 $authors[] = array(
0168                     'name' => $author['name']
0169                 );
0170             }
0171         }
0172 
0173         if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
0174         && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090) {
0175             $list = $this->_xpath->query($this->_xpathQueryRss . '//author');
0176         } else {
0177             $list = $this->_xpath->query($this->_xpathQueryRdf . '//rss:author');
0178         }
0179         if ($list->length) {
0180             foreach ($list as $author) {
0181                 $string = trim($author->nodeValue);
0182                 $email = null;
0183                 $name = null;
0184                 $data = array();
0185                 // Pretty rough parsing - but it's a catchall
0186                 if (preg_match("/^.*@[^ ]*/", $string, $matches)) {
0187                     $data['email'] = trim($matches[0]);
0188                     if (preg_match("/\((.*)\)$/", $string, $matches)) {
0189                         $data['name'] = $matches[1];
0190                     }
0191                     $authors[] = $data;
0192                 }
0193             }
0194         }
0195 
0196         if (count($authors) == 0) {
0197             $authors = $this->getExtension('Atom')->getAuthors();
0198         } else {
0199             $authors = new Zend_Feed_Reader_Collection_Author(
0200                 Zend_Feed_Reader::arrayUnique($authors)
0201             );
0202         }
0203 
0204         if (count($authors) == 0) {
0205             $authors = null;
0206         }
0207 
0208         $this->_data['authors'] = $authors;
0209 
0210         return $this->_data['authors'];
0211     }
0212 
0213     /**
0214      * Get the entry content
0215      *
0216      * @return string
0217      */
0218     public function getContent()
0219     {
0220         if (array_key_exists('content', $this->_data)) {
0221             return $this->_data['content'];
0222         }
0223 
0224         $content = $this->getExtension('Content')->getContent();
0225 
0226         if (!$content) {
0227             $content = $this->getDescription();
0228         }
0229 
0230         if (empty($content)) {
0231             $content = $this->getExtension('Atom')->getContent();
0232         }
0233 
0234         $this->_data['content'] = $content;
0235 
0236         return $this->_data['content'];
0237     }
0238 
0239     /**
0240      * Get the entry's date of creation
0241      *
0242      * @return string
0243      */
0244     public function getDateCreated()
0245     {
0246         return $this->getDateModified();
0247     }
0248 
0249     /**
0250      * Get the entry's date of modification
0251      *
0252      * @return string
0253      */
0254     public function getDateModified()
0255     {
0256         if (array_key_exists('datemodified', $this->_data)) {
0257             return $this->_data['datemodified'];
0258         }
0259 
0260         $dateModified = null;
0261         $date = null;
0262 
0263         if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
0264             && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090
0265         ) {
0266             $dateModified = $this->_xpath->evaluate('string('.$this->_xpathQueryRss.'/pubDate)');
0267             if ($dateModified) {
0268                 $dateModifiedParsed = strtotime($dateModified);
0269                 if ($dateModifiedParsed) {
0270                     $date = new Zend_Date($dateModifiedParsed);
0271                 } else {
0272                     $dateStandards = array(Zend_Date::RSS, Zend_Date::RFC_822,
0273                     Zend_Date::RFC_2822, Zend_Date::DATES);
0274                     $date = new Zend_Date;
0275                     foreach ($dateStandards as $standard) {
0276                         try {
0277                             $date->set($dateModified, $standard);
0278                             break;
0279                         } catch (Zend_Date_Exception $e) {
0280                             if ($standard == Zend_Date::DATES) {
0281                                 // require_once 'Zend/Feed/Exception.php';
0282                                 throw new Zend_Feed_Exception(
0283                                     'Could not load date due to unrecognised'
0284                                     .' format (should follow RFC 822 or 2822):'
0285                                     . $e->getMessage(),
0286                                     0, $e
0287                                 );
0288                             }
0289                         }
0290                     }
0291                 }
0292             }
0293         }
0294 
0295         if (!$date) {
0296             $date = $this->getExtension('DublinCore')->getDate();
0297         }
0298 
0299         if (!$date) {
0300             $date = $this->getExtension('Atom')->getDateModified();
0301         }
0302 
0303         if (!$date) {
0304             $date = null;
0305         }
0306 
0307         $this->_data['datemodified'] = $date;
0308 
0309         return $this->_data['datemodified'];
0310     }
0311 
0312     /**
0313      * Get the entry description
0314      *
0315      * @return string
0316      */
0317     public function getDescription()
0318     {
0319         if (array_key_exists('description', $this->_data)) {
0320             return $this->_data['description'];
0321         }
0322 
0323         $description = null;
0324 
0325         if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
0326             && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090
0327         ) {
0328             $description = $this->_xpath->evaluate('string('.$this->_xpathQueryRss.'/description)');
0329         } else {
0330             $description = $this->_xpath->evaluate('string('.$this->_xpathQueryRdf.'/rss:description)');
0331         }
0332 
0333         if (!$description) {
0334             $description = $this->getExtension('DublinCore')->getDescription();
0335         }
0336 
0337         if (empty($description)) {
0338             $description = $this->getExtension('Atom')->getDescription();
0339         }
0340 
0341         if (!$description) {
0342             $description = null;
0343         }
0344 
0345         $this->_data['description'] = $description;
0346 
0347         return $this->_data['description'];
0348     }
0349 
0350     /**
0351      * Get the entry enclosure
0352      * @return string
0353      */
0354     public function getEnclosure()
0355     {
0356         if (array_key_exists('enclosure', $this->_data)) {
0357             return $this->_data['enclosure'];
0358         }
0359 
0360         $enclosure = null;
0361 
0362         if ($this->getType() == Zend_Feed_Reader::TYPE_RSS_20) {
0363             $nodeList = $this->_xpath->query($this->_xpathQueryRss . '/enclosure');
0364 
0365             if ($nodeList->length > 0) {
0366                 $enclosure = new stdClass();
0367                 $enclosure->url    = $nodeList->item(0)->getAttribute('url');
0368                 $enclosure->length = $nodeList->item(0)->getAttribute('length');
0369                 $enclosure->type   = $nodeList->item(0)->getAttribute('type');
0370             }
0371         }
0372 
0373         if (!$enclosure) {
0374             $enclosure = $this->getExtension('Atom')->getEnclosure();
0375         }
0376 
0377         $this->_data['enclosure'] = $enclosure;
0378 
0379         return $this->_data['enclosure'];
0380     }
0381 
0382     /**
0383      * Get the entry ID
0384      *
0385      * @return string
0386      */
0387     public function getId()
0388     {
0389         if (array_key_exists('id', $this->_data)) {
0390             return $this->_data['id'];
0391         }
0392 
0393         $id = null;
0394 
0395         if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
0396             && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090
0397         ) {
0398             $id = $this->_xpath->evaluate('string('.$this->_xpathQueryRss.'/guid)');
0399         }
0400 
0401         if (!$id) {
0402             $id = $this->getExtension('DublinCore')->getId();
0403         }
0404 
0405         if (empty($id)) {
0406             $id = $this->getExtension('Atom')->getId();
0407         }
0408 
0409         if (!$id) {
0410             if ($this->getPermalink()) {
0411                 $id = $this->getPermalink();
0412             } elseif ($this->getTitle()) {
0413                 $id = $this->getTitle();
0414             } else {
0415                 $id = null;
0416             }
0417         }
0418 
0419         $this->_data['id'] = $id;
0420 
0421         return $this->_data['id'];
0422     }
0423 
0424     /**
0425      * Get a specific link
0426      *
0427      * @param  int $index
0428      * @return string
0429      */
0430     public function getLink($index = 0)
0431     {
0432         if (!array_key_exists('links', $this->_data)) {
0433             $this->getLinks();
0434         }
0435 
0436         if (isset($this->_data['links'][$index])) {
0437             return $this->_data['links'][$index];
0438         }
0439 
0440         return null;
0441     }
0442 
0443     /**
0444      * Get all links
0445      *
0446      * @return array
0447      */
0448     public function getLinks()
0449     {
0450         if (array_key_exists('links', $this->_data)) {
0451             return $this->_data['links'];
0452         }
0453 
0454         $links = array();
0455 
0456         if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 &&
0457             $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090) {
0458             $list = $this->_xpath->query($this->_xpathQueryRss.'//link');
0459         } else {
0460             $list = $this->_xpath->query($this->_xpathQueryRdf.'//rss:link');
0461         }
0462 
0463         if (!$list->length) {
0464             $links = $this->getExtension('Atom')->getLinks();
0465         } else {
0466             foreach ($list as $link) {
0467                 $links[] = $link->nodeValue;
0468             }
0469         }
0470 
0471         $this->_data['links'] = $links;
0472 
0473         return $this->_data['links'];
0474     }
0475 
0476     /**
0477      * Get all categories
0478      *
0479      * @return Zend_Feed_Reader_Collection_Category
0480      */
0481     public function getCategories()
0482     {
0483         if (array_key_exists('categories', $this->_data)) {
0484             return $this->_data['categories'];
0485         }
0486 
0487         if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 &&
0488             $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090) {
0489             $list = $this->_xpath->query($this->_xpathQueryRss.'//category');
0490         } else {
0491             $list = $this->_xpath->query($this->_xpathQueryRdf.'//rss:category');
0492         }
0493 
0494         if ($list->length) {
0495             $categoryCollection = new Zend_Feed_Reader_Collection_Category;
0496             foreach ($list as $category) {
0497                 $categoryCollection[] = array(
0498                     'term' => $category->nodeValue,
0499                     'scheme' => $category->getAttribute('domain'),
0500                     'label' => $category->nodeValue,
0501                 );
0502             }
0503         } else {
0504             $categoryCollection = $this->getExtension('DublinCore')->getCategories();
0505         }
0506 
0507         if (count($categoryCollection) == 0) {
0508             $categoryCollection = $this->getExtension('Atom')->getCategories();
0509         }
0510 
0511         $this->_data['categories'] = $categoryCollection;
0512 
0513         return $this->_data['categories'];
0514     }
0515 
0516     /**
0517      * Get a permalink to the entry
0518      *
0519      * @return string
0520      */
0521     public function getPermalink()
0522     {
0523         return $this->getLink(0);
0524     }
0525 
0526     /**
0527      * Get the entry title
0528      *
0529      * @return string
0530      */
0531     public function getTitle()
0532     {
0533         if (array_key_exists('title', $this->_data)) {
0534             return $this->_data['title'];
0535         }
0536 
0537         $title = null;
0538 
0539         if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
0540             && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090
0541         ) {
0542             $title = $this->_xpath->evaluate('string('.$this->_xpathQueryRss.'/title)');
0543         } else {
0544             $title = $this->_xpath->evaluate('string('.$this->_xpathQueryRdf.'/rss:title)');
0545         }
0546 
0547         if (!$title) {
0548             $title = $this->getExtension('DublinCore')->getTitle();
0549         }
0550 
0551         if (!$title) {
0552             $title = $this->getExtension('Atom')->getTitle();
0553         }
0554 
0555         if (!$title) {
0556             $title = null;
0557         }
0558 
0559         $this->_data['title'] = $title;
0560 
0561         return $this->_data['title'];
0562     }
0563 
0564     /**
0565      * Get the number of comments/replies for current entry
0566      *
0567      * @return string|null
0568      */
0569     public function getCommentCount()
0570     {
0571         if (array_key_exists('commentcount', $this->_data)) {
0572             return $this->_data['commentcount'];
0573         }
0574 
0575         $commentcount = $this->getExtension('Slash')->getCommentCount();
0576 
0577         if (!$commentcount) {
0578             $commentcount = $this->getExtension('Thread')->getCommentCount();
0579         }
0580 
0581         if (!$commentcount) {
0582             $commentcount = $this->getExtension('Atom')->getCommentCount();
0583         }
0584 
0585         if (!$commentcount) {
0586             $commentcount = null;
0587         }
0588 
0589         $this->_data['commentcount'] = $commentcount;
0590 
0591         return $this->_data['commentcount'];
0592     }
0593 
0594     /**
0595      * Returns a URI pointing to the HTML page where comments can be made on this entry
0596      *
0597      * @return string
0598      */
0599     public function getCommentLink()
0600     {
0601         if (array_key_exists('commentlink', $this->_data)) {
0602             return $this->_data['commentlink'];
0603         }
0604 
0605         $commentlink = null;
0606 
0607         if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
0608             && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090
0609         ) {
0610             $commentlink = $this->_xpath->evaluate('string('.$this->_xpathQueryRss.'/comments)');
0611         }
0612 
0613         if (!$commentlink) {
0614             $commentlink = $this->getExtension('Atom')->getCommentLink();
0615         }
0616 
0617         if (!$commentlink) {
0618             $commentlink = null;
0619         }
0620 
0621         $this->_data['commentlink'] = $commentlink;
0622 
0623         return $this->_data['commentlink'];
0624     }
0625 
0626     /**
0627      * Returns a URI pointing to a feed of all comments for this entry
0628      *
0629      * @return string
0630      */
0631     public function getCommentFeedLink()
0632     {
0633         if (array_key_exists('commentfeedlink', $this->_data)) {
0634             return $this->_data['commentfeedlink'];
0635         }
0636 
0637         $commentfeedlink = $this->getExtension('WellFormedWeb')->getCommentFeedLink();
0638 
0639         if (!$commentfeedlink) {
0640             $commentfeedlink = $this->getExtension('Atom')->getCommentFeedLink('rss');
0641         }
0642 
0643         if (!$commentfeedlink) {
0644             $commentfeedlink = $this->getExtension('Atom')->getCommentFeedLink('rdf');
0645         }
0646 
0647         if (!$commentfeedlink) {
0648             $commentfeedlink = null;
0649         }
0650 
0651         $this->_data['commentfeedlink'] = $commentfeedlink;
0652 
0653         return $this->_data['commentfeedlink'];
0654     }
0655 
0656     /**
0657      * Set the XPath query (incl. on all Extensions)
0658      *
0659      * @param DOMXPath $xpath
0660      */
0661     public function setXpath(DOMXPath $xpath)
0662     {
0663         parent::setXpath($xpath);
0664         foreach ($this->_extensions as $extension) {
0665             $extension->setXpath($this->_xpath);
0666         }
0667     }
0668 }