166 lines
5.2 KiB
PHP
166 lines
5.2 KiB
PHP
<?php
|
|
/**
|
|
* Portions Copyright 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
|
* Copyright 2007-2016 Horde LLC (http://www.horde.org/)
|
|
*
|
|
* @author Chuck Hagenbuch <chuck@horde.org>
|
|
* @license http://www.horde.org/licenses/bsd BSD
|
|
* @category Horde
|
|
* @package Feed
|
|
*/
|
|
|
|
/**
|
|
* @author Chuck Hagenbuch <chuck@horde.org>
|
|
* @license http://www.horde.org/licenses/bsd BSD
|
|
* @category Horde
|
|
* @package Feed
|
|
*/
|
|
class Horde_Feed
|
|
{
|
|
/**
|
|
* Create a Feed object based on a DOMDocument.
|
|
*
|
|
* @param DOMDocument $doc The DOMDocument object to import.
|
|
*
|
|
* @throws Horde_Feed_Exception
|
|
*
|
|
* @return Horde_Feed_Base The feed object imported from $doc
|
|
*/
|
|
public static function create(DOMDocument $doc, $uri = null)
|
|
{
|
|
// Try to find the base feed element or a single <entry> of an
|
|
// Atom feed.
|
|
if ($feed = $doc->getElementsByTagName('feed')->item(0)) {
|
|
// Return an Atom feed.
|
|
return new Horde_Feed_Atom($feed, $uri);
|
|
} elseif ($entry = $doc->getElementsByTagName('entry')->item(0)) {
|
|
// Return an Atom single-entry feed.
|
|
$feeddoc = new DOMDocument($doc->version,
|
|
$doc->actualEncoding);
|
|
$feed = $feeddoc->appendChild($feeddoc->createElement('feed'));
|
|
$feed->appendChild($feeddoc->importNode($entry, true));
|
|
|
|
return new Horde_Feed_Atom($feed, $uri);
|
|
}
|
|
|
|
// Try to find the base feed element of an RSS feed.
|
|
if ($channel = $doc->getElementsByTagName('channel')->item(0)) {
|
|
// Return an RSS feed.
|
|
return new Horde_Feed_Rss($channel, $uri);
|
|
}
|
|
|
|
// Try to find an outline element of an OPML blogroll.
|
|
if ($outline = $doc->getElementsByTagName('outline')->item(0)) {
|
|
// Return a blogroll feed.
|
|
return new Horde_Feed_Blogroll($doc->documentElement, $uri);
|
|
}
|
|
|
|
// $doc does not appear to be a valid feed of the supported
|
|
// types.
|
|
throw new Horde_Feed_Exception('Invalid or unsupported feed format: '
|
|
. substr($doc->saveXML(), 0, 80) . '...');
|
|
}
|
|
|
|
/**
|
|
* Reads a feed represented by $string.
|
|
*
|
|
* @param string $string The XML content of the feed.
|
|
* @param string $uri The feed's URI location, if known.
|
|
*
|
|
* @throws Horde_Feed_Exception
|
|
*
|
|
* @return Horde_Feed_Base
|
|
*/
|
|
public static function read($string, $uri = null)
|
|
{
|
|
// Load the feed as a DOMDocument object.
|
|
libxml_use_internal_errors(true);
|
|
$doc = new DOMDocument;
|
|
$doc->recover = true;
|
|
$loaded = $doc->loadXML($string);
|
|
if (!$loaded) {
|
|
$loaded = $doc->loadHTML($string);
|
|
if (!$loaded) {
|
|
self::_exception('DOMDocument cannot parse XML', libxml_get_last_error());
|
|
}
|
|
}
|
|
|
|
return self::create($doc);
|
|
}
|
|
|
|
/**
|
|
* Read a feed located at $uri
|
|
*
|
|
* @param string $uri The URI to fetch the feed from.
|
|
* @param Horde_Http_Client $httpclient The HTTP client to use.
|
|
*
|
|
* @throws Horde_Feed_Exception
|
|
*
|
|
* @return Horde_Feed_Base
|
|
*/
|
|
public static function readUri($uri, Horde_Http_Client $httpclient = null)
|
|
{
|
|
if (is_null($httpclient)) {
|
|
$httpclient = new Horde_Http_Client();
|
|
}
|
|
|
|
try {
|
|
$response = $httpclient->get($uri);
|
|
} catch (Horde_Http_Exception $e) {
|
|
throw new Horde_Feed_Exception('Error reading feed: ' . $e->getMessage());
|
|
}
|
|
if ($response->code != 200) {
|
|
throw new Horde_Feed_Exception('Unable to read feed, got response code ' . $response->code);
|
|
}
|
|
$feed = $response->getBody();
|
|
return self::read($feed, $uri);
|
|
}
|
|
|
|
/**
|
|
* Read a feed from $filename
|
|
*
|
|
* @param string $filename The location of the feed file on an accessible
|
|
* filesystem or through an available stream wrapper.
|
|
*
|
|
* @throws Horde_Feed_Exception
|
|
*
|
|
* @return Horde_Feed_Base
|
|
*/
|
|
public static function readFile($filename)
|
|
{
|
|
libxml_use_internal_errors(true);
|
|
$doc = new DOMDocument;
|
|
$doc->recover = true;
|
|
$contents = file_get_contents($filename);
|
|
$loaded = $doc->loadXML($contents);
|
|
if (!$loaded) {
|
|
$loaded = $doc->loadHTML($contents);
|
|
if (!$loaded) {
|
|
self::_exception('File could not be read or parsed', libxml_get_last_error());
|
|
}
|
|
}
|
|
|
|
return self::create($doc);
|
|
}
|
|
|
|
/**
|
|
* Builds an exception message from a libXMLError object.
|
|
*
|
|
* @param string $msg An error message.
|
|
* @param libXMLError $error An error object.
|
|
*
|
|
* @throws Horde_Feed_Exception
|
|
*/
|
|
protected static function _exception($msg, $error)
|
|
{
|
|
if ($error) {
|
|
$msg .= ': ' . $error->message;
|
|
if ($error->file) {
|
|
$msg .= sprintf(' in file %s, line %d, column %d',
|
|
$error->file, $error->line, $error->column);
|
|
}
|
|
}
|
|
throw new Horde_Feed_Exception($msg);
|
|
}
|
|
}
|