From 36a74c4937e136fdf11c15bb1b75ef91031e9e69 Mon Sep 17 00:00:00 2001
From: Laurent Laffont <llaffont@afi-sa.fr>
Date: Tue, 13 Nov 2018 14:25:10 +0100
Subject: [PATCH] hotline #81451 rss feed handles cache

---
 .../opac/views/scripts/rss/afficherrss.phtml  | 11 +++-
 library/Class/Rss.php                         | 26 +++++---
 library/ZendAfi/Feed.php                      | 26 +-------
 .../opac/controllers/RssControllerTest.php    | 62 +++++++++++++++----
 4 files changed, 82 insertions(+), 43 deletions(-)

diff --git a/application/modules/opac/views/scripts/rss/afficherrss.phtml b/application/modules/opac/views/scripts/rss/afficherrss.phtml
index dbf2172b561..e8b1c541492 100644
--- a/application/modules/opac/views/scripts/rss/afficherrss.phtml
+++ b/application/modules/opac/views/scripts/rss/afficherrss.phtml
@@ -5,7 +5,16 @@
   </a>
 
   <div class="content">
-    <?php  foreach($this->rss->getFeedItems() as $item) {?>
+    <?php
+    $items = $this->rss->getFeedItems();
+
+    if (!$items) {
+      echo $this->_('Impossible de charger le flux');
+    }
+
+
+    foreach($items as $item)
+    {?>
       <div>
         <h2>
           <?php echo $this->tagAnchor($item->link(),
diff --git a/library/Class/Rss.php b/library/Class/Rss.php
index 1dbdf3dd714..64fa9717fce 100644
--- a/library/Class/Rss.php
+++ b/library/Class/Rss.php
@@ -106,7 +106,7 @@ class RssLoader extends Storm_Model_Loader {
 
 
 class Class_Rss extends Storm_Model_Abstract {
-  use Trait_Indexable, Trait_Translator;
+  use Trait_Indexable, Trait_Translator, Trait_StaticFileSystem;
 
   protected
     $_loader_class = 'RssLoader',
@@ -196,15 +196,27 @@ class Class_Rss extends Storm_Model_Abstract {
    * @return Class_Rss
    */
   public function loadFeedItems() {
-      $this->_feed_items = array();
+    $this->_feed_items = [];
+    $cache_filename = sprintf('%srss%d.xml', PATH_TEMP, $this->getId());
 
-      ZendAfi_Feed::setHttpClient(Class_HttpClientFactory::getInstance()->newHttpClient());
-      $feed = ZendAfi_Feed::import($this->getUrl());
+    try {
+      $feed_xml = (new Class_WebService_Abstract())->httpGet($this->getUrl());
+      $feed = ZendAfi_Feed::importString($feed_xml);
 
-      foreach($feed as $item)
-        $this->_feed_items []= new Class_RssItem($item);
+      $this->getFileSystem()->file_put_contents($cache_filename,
+                                                $feed_xml);
+    } catch (Exception $e) {
+        $feed = [];
+    }
+
+    if (!$feed && ($cached_xml = $this->getFileSystem()->file_get_contents($cache_filename))) {
+      $feed = ZendAfi_Feed::importString($cached_xml);
+    }
+
+    foreach($feed as $item)
+      $this->_feed_items []= new Class_RssItem($item);
 
-      return $this;
+    return $this;
   }
 
 
diff --git a/library/ZendAfi/Feed.php b/library/ZendAfi/Feed.php
index 9259ed4e291..235efeede66 100644
--- a/library/ZendAfi/Feed.php
+++ b/library/ZendAfi/Feed.php
@@ -16,35 +16,15 @@
  *
  * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
  * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 /**
  * Extend Zend_Feed to workaround a bug in Zend_Feed::import()
  * The original Zend_Feed::import() has a problem displaying Smart Quotes
  */
 class ZendAfi_Feed extends Zend_Feed {
-  /**
-   * Imports a feed located at $uri.
-   *
-   * @param  string $uri
-   * @throws Zend_Feed_Exception
-   * @return Zend_Feed_Abstract
-   */
-  public static function import($uri) {
-    $client = self::getHttpClient();
-    $client->setUri($uri);
-    $response = $client->request('GET');
-
-    if ($response->getStatus() !== 200) {
-      /**
-       * @see Zend_Feed_Exception
-       */
-      //require_once 'Zend/Feed/Exception.php';
-      throw new Zend_Feed_Exception('Feed failed to load, got response code '
-                                                      . $response->getStatus());
-    }
-
-    return self::importString(self::escapeIsoChars($response->getBody()));
+  public static function importString($string) {
+    return parent::importString(self::escapeIsoChars($string));
   }
 
 
diff --git a/tests/application/modules/opac/controllers/RssControllerTest.php b/tests/application/modules/opac/controllers/RssControllerTest.php
index 8890fc05a70..9fbe92427a2 100644
--- a/tests/application/modules/opac/controllers/RssControllerTest.php
+++ b/tests/application/modules/opac/controllers/RssControllerTest.php
@@ -18,15 +18,6 @@
  * along with BOKEH; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
-require_once 'AbstractControllerTestCase.php';
-
-class MockZendHttpClient extends Zend_Http_Client {
-  public function request($method = null) {
-    return new Zend_Http_Response(200, [], RssFixtures::lemondeRSS());
-  }
-}
-
-
 abstract class RssControllerTestCase extends AbstractControllerTestCase {
   protected $_storm_default_to_volatile = true;
 
@@ -42,9 +33,20 @@ abstract class RssControllerTestCase extends AbstractControllerTestCase {
                     'url' => 'http://rss.lemonde.fr/c/205/f/3050/index.rss',
                     'date_maj' => '2010-04-01 10:47:58']);
 
-    Class_HttpClientFactory::setInstance($this->mock()
-                                         ->whenCalled('newHttpClient')
-                                         ->answers(new MockZendHttpClient()));
+    Class_WebService_Abstract::setHttpClient($this
+                                             ->mock()
+                                             ->whenCalled('open_url')
+                                             ->with('http://rss.lemonde.fr/c/205/f/3050/index.rss')
+                                             ->answers(RssFixtures::lemondeRSS())
+                                             ->beStrict());
+
+    Class_Rss::setFileSystem($this->mock()
+                             ->whenCalled('file_get_contents')
+                             ->with(PATH_TEMP . 'rss15.xml')
+                             ->answers(false)
+
+                             ->whenCalled('file_put_contents')
+                             ->answers(12345));
   }
 }
 
@@ -70,17 +72,53 @@ class RssControllerAfficherRssTest extends RssControllerTestCase {
     $this->assertXPathContentContains('//h2/a',
                                       utf8_encode('Blog - Délinquance des mineurs : le septième rapport en sept ans'));
   }
+
+
+  /** @test */
+  public function cacheRSSShouldBeCreated() {
+    $this->assertEquals([PATH_TEMP . 'rss15.xml', RssFixtures::lemondeRSS()],
+                        Class_Rss::getFileSystem()->getAttributesForLastCallOn('file_put_contents'));
+  }
 }
 
 
 
 
 class RssControllerAfficherRssErrorsTest extends RssControllerTestCase {
+  public function setUp() {
+    parent::setUp();
+    Class_WebService_Abstract::setHttpClient($this
+                                             ->mock()
+                                             ->whenCalled('open_url')
+                                             ->with('http://rss.lemonde.fr/c/205/f/3050/index.rss')
+                                             ->answers('a plus')
+                                             ->beStrict());
+
+  }
+
+
   /** @test */
   public function withInexistingRssShouldAnswerEmptyResponse() {
     $this->dispatch('rss/afficherrss/id_rss/666');
     $this->assertEquals('', $this->_response->getBody());
+  }
+
+
+  /** @test */
+  public function withoutCacheShouldDisplayCouldNotGetFeed() {
+    $this->dispatch('rss/afficherrss/id_rss/15');
+    $this->assertXPathContentContains('//div', 'Impossible de charger le flux', $this->_response->getBody());
+  }
 
+
+  /** @test */
+  public function withCacheShouldDisplayCacheContent() {
+    Class_Rss::getFileSystem()->whenCalled('file_get_contents')
+                              ->with(PATH_TEMP . 'rss15.xml')
+                              ->answers(RssFixtures::lemondeRSS());
+    $this->dispatch('rss/afficherrss/id_rss/15');
+    $this->assertXPathContentContains('//h2/a',
+                                      utf8_encode('Blog - Délinquance des mineurs : le septième rapport en sept ans'));
   }
 }
 
-- 
GitLab