File indexing completed on 2024-12-22 05:36:40
0001 <?php 0002 0003 /** 0004 * Zend Framework 0005 * 0006 * LICENSE 0007 * 0008 * This source file is subject to the new BSD license that is bundled 0009 * with this package in the file LICENSE.txt. 0010 * It is also available through the world-wide-web at this URL: 0011 * http://framework.zend.com/license/new-bsd 0012 * If you did not receive a copy of the license and are unable to 0013 * obtain it through the world-wide-web, please send an email 0014 * to license@zend.com so we can send you a copy immediately. 0015 * 0016 * @category Zend 0017 * @package Zend_Feed 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 0024 /** 0025 * @see Zend_Feed_Abstract 0026 */ 0027 // require_once 'Zend/Feed/Abstract.php'; 0028 0029 /** 0030 * @see Zend_Feed_Entry_Atom 0031 */ 0032 // require_once 'Zend/Feed/Entry/Atom.php'; 0033 0034 0035 /** 0036 * Atom feed class 0037 * 0038 * The Zend_Feed_Atom class is a concrete subclass of the general 0039 * Zend_Feed_Abstract class, tailored for representing an Atom 0040 * feed. It shares all of the same methods with its abstract 0041 * parent. The distinction is made in the format of data that 0042 * Zend_Feed_Atom expects, and as a further pointer for users as to 0043 * what kind of feed object they have been passed. 0044 * 0045 * @category Zend 0046 * @package Zend_Feed 0047 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0048 * @license http://framework.zend.com/license/new-bsd New BSD License 0049 */ 0050 class Zend_Feed_Atom extends Zend_Feed_Abstract 0051 { 0052 0053 /** 0054 * The classname for individual feed elements. 0055 * 0056 * @var string 0057 */ 0058 protected $_entryClassName = 'Zend_Feed_Entry_Atom'; 0059 0060 /** 0061 * The element name for individual feed elements (Atom <entry> 0062 * elements). 0063 * 0064 * @var string 0065 */ 0066 protected $_entryElementName = 'entry'; 0067 0068 /** 0069 * The default namespace for Atom feeds. 0070 * 0071 * @var string 0072 */ 0073 protected $_defaultNamespace = 'atom'; 0074 0075 0076 /** 0077 * Override Zend_Feed_Abstract to set up the $_element and $_entries aliases. 0078 * 0079 * @return void 0080 * @throws Zend_Feed_Exception 0081 */ 0082 public function __wakeup() 0083 { 0084 parent::__wakeup(); 0085 0086 // Find the base feed element and create an alias to it. 0087 $element = $this->_element->getElementsByTagName('feed')->item(0); 0088 if (!$element) { 0089 // Try to find a single <entry> instead. 0090 $element = $this->_element->getElementsByTagName($this->_entryElementName)->item(0); 0091 if (!$element) { 0092 /** 0093 * @see Zend_Feed_Exception 0094 */ 0095 // require_once 'Zend/Feed/Exception.php'; 0096 throw new Zend_Feed_Exception('No root <feed> or <' . $this->_entryElementName 0097 . '> element found, cannot parse feed.'); 0098 } 0099 0100 $doc = new DOMDocument($this->_element->version, 0101 $this->_element->actualEncoding); 0102 $feed = $doc->appendChild($doc->createElement('feed')); 0103 $feed->appendChild($doc->importNode($element, true)); 0104 $element = $feed; 0105 } 0106 0107 $this->_element = $element; 0108 0109 // Find the entries and save a pointer to them for speed and 0110 // simplicity. 0111 $this->_buildEntryCache(); 0112 } 0113 0114 0115 /** 0116 * Easy access to <link> tags keyed by "rel" attributes. 0117 * 0118 * If $elt->link() is called with no arguments, we will attempt to 0119 * return the value of the <link> tag(s) like all other 0120 * method-syntax attribute access. If an argument is passed to 0121 * link(), however, then we will return the "href" value of the 0122 * first <link> tag that has a "rel" attribute matching $rel: 0123 * 0124 * $elt->link(): returns the value of the link tag. 0125 * $elt->link('self'): returns the href from the first <link rel="self"> in the entry. 0126 * 0127 * @param string $rel The "rel" attribute to look for. 0128 * @return mixed 0129 */ 0130 public function link($rel = null) 0131 { 0132 if ($rel === null) { 0133 return parent::__call('link', null); 0134 } 0135 0136 // index link tags by their "rel" attribute. 0137 $links = parent::__get('link'); 0138 if (!is_array($links)) { 0139 if ($links instanceof Zend_Feed_Element) { 0140 $links = array($links); 0141 } else { 0142 return $links; 0143 } 0144 } 0145 0146 foreach ($links as $link) { 0147 if (empty($link['rel'])) { 0148 continue; 0149 } 0150 if ($rel == $link['rel']) { 0151 return $link['href']; 0152 } 0153 } 0154 0155 return null; 0156 } 0157 0158 0159 /** 0160 * Make accessing some individual elements of the feed easier. 0161 * 0162 * Special accessors 'entry' and 'entries' are provided so that if 0163 * you wish to iterate over an Atom feed's entries, you can do so 0164 * using foreach ($feed->entries as $entry) or foreach 0165 * ($feed->entry as $entry). 0166 * 0167 * @param string $var The property to access. 0168 * @return mixed 0169 */ 0170 public function __get($var) 0171 { 0172 switch ($var) { 0173 case 'entry': 0174 // fall through to the next case 0175 case 'entries': 0176 return $this; 0177 0178 default: 0179 return parent::__get($var); 0180 } 0181 } 0182 0183 /** 0184 * Generate the header of the feed when working in write mode 0185 * 0186 * @param array $array the data to use 0187 * @return DOMElement root node 0188 */ 0189 protected function _mapFeedHeaders($array) 0190 { 0191 $feed = $this->_element->createElement('feed'); 0192 $feed->setAttribute('xmlns', 'http://www.w3.org/2005/Atom'); 0193 0194 $id = $this->_element->createElement('id', $array->link); 0195 $feed->appendChild($id); 0196 0197 $title = $this->_element->createElement('title'); 0198 $title->appendChild($this->_element->createCDATASection($array->title)); 0199 $feed->appendChild($title); 0200 0201 if (isset($array->author)) { 0202 $author = $this->_element->createElement('author'); 0203 $name = $this->_element->createElement('name', $array->author); 0204 $author->appendChild($name); 0205 if (isset($array->email)) { 0206 $email = $this->_element->createElement('email', $array->email); 0207 $author->appendChild($email); 0208 } 0209 $feed->appendChild($author); 0210 } 0211 0212 $updated = isset($array->lastUpdate) ? $array->lastUpdate : time(); 0213 $updated = $this->_element->createElement('updated', date(DATE_ATOM, $updated)); 0214 $feed->appendChild($updated); 0215 0216 if (isset($array->published)) { 0217 $published = $this->_element->createElement('published', date(DATE_ATOM, $array->published)); 0218 $feed->appendChild($published); 0219 } 0220 0221 $link = $this->_element->createElement('link'); 0222 $link->setAttribute('rel', 'self'); 0223 $link->setAttribute('href', $array->link); 0224 if (isset($array->language)) { 0225 $link->setAttribute('hreflang', $array->language); 0226 } 0227 $feed->appendChild($link); 0228 0229 if (isset($array->description)) { 0230 $subtitle = $this->_element->createElement('subtitle'); 0231 $subtitle->appendChild($this->_element->createCDATASection($array->description)); 0232 $feed->appendChild($subtitle); 0233 } 0234 0235 if (isset($array->copyright)) { 0236 $copyright = $this->_element->createElement('rights', $array->copyright); 0237 $feed->appendChild($copyright); 0238 } 0239 0240 if (isset($array->image)) { 0241 $image = $this->_element->createElement('logo', $array->image); 0242 $feed->appendChild($image); 0243 } 0244 0245 $generator = !empty($array->generator) ? $array->generator : 'Zend_Feed'; 0246 $generator = $this->_element->createElement('generator', $generator); 0247 $feed->appendChild($generator); 0248 0249 return $feed; 0250 } 0251 0252 /** 0253 * Generate the entries of the feed when working in write mode 0254 * 0255 * The following nodes are constructed for each feed entry 0256 * <entry> 0257 * <id>url to feed entry</id> 0258 * <title>entry title</title> 0259 * <updated>last update</updated> 0260 * <link rel="alternate" href="url to feed entry" /> 0261 * <summary>short text</summary> 0262 * <content>long version, can contain html</content> 0263 * </entry> 0264 * 0265 * @param array $array the data to use 0266 * @param DOMElement $root the root node to use 0267 * @return void 0268 */ 0269 protected function _mapFeedEntries(DOMElement $root, $array) 0270 { 0271 foreach ($array as $dataentry) { 0272 $entry = $this->_element->createElement('entry'); 0273 0274 $id = $this->_element->createElement('id', isset($dataentry->guid) ? $dataentry->guid : $dataentry->link); 0275 $entry->appendChild($id); 0276 0277 $title = $this->_element->createElement('title'); 0278 $title->appendChild($this->_element->createCDATASection($dataentry->title)); 0279 $entry->appendChild($title); 0280 0281 $updated = isset($dataentry->lastUpdate) ? $dataentry->lastUpdate : time(); 0282 $updated = $this->_element->createElement('updated', date(DATE_ATOM, $updated)); 0283 $entry->appendChild($updated); 0284 0285 $link = $this->_element->createElement('link'); 0286 $link->setAttribute('rel', 'alternate'); 0287 $link->setAttribute('href', $dataentry->link); 0288 $entry->appendChild($link); 0289 0290 $summary = $this->_element->createElement('summary'); 0291 $summary->appendChild($this->_element->createCDATASection($dataentry->description)); 0292 $entry->appendChild($summary); 0293 0294 if (isset($dataentry->content)) { 0295 $content = $this->_element->createElement('content'); 0296 $content->setAttribute('type', 'html'); 0297 $content->appendChild($this->_element->createCDATASection($dataentry->content)); 0298 $entry->appendChild($content); 0299 } 0300 0301 if (isset($dataentry->category)) { 0302 foreach ($dataentry->category as $category) { 0303 $node = $this->_element->createElement('category'); 0304 $node->setAttribute('term', $category['term']); 0305 if (isset($category['scheme'])) { 0306 $node->setAttribute('scheme', $category['scheme']); 0307 } 0308 $entry->appendChild($node); 0309 } 0310 } 0311 0312 if (isset($dataentry->source)) { 0313 $source = $this->_element->createElement('source'); 0314 $title = $this->_element->createElement('title', $dataentry->source['title']); 0315 $source->appendChild($title); 0316 $link = $this->_element->createElement('link', $dataentry->source['title']); 0317 $link->setAttribute('rel', 'alternate'); 0318 $link->setAttribute('href', $dataentry->source['url']); 0319 $source->appendChild($link); 0320 } 0321 0322 if (isset($dataentry->enclosure)) { 0323 foreach ($dataentry->enclosure as $enclosure) { 0324 $node = $this->_element->createElement('link'); 0325 $node->setAttribute('rel', 'enclosure'); 0326 $node->setAttribute('href', $enclosure['url']); 0327 if (isset($enclosure['type'])) { 0328 $node->setAttribute('type', $enclosure['type']); 0329 } 0330 if (isset($enclosure['length'])) { 0331 $node->setAttribute('length', $enclosure['length']); 0332 } 0333 $entry->appendChild($node); 0334 } 0335 } 0336 0337 if (isset($dataentry->comments)) { 0338 $comments = $this->_element->createElementNS('http://wellformedweb.org/CommentAPI/', 0339 'wfw:comment', 0340 $dataentry->comments); 0341 $entry->appendChild($comments); 0342 } 0343 if (isset($dataentry->commentRss)) { 0344 $comments = $this->_element->createElementNS('http://wellformedweb.org/CommentAPI/', 0345 'wfw:commentRss', 0346 $dataentry->commentRss); 0347 $entry->appendChild($comments); 0348 } 0349 0350 $root->appendChild($entry); 0351 } 0352 } 0353 0354 /** 0355 * Override Zend_Feed_Element to allow formated feeds 0356 * 0357 * @return string 0358 */ 0359 public function saveXml() 0360 { 0361 // Return a complete document including XML prologue. 0362 $doc = new DOMDocument($this->_element->ownerDocument->version, 0363 $this->_element->ownerDocument->actualEncoding); 0364 $doc->appendChild($doc->importNode($this->_element, true)); 0365 $doc->formatOutput = true; 0366 0367 return $doc->saveXML(); 0368 } 0369 0370 /** 0371 * Send feed to a http client with the correct header 0372 * 0373 * @return void 0374 * @throws Zend_Feed_Exception if headers have already been sent 0375 */ 0376 public function send() 0377 { 0378 if (headers_sent()) { 0379 /** 0380 * @see Zend_Feed_Exception 0381 */ 0382 // require_once 'Zend/Feed/Exception.php'; 0383 throw new Zend_Feed_Exception('Cannot send ATOM because headers have already been sent.'); 0384 } 0385 0386 header('Content-Type: application/atom+xml; charset=' . $this->_element->ownerDocument->actualEncoding); 0387 0388 echo $this->saveXML(); 0389 } 0390 }