- split off files from tutorial.txt into lib/*.php
[m6w6/ext-http] / lib / FeedAggregator.php
diff --git a/lib/FeedAggregator.php b/lib/FeedAggregator.php
new file mode 100644 (file)
index 0000000..de2ae0b
--- /dev/null
@@ -0,0 +1,187 @@
+<?php
+
+/**
+ * Simple Feed Aggregator
+ * $Id$
+ * 
+ * @copyright   Michael Wallner, <mike@iworks.at>
+ * @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);
+               }
+       }
+}
+
+?>