/zf/library/Zend/Feed/Abstract.php
PHP | 259 lines | 93 code | 32 blank | 134 comment | 10 complexity | 3b04ad6d95fef4ab8319d4273586f221 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, Apache-2.0, LGPL-2.1, LGPL-3.0, BSD-2-Clause
1<?php 2 3/** 4 * Zend Framework 5 * 6 * LICENSE 7 * 8 * This source file is subject to the new BSD license that is bundled 9 * with this package in the file LICENSE.txt. 10 * It is also available through the world-wide-web at this URL: 11 * http://framework.zend.com/license/new-bsd 12 * If you did not receive a copy of the license and are unable to 13 * obtain it through the world-wide-web, please send an email 14 * to license@zend.com so we can send you a copy immediately. 15 * 16 * @category Zend 17 * @package Zend_Feed 18 * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) 19 * @license http://framework.zend.com/license/new-bsd New BSD License 20 * @version $Id: Abstract.php 23775 2011-03-01 17:25:24Z ralph $ 21 */ 22 23 24/** 25 * @see Zend_Feed_Element 26 */ 27require_once 'Zend/Feed/Element.php'; 28 29 30/** 31 * The Zend_Feed_Abstract class is an abstract class representing feeds. 32 * 33 * Zend_Feed_Abstract implements two core PHP 5 interfaces: ArrayAccess and 34 * Iterator. In both cases the collection being treated as an array is 35 * considered to be the entry collection, such that iterating over the 36 * feed takes you through each of the feed.s entries. 37 * 38 * @category Zend 39 * @package Zend_Feed 40 * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) 41 * @license http://framework.zend.com/license/new-bsd New BSD License 42 */ 43abstract class Zend_Feed_Abstract extends Zend_Feed_Element implements Iterator, Countable 44{ 45 /** 46 * Current index on the collection of feed entries for the 47 * Iterator implementation. 48 * 49 * @var integer 50 */ 51 protected $_entryIndex = 0; 52 53 /** 54 * Cache of feed entries. 55 * 56 * @var array 57 */ 58 protected $_entries; 59 60 /** 61 * Feed constructor 62 * 63 * The Zend_Feed_Abstract constructor takes the URI of a feed or a 64 * feed represented as a string and loads it as XML. 65 * 66 * @param string $uri The full URI of the feed to load, or NULL if not retrieved via HTTP or as an array. 67 * @param string $string The feed as a string, or NULL if retrieved via HTTP or as an array. 68 * @param Zend_Feed_Builder_Interface $builder The feed as a builder instance or NULL if retrieved as a string or via HTTP. 69 * @return void 70 * @throws Zend_Feed_Exception If loading the feed failed. 71 */ 72 public function __construct($uri = null, $string = null, Zend_Feed_Builder_Interface $builder = null) 73 { 74 if ($uri !== null) { 75 // Retrieve the feed via HTTP 76 $client = Zend_Feed::getHttpClient(); 77 $client->setUri($uri); 78 $response = $client->request('GET'); 79 if ($response->getStatus() !== 200) { 80 /** 81 * @see Zend_Feed_Exception 82 */ 83 require_once 'Zend/Feed/Exception.php'; 84 throw new Zend_Feed_Exception('Feed failed to load, got response code ' . $response->getStatus()); 85 } 86 $this->_element = $response->getBody(); 87 $this->__wakeup(); 88 } elseif ($string !== null) { 89 // Retrieve the feed from $string 90 $this->_element = $string; 91 $this->__wakeup(); 92 } else { 93 // Generate the feed from the array 94 $header = $builder->getHeader(); 95 $this->_element = new DOMDocument('1.0', $header['charset']); 96 $root = $this->_mapFeedHeaders($header); 97 $this->_mapFeedEntries($root, $builder->getEntries()); 98 $this->_element = $root; 99 $this->_buildEntryCache(); 100 } 101 } 102 103 104 /** 105 * Load the feed as an XML DOMDocument object 106 * 107 * @return void 108 * @throws Zend_Feed_Exception 109 */ 110 public function __wakeup() 111 { 112 @ini_set('track_errors', 1); 113 $doc = new DOMDocument; 114 $status = @$doc->loadXML($this->_element); 115 @ini_restore('track_errors'); 116 117 if (!$status) { 118 // prevent the class to generate an undefined variable notice (ZF-2590) 119 if (!isset($php_errormsg)) { 120 if (function_exists('xdebug_is_enabled')) { 121 $php_errormsg = '(error message not available, when XDebug is running)'; 122 } else { 123 $php_errormsg = '(error message not available)'; 124 } 125 } 126 127 /** 128 * @see Zend_Feed_Exception 129 */ 130 require_once 'Zend/Feed/Exception.php'; 131 throw new Zend_Feed_Exception("DOMDocument cannot parse XML: $php_errormsg"); 132 } 133 134 $this->_element = $doc; 135 } 136 137 138 /** 139 * Prepare for serialiation 140 * 141 * @return array 142 */ 143 public function __sleep() 144 { 145 $this->_element = $this->saveXML(); 146 147 return array('_element'); 148 } 149 150 151 /** 152 * Cache the individual feed elements so they don't need to be 153 * searched for on every operation. 154 * 155 * @return void 156 */ 157 protected function _buildEntryCache() 158 { 159 $this->_entries = array(); 160 foreach ($this->_element->childNodes as $child) { 161 if ($child->localName == $this->_entryElementName) { 162 $this->_entries[] = $child; 163 } 164 } 165 } 166 167 168 /** 169 * Get the number of entries in this feed object. 170 * 171 * @return integer Entry count. 172 */ 173 public function count() 174 { 175 return count($this->_entries); 176 } 177 178 179 /** 180 * Required by the Iterator interface. 181 * 182 * @return void 183 */ 184 public function rewind() 185 { 186 $this->_entryIndex = 0; 187 } 188 189 190 /** 191 * Required by the Iterator interface. 192 * 193 * @return mixed The current row, or null if no rows. 194 */ 195 public function current() 196 { 197 return new $this->_entryClassName( 198 null, 199 $this->_entries[$this->_entryIndex]); 200 } 201 202 203 /** 204 * Required by the Iterator interface. 205 * 206 * @return mixed The current row number (starts at 0), or NULL if no rows 207 */ 208 public function key() 209 { 210 return $this->_entryIndex; 211 } 212 213 214 /** 215 * Required by the Iterator interface. 216 * 217 * @return mixed The next row, or null if no more rows. 218 */ 219 public function next() 220 { 221 ++$this->_entryIndex; 222 } 223 224 225 /** 226 * Required by the Iterator interface. 227 * 228 * @return boolean Whether the iteration is valid 229 */ 230 public function valid() 231 { 232 return 0 <= $this->_entryIndex && $this->_entryIndex < $this->count(); 233 } 234 235 /** 236 * Generate the header of the feed when working in write mode 237 * 238 * @param array $array the data to use 239 * @return DOMElement root node 240 */ 241 abstract protected function _mapFeedHeaders($array); 242 243 /** 244 * Generate the entries of the feed when working in write mode 245 * 246 * @param DOMElement $root the root node to use 247 * @param array $array the data to use 248 * @return DOMElement root node 249 */ 250 abstract protected function _mapFeedEntries(DOMElement $root, $array); 251 252 /** 253 * Send feed to a http client with the correct header 254 * 255 * @throws Zend_Feed_Exception if headers have already been sent 256 * @return void 257 */ 258 abstract public function send(); 259}