* @license BSD, revised * @package pecl/http * @version $Revision$ */ class FeedAggregator { /** * Cache directory * * @var string */ public $directory; /** * Feeds * * @var array */ protected $feeds = array(); /** * Constructor * * @param string $directory */ public function __construct($directory = 'feeds') { $this->setDirectory($directory); } /** * Set cache directory * * @param string $directory */ public function setDirectory($directory) { $this->directory = $directory; foreach (glob($this->directory .'/*.xml') as $feed) { $this->feeds[basename($feed, '.xml')] = filemtime($feed); } } /** * Strips all special chars * * @param string $url * @return string */ public function url2name($url) { return preg_replace('/[^\w\.-]+/', '_', $url); } /** * Checks if $url is a known feed * * @param string $url * @return bool */ public function hasFeed($url) { return isset($this->feeds[$this->url2name($url)]); } /** * Add an URL as feed * * @param string $url * @return void * @throws Exception */ public function addFeed($url) { $r = $this->setupRequest($url); $r->send(); $this->handleResponse($r); } /** * Add several URLs as feeds * * @param array $urls * @return void * @throws Exception */ public function addFeeds(array $urls) { $pool = new HttpRequestPool; foreach ($urls as $url) { $pool->attach($r = $this->setupRequest($url)); } $pool->send(); foreach ($pool as $request) { $this->handleResponse($request); } } /** * Load a feed (from cache) * * @param string $url * @return string * @throws Exception */ public function getFeed($url) { $this->addFeed($url); return $this->loadFeed($this->url2name($url)); } /** * Load several feeds (from cache) * * @param array $urls * @return array * @throws Exception */ public function getFeeds(array $urls) { $feeds = array(); $this->addFeeds($urls); foreach ($urls as $url) { $feeds[] = $this->loadFeed($this->url2name($url)); } return $feeds; } protected function saveFeed($file, $contents) { if (file_put_contents($this->directory .'/'. $file .'.xml', $contents)) { $this->feeds[$file] = time(); } else { throw new Exception("Could not save feed contents to $file.xml"); } } protected function loadFeed($file) { if (isset($this->feeds[$file])) { if ($data = file_get_contents($this->directory .'/'. $file .'.xml')) { return $data; } else { throw new Exception("Could not load feed contents from $file.xml"); } } else { throw new Exception("Unknown feed/file $file.xml"); } } protected function setupRequest($url, $escape = true) { $r = new HttpRequest($url); $r->setOptions(array('redirect' => true)); $file = $escape ? $this->url2name($url) : $url; if (isset($this->feeds[$file])) { $r->setOptions(array('lastmodified' => $this->feeds[$file])); } return $r; } protected function handleResponse(HttpRequest $r) { if ($r->getResponseCode() != 304) { if ($r->getResponseCode() != 200) { throw new Exception("Unexpected response code ". $r->getResponseCode()); } if (!strlen($body = $r->getResponseBody())) { throw new Exception("Received empty feed from ". $r->getUrl()); } $this->saveFeed($this->url2name($r->getUrl()), $body); } } } ?>