00001 <?php
00002
00035 class Zend_Feed
00036 {
00037
00043 protected static $_httpClient = null;
00044
00050 protected static $_httpMethodOverride = false;
00051
00055 protected static $_namespaces = array(
00056 'opensearch' => 'http://a9.com/-/spec/opensearchrss/1.0/',
00057 'atom' => 'http://www.w3.org/2005/Atom',
00058 'rss' => 'http://blogs.law.harvard.edu/tech/rss',
00059 );
00060
00061
00070 public static function setHttpClient(Zend_Http_Client $httpClient)
00071 {
00072 self::$_httpClient = $httpClient;
00073 }
00074
00075
00081 public static function getHttpClient()
00082 {
00083 if (!self::$_httpClient instanceof Zend_Http_Client) {
00087 require_once 'Zend/Http/Client.php';
00088 self::$_httpClient = new Zend_Http_Client();
00089 }
00090
00091 return self::$_httpClient;
00092 }
00093
00094
00108 public static function setHttpMethodOverride($override = true)
00109 {
00110 self::$_httpMethodOverride = $override;
00111 }
00112
00113
00119 public static function getHttpMethodOverride()
00120 {
00121 return self::$_httpMethodOverride;
00122 }
00123
00124
00135 public static function lookupNamespace($prefix)
00136 {
00137 return isset(self::$_namespaces[$prefix]) ?
00138 self::$_namespaces[$prefix] :
00139 $prefix;
00140 }
00141
00142
00154 public static function registerNamespace($prefix, $namespaceURI)
00155 {
00156 self::$_namespaces[$prefix] = $namespaceURI;
00157 }
00158
00159
00167 public static function import($uri)
00168 {
00169 $client = self::getHttpClient();
00170 $client->setUri($uri);
00171 $response = $client->request('GET');
00172 if ($response->getStatus() !== 200) {
00176 require_once 'Zend/Feed/Exception.php';
00177 throw new Zend_Feed_Exception('Feed failed to load, got response code ' . $response->getStatus());
00178 }
00179 $feed = $response->getBody();
00180 return self::importString($feed);
00181 }
00182
00183
00191 public static function importString($string)
00192 {
00193
00194 $libxml_errflag = libxml_use_internal_errors(true);
00195 $doc = new DOMDocument;
00196 if (trim($string) == '') {
00197 require_once 'Zend/Feed/Exception.php';
00198 throw new Zend_Feed_Exception('Document/string being imported'
00199 . ' is an Empty string or comes from an empty HTTP response');
00200 }
00201 $status = $doc->loadXML($string);
00202 libxml_use_internal_errors($libxml_errflag);
00203
00204
00205 if (!$status) {
00206
00207
00208 $error = libxml_get_last_error();
00209 if ($error && $error->message) {
00210 $errormsg = "DOMDocument cannot parse XML: {$error->message}";
00211 } else {
00212 $errormsg = "DOMDocument cannot parse XML";
00213 }
00214
00215
00219 require_once 'Zend/Feed/Exception.php';
00220 throw new Zend_Feed_Exception($errormsg);
00221 }
00222
00223
00224 if ($doc->getElementsByTagName('feed')->item(0) ||
00225 $doc->getElementsByTagName('entry')->item(0)) {
00229 require_once 'Zend/Feed/Atom.php';
00230
00231 return new Zend_Feed_Atom(null, $string);
00232 }
00233
00234
00235 if ($doc->getElementsByTagName('channel')->item(0)) {
00239 require_once 'Zend/Feed/Rss.php';
00240
00241 return new Zend_Feed_Rss(null, $string);
00242 }
00243
00244
00248 require_once 'Zend/Feed/Exception.php';
00249 throw new Zend_Feed_Exception('Invalid or unsupported feed format');
00250 }
00251
00252
00260 public static function importFile($filename)
00261 {
00262 @ini_set('track_errors', 1);
00263 $feed = @file_get_contents($filename);
00264 @ini_restore('track_errors');
00265 if ($feed === false) {
00269 require_once 'Zend/Feed/Exception.php';
00270 throw new Zend_Feed_Exception("File could not be loaded: $php_errormsg");
00271 }
00272 return self::importString($feed);
00273 }
00274
00275
00286 public static function findFeeds($uri)
00287 {
00288
00289 $client = self::getHttpClient();
00290 $client->setUri($uri);
00291 $response = $client->request();
00292 if ($response->getStatus() !== 200) {
00296 require_once 'Zend/Feed/Exception.php';
00297 throw new Zend_Feed_Exception("Failed to access $uri, got response code " . $response->getStatus());
00298 }
00299 $contents = $response->getBody();
00300
00301
00302 @ini_set('track_errors', 1);
00303 $pattern = '~(<link[^>]+)/?>~i';
00304 $result = @preg_match_all($pattern, $contents, $matches);
00305 @ini_restore('track_errors');
00306 if ($result === false) {
00310 require_once 'Zend/Feed/Exception.php';
00311 throw new Zend_Feed_Exception("Internal error: $php_errormsg");
00312 }
00313
00314
00315 $feeds = array();
00316 if (isset($matches[1]) && count($matches[1]) > 0) {
00317 foreach ($matches[1] as $link) {
00318
00319 if (!mb_check_encoding($link, 'UTF-8')) {
00320 $link = mb_convert_encoding($link, 'UTF-8');
00321 }
00322 $xml = @simplexml_load_string(rtrim($link, ' /') . ' />');
00323 if ($xml === false) {
00324 continue;
00325 }
00326 $attributes = $xml->attributes();
00327 if (!isset($attributes['rel']) || !@preg_match('~^(?:alternate|service\.feed)~i', $attributes['rel'])) {
00328 continue;
00329 }
00330 if (!isset($attributes['type']) ||
00331 !@preg_match('~^application/(?:atom|rss|rdf)\+xml~', $attributes['type'])) {
00332 continue;
00333 }
00334 if (!isset($attributes['href'])) {
00335 continue;
00336 }
00337 try {
00338
00339 try {
00340 $uri = Zend_Uri::factory((string) $attributes['href']);
00341 } catch (Zend_Uri_Exception $e) {
00342
00343 $path = (string) $attributes['href'];
00344 $query = $fragment = '';
00345 if (substr($path, 0, 1) != '/') {
00346
00347 $path = rtrim($client->getUri()->getPath(), '/') . '/' . $path;
00348 }
00349 if (strpos($path, '?') !== false) {
00350 list($path, $query) = explode('?', $path, 2);
00351 }
00352 if (strpos($query, '#') !== false) {
00353 list($query, $fragment) = explode('#', $query, 2);
00354 }
00355 $uri = Zend_Uri::factory($client->getUri(true));
00356 $uri->setPath($path);
00357 $uri->setQuery($query);
00358 $uri->setFragment($fragment);
00359 }
00360
00361 $feed = self::import($uri);
00362 } catch (Exception $e) {
00363 continue;
00364 }
00365 $feeds[$uri->getUri()] = $feed;
00366 }
00367 }
00368
00369
00370 return $feeds;
00371 }
00372
00380 public static function importArray(array $data, $format = 'atom')
00381 {
00382 $obj = 'Zend_Feed_' . ucfirst(strtolower($format));
00383 if (!class_exists($obj)) {
00384 require_once 'Zend/Loader.php';
00385 Zend_Loader::loadClass($obj);
00386 }
00387
00391 require_once 'Zend/Feed/Builder.php';
00392 return new $obj(null, null, new Zend_Feed_Builder($data));
00393 }
00394
00402 public static function importBuilder(Zend_Feed_Builder_Interface $builder, $format = 'atom')
00403 {
00404 $obj = 'Zend_Feed_' . ucfirst(strtolower($format));
00405 if (!class_exists($obj)) {
00406 require_once 'Zend/Loader.php';
00407 Zend_Loader::loadClass($obj);
00408 }
00409 return new $obj(null, null, $builder);
00410 }
00411 }