*prechod na novsiu verziu ZF
[sport-group.git] / library / Zend / Feed.php
blobeeedca012bba23b018288f8edbd86ecc34f3b0b3
1 <?php
3 /**
4 * Zend Framework
6 * LICENSE
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.
16 * @category Zend
17 * @package Zend_Feed
18 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license http://framework.zend.com/license/new-bsd New BSD License
20 * @version $Id: Feed.php 16205 2009-06-21 19:08:45Z thomas $
24 /**
25 * Feed utility class
27 * Base Zend_Feed class, containing constants and the Zend_Http_Client instance
28 * accessor.
30 * @category Zend
31 * @package Zend_Feed
32 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
33 * @license http://framework.zend.com/license/new-bsd New BSD License
35 class Zend_Feed
38 /**
39 * HTTP client object to use for retrieving feeds
41 * @var Zend_Http_Client
43 protected static $_httpClient = null;
45 /**
46 * Override HTTP PUT and DELETE request methods?
48 * @var boolean
50 protected static $_httpMethodOverride = false;
52 /**
53 * @var array
55 protected static $_namespaces = array(
56 'opensearch' => 'http://a9.com/-/spec/opensearchrss/1.0/',
57 'atom' => 'http://www.w3.org/2005/Atom',
58 'rss' => 'http://blogs.law.harvard.edu/tech/rss',
62 /**
63 * Set the HTTP client instance
65 * Sets the HTTP client object to use for retrieving the feeds.
67 * @param Zend_Http_Client $httpClient
68 * @return void
70 public static function setHttpClient(Zend_Http_Client $httpClient)
72 self::$_httpClient = $httpClient;
76 /**
77 * Gets the HTTP client object. If none is set, a new Zend_Http_Client will be used.
79 * @return Zend_Http_Client_Abstract
81 public static function getHttpClient()
83 if (!self::$_httpClient instanceof Zend_Http_Client) {
84 /**
85 * @see Zend_Http_Client
87 require_once 'Zend/Http/Client.php';
88 self::$_httpClient = new Zend_Http_Client();
91 return self::$_httpClient;
95 /**
96 * Toggle using POST instead of PUT and DELETE HTTP methods
98 * Some feed implementations do not accept PUT and DELETE HTTP
99 * methods, or they can't be used because of proxies or other
100 * measures. This allows turning on using POST where PUT and
101 * DELETE would normally be used; in addition, an
102 * X-Method-Override header will be sent with a value of PUT or
103 * DELETE as appropriate.
105 * @param boolean $override Whether to override PUT and DELETE.
106 * @return void
108 public static function setHttpMethodOverride($override = true)
110 self::$_httpMethodOverride = $override;
115 * Get the HTTP override state
117 * @return boolean
119 public static function getHttpMethodOverride()
121 return self::$_httpMethodOverride;
126 * Get the full version of a namespace prefix
128 * Looks up a prefix (atom:, etc.) in the list of registered
129 * namespaces and returns the full namespace URI if
130 * available. Returns the prefix, unmodified, if it's not
131 * registered.
133 * @return string
135 public static function lookupNamespace($prefix)
137 return isset(self::$_namespaces[$prefix]) ?
138 self::$_namespaces[$prefix] :
139 $prefix;
144 * Add a namespace and prefix to the registered list
146 * Takes a prefix and a full namespace URI and adds them to the
147 * list of registered namespaces for use by
148 * Zend_Feed::lookupNamespace().
150 * @param string $prefix The namespace prefix
151 * @param string $namespaceURI The full namespace URI
152 * @return void
154 public static function registerNamespace($prefix, $namespaceURI)
156 self::$_namespaces[$prefix] = $namespaceURI;
161 * Imports a feed located at $uri.
163 * @param string $uri
164 * @throws Zend_Feed_Exception
165 * @return Zend_Feed_Abstract
167 public static function import($uri)
169 $client = self::getHttpClient();
170 $client->setUri($uri);
171 $response = $client->request('GET');
172 if ($response->getStatus() !== 200) {
174 * @see Zend_Feed_Exception
176 require_once 'Zend/Feed/Exception.php';
177 throw new Zend_Feed_Exception('Feed failed to load, got response code ' . $response->getStatus());
179 $feed = $response->getBody();
180 return self::importString($feed);
185 * Imports a feed represented by $string.
187 * @param string $string
188 * @throws Zend_Feed_Exception
189 * @return Zend_Feed_Abstract
191 public static function importString($string)
193 // Load the feed as an XML DOMDocument object
194 @ini_set('track_errors', 1);
195 $doc = new DOMDocument;
196 $status = @$doc->loadXML($string);
197 @ini_restore('track_errors');
199 if (!$status) {
200 // prevent the class to generate an undefined variable notice (ZF-2590)
201 if (!isset($php_errormsg)) {
202 if (function_exists('xdebug_is_enabled')) {
203 $php_errormsg = '(error message not available, when XDebug is running)';
204 } else {
205 $php_errormsg = '(error message not available)';
210 * @see Zend_Feed_Exception
212 require_once 'Zend/Feed/Exception.php';
213 throw new Zend_Feed_Exception("DOMDocument cannot parse XML: $php_errormsg");
216 // Try to find the base feed element or a single <entry> of an Atom feed
217 if ($doc->getElementsByTagName('feed')->item(0) ||
218 $doc->getElementsByTagName('entry')->item(0)) {
220 * @see Zend_Feed_Atom
222 require_once 'Zend/Feed/Atom.php';
223 // return a newly created Zend_Feed_Atom object
224 return new Zend_Feed_Atom(null, $string);
227 // Try to find the base feed element of an RSS feed
228 if ($doc->getElementsByTagName('channel')->item(0)) {
230 * @see Zend_Feed_Rss
232 require_once 'Zend/Feed/Rss.php';
233 // return a newly created Zend_Feed_Rss object
234 return new Zend_Feed_Rss(null, $string);
237 // $string does not appear to be a valid feed of the supported types
239 * @see Zend_Feed_Exception
241 require_once 'Zend/Feed/Exception.php';
242 throw new Zend_Feed_Exception('Invalid or unsupported feed format');
247 * Imports a feed from a file located at $filename.
249 * @param string $filename
250 * @throws Zend_Feed_Exception
251 * @return Zend_Feed_Abstract
253 public static function importFile($filename)
255 @ini_set('track_errors', 1);
256 $feed = @file_get_contents($filename);
257 @ini_restore('track_errors');
258 if ($feed === false) {
260 * @see Zend_Feed_Exception
262 require_once 'Zend/Feed/Exception.php';
263 throw new Zend_Feed_Exception("File could not be loaded: $php_errormsg");
265 return self::importString($feed);
270 * Attempts to find feeds at $uri referenced by <link ... /> tags. Returns an
271 * array of the feeds referenced at $uri.
273 * @todo Allow findFeeds() to follow one, but only one, code 302.
275 * @param string $uri
276 * @throws Zend_Feed_Exception
277 * @return array
279 public static function findFeeds($uri)
281 // Get the HTTP response from $uri and save the contents
282 $client = self::getHttpClient();
283 $client->setUri($uri);
284 $response = $client->request();
285 if ($response->getStatus() !== 200) {
287 * @see Zend_Feed_Exception
289 require_once 'Zend/Feed/Exception.php';
290 throw new Zend_Feed_Exception("Failed to access $uri, got response code " . $response->getStatus());
292 $contents = $response->getBody();
294 // Parse the contents for appropriate <link ... /> tags
295 @ini_set('track_errors', 1);
296 $pattern = '~(<link[^>]+)/?>~i';
297 $result = @preg_match_all($pattern, $contents, $matches);
298 @ini_restore('track_errors');
299 if ($result === false) {
301 * @see Zend_Feed_Exception
303 require_once 'Zend/Feed/Exception.php';
304 throw new Zend_Feed_Exception("Internal error: $php_errormsg");
307 // Try to fetch a feed for each link tag that appears to refer to a feed
308 $feeds = array();
309 if (isset($matches[1]) && count($matches[1]) > 0) {
310 foreach ($matches[1] as $link) {
311 // force string to be an utf-8 one
312 if (!mb_check_encoding($link, 'UTF-8')) {
313 $link = mb_convert_encoding($link, 'UTF-8');
315 $xml = @simplexml_load_string(rtrim($link, ' /') . ' />');
316 if ($xml === false) {
317 continue;
319 $attributes = $xml->attributes();
320 if (!isset($attributes['rel']) || !@preg_match('~^(?:alternate|service\.feed)~i', $attributes['rel'])) {
321 continue;
323 if (!isset($attributes['type']) ||
324 !@preg_match('~^application/(?:atom|rss|rdf)\+xml~', $attributes['type'])) {
325 continue;
327 if (!isset($attributes['href'])) {
328 continue;
330 try {
331 // checks if we need to canonize the given uri
332 try {
333 $uri = Zend_Uri::factory((string) $attributes['href']);
334 } catch (Zend_Uri_Exception $e) {
335 // canonize the uri
336 $path = (string) $attributes['href'];
337 $query = $fragment = '';
338 if (substr($path, 0, 1) != '/') {
339 // add the current root path to this one
340 $path = rtrim($client->getUri()->getPath(), '/') . '/' . $path;
342 if (strpos($path, '?') !== false) {
343 list($path, $query) = explode('?', $path, 2);
345 if (strpos($query, '#') !== false) {
346 list($query, $fragment) = explode('#', $query, 2);
348 $uri = Zend_Uri::factory($client->getUri(true));
349 $uri->setPath($path);
350 $uri->setQuery($query);
351 $uri->setFragment($fragment);
354 $feed = self::import($uri);
355 } catch (Exception $e) {
356 continue;
358 $feeds[] = $feed;
362 // Return the fetched feeds
363 return $feeds;
367 * Construct a new Zend_Feed_Abstract object from a custom array
369 * @param array $data
370 * @param string $format (rss|atom) the requested output format
371 * @return Zend_Feed_Abstract
373 public static function importArray(array $data, $format = 'atom')
375 $obj = 'Zend_Feed_' . ucfirst(strtolower($format));
376 if (!class_exists($obj)) {
377 require_once 'Zend/Loader.php';
378 Zend_Loader::loadClass($obj);
382 * @see Zend_Feed_Builder
384 require_once 'Zend/Feed/Builder.php';
385 return new $obj(null, null, new Zend_Feed_Builder($data));
389 * Construct a new Zend_Feed_Abstract object from a Zend_Feed_Builder_Interface data source
391 * @param Zend_Feed_Builder_Interface $builder this object will be used to extract the data of the feed
392 * @param string $format (rss|atom) the requested output format
393 * @return Zend_Feed_Abstract
395 public static function importBuilder(Zend_Feed_Builder_Interface $builder, $format = 'atom')
397 $obj = 'Zend_Feed_' . ucfirst(strtolower($format));
398 if (!class_exists($obj)) {
399 require_once 'Zend/Loader.php';
400 Zend_Loader::loadClass($obj);
402 return new $obj(null, null, $builder);