From d97b552ac6c980e59aedd888e31ed0da7c8fbfb6 Mon Sep 17 00:00:00 2001
From: Ghislain Loas <ghislo@sandbox.pergame.net>
Date: Tue, 24 Nov 2015 17:03:56 +0100
Subject: [PATCH] dev #30973 add usage table in import-dilicom action

---
 .../admin/controllers/AlbumController.php     |   4 +-
 .../views/scripts/album/import-dilicom.phtml  |  67 ++++++++++-
 library/Class/Album/UsageConstraints.php      |   7 ++
 library/Class/ScriptLoader.php                |   8 +-
 .../View/Helper/Admin/MenuGaucheAdmin.php     |   2 +-
 library/ZendAfi/View/Helper/TagModelTable.php |  47 +++++++-
 .../AlbumControllerDilicomPNBTest.php         | 113 +++++++++++++++---
 .../admin/controllers/AlbumControllerTest.php |  16 ++-
 .../admin/controllers/IndexControllerTest.php |  56 ++++++---
 .../Dilicom/PNBOffersParserTest.php           |  13 +-
 10 files changed, 287 insertions(+), 46 deletions(-)

diff --git a/application/modules/admin/controllers/AlbumController.php b/application/modules/admin/controllers/AlbumController.php
index a8474252231..a6d80b2f984 100644
--- a/application/modules/admin/controllers/AlbumController.php
+++ b/application/modules/admin/controllers/AlbumController.php
@@ -71,12 +71,12 @@ class Admin_AlbumController extends ZendAfi_Controller_Action {
 
 
   public function importDilicomAction() {
-    $this->view->titre = $this->_('Import des offres Dilicom/PNB');
+    $this->view->titre = $this->_('PNB Dilicom');
     $form = $this->_formImportDilicom();
     $this->view->form_import_dilicom = $form;
 
     if (!$this->_request->isPost())
-      return;
+      return $this->view->albums = Class_Album::findAllBy(['type_doc_id' => Class_TypeDoc::DILICOM]);
 
     if ($form->isValid($this->_request->getPost()) && $form->offers->receive()) {
       $xml = file_get_contents($form->offers->getFileName());
diff --git a/application/modules/admin/views/scripts/album/import-dilicom.phtml b/application/modules/admin/views/scripts/album/import-dilicom.phtml
index 58ab1dc7344..105bd2511c0 100644
--- a/application/modules/admin/views/scripts/album/import-dilicom.phtml
+++ b/application/modules/admin/views/scripts/album/import-dilicom.phtml
@@ -1 +1,66 @@
-<?php echo $this->form_import_dilicom; ?>
+<?php
+
+$title = function($model, $attrib) {
+  return $this->tagAnchor($this->url(['module' => 'admin',
+                                      'controller' => 'album',
+                                      'action' => 'edit_album',
+                                      'id' => $model->getId()], null, true),
+                          $model->getTitre());
+};
+
+$quantity_of_loans_done = function($model, $attrib) {
+  if(!$usage_constraints = $model->getUsageConstraints())
+    return;
+  return $usage_constraints->getLoanQuantity() - $usage_constraints->quantityOfLoansRemaining() .
+         ' / ' .
+         $usage_constraints->getLoanQuantity();
+};
+
+$live_quantity_of_loans_done = function($model, $attrib) {
+  if(!$usage_constraints = $model->getUsageConstraints())
+    return;
+
+  return $usage_constraints->getLoanAllowedNumberOfUsers() - $usage_constraints->numberOfSimultaneousLoansRemaning() .
+         ' / ' .
+         $usage_constraints->getLoanAllowedNumberOfUsers();
+};
+
+$loan_duration = function($model, $attrib) {
+  if(!$usage_constraints = $model->getUsageConstraints())
+    return;
+
+  return $usage_constraints->getLoanDuration();
+};
+
+$license_expiration = function($model, $attrib) {
+  if(!$usage_constraints = $model->getUsageConstraints())
+    return;
+
+  return $usage_constraints->getAvailabilityRemainingDaysBeforeEndDate();
+
+};
+
+echo $this->tag('h2', $this->_('Import des offres Dilicom/PNB'));
+echo $this->form_import_dilicom;
+echo $this->tag('h2', $this->_('Utilisation des ressources PNB Dilicom'));
+echo $this->tagModelTable($this->albums,
+                          [$this->_('Titre'),
+                           $this->_('Nombre de prêts'),
+                           $this->_('Nombre de prêts simultanés'),
+                           $this->_('Durée de prêt en jours'),
+                           $this->_('Nombre de jours restant sur la licence')],
+                          ['title',
+                           'quantity_of_loans_done',
+                           'live_quantity_of_loans_done',
+                           'loan_duration',
+                           'license_expiration'],
+                          null,
+                          'pnb_dilicom',
+                          null,
+                          ['title' => $title,
+                           'quantity_of_loans_done' => $quantity_of_loans_done,
+                           'live_quantity_of_loans_done' => $live_quantity_of_loans_done,
+                           'loan_duration' => $loan_duration,
+                           'license_expiration' => $license_expiration],
+                          true);
+?>
diff --git a/library/Class/Album/UsageConstraints.php b/library/Class/Album/UsageConstraints.php
index 743be1838f6..7331e01fb1a 100644
--- a/library/Class/Album/UsageConstraints.php
+++ b/library/Class/Album/UsageConstraints.php
@@ -21,6 +21,8 @@
 
 
 class Class_Album_UsageConstraints extends Storm_Model_Collection_Abstract {
+  use Trait_TimeSource;
+
   public function getLoanConstraint() {
     return ($constraint = $this->detect(function($c) {return $c->isLoanConstraint();}))
       ? $constraint
@@ -75,6 +77,11 @@ class Class_Album_UsageConstraints extends Storm_Model_Collection_Abstract {
   }
 
 
+  public function getAvailabilityRemainingDaysBeforeEndDate() {
+    return (int) floor((strtotime($this->getAvailabilityEndDate()) - $this->getTimeSource()->time()) / (3600 * 24));
+  }
+
+
   public function isAValidOffer() {
     return $this->getAvailabilityConstraint()->isAValidOffer();
   }
diff --git a/library/Class/ScriptLoader.php b/library/Class/ScriptLoader.php
index d7eb99da60d..7fb23260255 100644
--- a/library/Class/ScriptLoader.php
+++ b/library/Class/ScriptLoader.php
@@ -705,9 +705,11 @@ class Class_ScriptLoader {
    */
   public function loadTableSorter() {
     return $this
-      ->addOPACScript('tablesorter/js/jquery.tablesorter.min')
-      ->addStyleSheet(BASE_URL."/public/opac/js/tablesorter/css/theme.default.css")
-      ->addJQueryReady('$(".tablesorter").tablesorter()');
+      ->addOPACScripts(['tablesorter/js/jquery.tablesorter.min',
+                        'tablesorter/addons/pager/jquery.tablesorter.pager.min'])
+      ->addStyleSheets([BASE_URL."/public/opac/js/tablesorter/css/theme.default.css",
+                        BASE_URL."/public/opac/js/tablesorter/addons/pager/jquery.tablesorter.pager.css"])
+      ->addJQueryReady('$(".tablesorter").tablesorter().tablesorterPager({container: $(".model_table_pager")})');
   }
 
 
diff --git a/library/ZendAfi/View/Helper/Admin/MenuGaucheAdmin.php b/library/ZendAfi/View/Helper/Admin/MenuGaucheAdmin.php
index 277f0d9376d..975a38b9dad 100644
--- a/library/ZendAfi/View/Helper/Admin/MenuGaucheAdmin.php
+++ b/library/ZendAfi/View/Helper/Admin/MenuGaucheAdmin.php
@@ -159,7 +159,7 @@ class ZendAfi_View_Helper_Admin_MenuGaucheAdmin extends ZendAfi_View_Helper_Base
                       Class_AdminVar::isBibNumEnabled()
                       && $this->filterAdmin($this->user))
 
-      .$this->addMenu("pnb_16.png",       $this->translate()->_("Import offres Dilicom"), "/admin/album/import-dilicom",
+      .$this->addMenu("pnb_16.png",       $this->translate()->_("PNB Dilicom"), "/admin/album/import-dilicom",
                       Class_AdminVar::isDilicomPNBEnabled()
                       && $this->filterAdmin($this->user))
 
diff --git a/library/ZendAfi/View/Helper/TagModelTable.php b/library/ZendAfi/View/Helper/TagModelTable.php
index 9718d112ea0..3fe2e493cd0 100644
--- a/library/ZendAfi/View/Helper/TagModelTable.php
+++ b/library/ZendAfi/View/Helper/TagModelTable.php
@@ -39,17 +39,56 @@ class ZendAfi_View_Helper_TagModelTable extends Zend_View_Helper_HtmlElement {
 
                             'relations');
   */
-  public function tagModelTable($models, $cols, $attribs, $actions, $id, $group_by = null, $callbacks = []) {
+  public function tagModelTable($models, $cols, $attribs, $actions, $id, $group_by = null, $callbacks = [], $pager = false) {
     Class_ScriptLoader::getInstance()->loadTableSorter();
 
     $this->_hasActions = 0 < count($actions);
     $this->_cols_count = count($attribs) + ($this->_hasActions ? 1 : 0);
 
-    return $this->tag('table',
-                      $this->head($cols)
-                      .$this->tbody($models, $attribs, $actions, $group_by, $callbacks),
+    $html = $this->tag('table',
+                       $this->head($cols)
+                       .$this->tbody($models, $attribs, $actions, $group_by, $callbacks),
                       ['id' => $id,
                        'class' => 'models tablesorter']);
+
+    return $html . $this->_getPager($pager);
+  }
+
+
+  protected function _getPager($pager) {
+    if(!$pager)
+      return '';
+
+    $first = $this->view->tag('span', '|<<' , ['class' => 'first',
+                                               'style' => 'cursor:pointer']);
+
+    $previous = $this->view->tag('span', '<' , ['class' => 'first',
+                                                'style' => 'cursor:pointer']);
+
+    $page_display = $this->tag('input', '', ['class' => 'pagedisplay']);
+
+    $next = $this->view->tag('span', '>' , ['class' => 'next',
+                                            'style' => 'cursor:pointer']);
+
+    $last = $this->view->tag('span', '>>|' , ['class' => 'last',
+                                              'style' => 'cursor:pointer']);
+
+    $select = $this->view->formSelect('pagesize',
+                                      '',
+                                      ['class' => 'pagesize'],
+                                      ['10' => 10,
+                                       '20' => 20,
+                                       '30' => 30]);
+    $html = $first .
+      $previous .
+      $page_display.
+      $next .
+      $last .
+      $select;
+
+    $form = $this->tag('form', $html);
+
+    return $this->tag('div', $form, ['class' => 'pager model_table_pager']);
   }
 
 
diff --git a/tests/application/modules/admin/controllers/AlbumControllerDilicomPNBTest.php b/tests/application/modules/admin/controllers/AlbumControllerDilicomPNBTest.php
index ef8a301933c..cf4aa314072 100644
--- a/tests/application/modules/admin/controllers/AlbumControllerDilicomPNBTest.php
+++ b/tests/application/modules/admin/controllers/AlbumControllerDilicomPNBTest.php
@@ -19,30 +19,72 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
-class AlbumControllerDilicomPNBEditTest extends Admin_AbstractControllerTestCase {
+abstract class Admin_AlbumControllerDilicomPNBTestCase extends Admin_AbstractControllerTestCase {
+
   public function setUp() {
     parent::setUp();
 
     $this->fixture('Class_Album',
                    ['id' => 23,
                     'titre' => 'Being human being',
+                    'type_doc_id' => Class_TypeDoc::DILICOM,
                     'usage_constraints' =>
 
-       [
-        $this->fixture('Class_Album_UsageConstraint',
-                       ['id' => 1,
-                        'usage_type' => Class_Album_UsageConstraint::LOAN_CONSTRAINT,
-                        'serialized_datas' => json_encode([Class_Album_UsageConstraint::DURATION => 45,
-                                                           Class_Album_UsageConstraint::QUANTITY => 30,
-                                                           Class_Album_UsageConstraint::MAX_NB_OF_USERS => 15])]),
-
-        $this->fixture('Class_Album_UsageConstraint',
-                       ['id' => 2,
-                        'usage_type' => Class_Album_UsageConstraint::DEVICE_SHARE_CONSTRAINT,
-                        'serialized_datas' => json_encode([Class_Album_UsageConstraint::QUANTITY => 6])])
-       ]
-       ]);
+                    [
+                     $this->fixture('Class_Album_UsageConstraint',
+                                    ['id' => 1,
+                                     'usage_type' => Class_Album_UsageConstraint::LOAN_CONSTRAINT,
+                                     'serialized_datas' => json_encode([Class_Album_UsageConstraint::DURATION => 45,
+                                                                        Class_Album_UsageConstraint::QUANTITY => 30,
+                                                                        Class_Album_UsageConstraint::MAX_NB_OF_USERS => 15])]),
+
+                     $this->fixture('Class_Album_UsageConstraint',
+                                    ['id' => 2,
+                                     'usage_type' => Class_Album_UsageConstraint::DEVICE_SHARE_CONSTRAINT,
+                                     'serialized_datas' => json_encode([Class_Album_UsageConstraint::QUANTITY => 6])])
+                    ]
+                   ]);
+  }
+}
+
+
+
+class AlbumControllerDilicomPNBImportDilicomTest extends Admin_AlbumControllerDilicomPNBTestCase {
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('/admin/album/import-dilicom', true);
+  }
+
+
+  /** @test */
+  public function beingHumanTitleShouldBeInTalbe() {
+    $this->assertXPathContentContains('//table//tr/td/a[contains(@href, "/edit_album/id/23")]', 'Being human being');
+  }
+
+
+  /** @test */
+  public function nbOfLoansShouldBe30() {
+    $this->assertXPathContentContains('//table//tr/td', '30 / 30');
+  }
+
+
+  /** @test */
+  public function nbOfLiveLoansShouldBe5() {
+    $this->assertXPathContentContains('//table//tr/td', '5 / 5');
+  }
+
 
+  /** @test */
+  public function nbOfRemainingDaysInLicenseShouldBe45() {
+    $this->assertXPathContentContains('//table//tr/td', '45');
+  }
+}
+
+
+
+class AlbumControllerDilicomPNBEditTest extends Admin_AlbumControllerDilicomPNBTestCase {
+  public function setUp() {
+    parent::setUp();
     $this->dispatch('/admin/album/editalbum/id/23', true);
   }
 
@@ -114,4 +156,43 @@ class AlbumControllerDilicomPNBEditPostTest extends Admin_AbstractControllerTest
   }
 }
 
-?>
\ No newline at end of file
+
+
+class AlbumControllerDilicomPNBImportDilicomPaginatorTest extends Admin_AlbumControllerDilicomPNBTestCase {
+  public function setUp() {
+    parent::setUp();
+    $this->generateDilicomAlbums();
+    $this->dispatch('admin/album/import-dilicom', true);
+  }
+
+
+  /** @test */
+  public function contextShouldExpectation() {
+    $this->assertXPathContentContains('//div[@class="pager model_table_pager"]', '1', $this->_response->getBody());
+  }
+
+
+  protected function generateDilicomAlbums() {
+    for($id=50; $id<=75; $id++) {
+     $this->fixture('Class_Album',
+                   ['id' => $id,
+                    'titre' => 'Being human n°' . $id,
+                    'type_doc_id' => Class_TypeDoc::DILICOM,
+                    'usage_constraints' =>
+                    [
+                     $this->fixture('Class_Album_UsageConstraint',
+                                    ['id' => 1000 + $id,
+                                     'usage_type' => Class_Album_UsageConstraint::LOAN_CONSTRAINT,
+                                     'serialized_datas' => json_encode([Class_Album_UsageConstraint::DURATION => 45,
+                                                                        Class_Album_UsageConstraint::QUANTITY => 30,
+                                                                        Class_Album_UsageConstraint::MAX_NB_OF_USERS => 15])]),
+
+                     $this->fixture('Class_Album_UsageConstraint',
+                                    ['id' => 100 + $id,
+                                     'usage_type' => Class_Album_UsageConstraint::DEVICE_SHARE_CONSTRAINT,
+                                     'serialized_datas' => json_encode([Class_Album_UsageConstraint::QUANTITY => 6])])
+                    ]
+                   ]);
+    }
+  }
+}
\ No newline at end of file
diff --git a/tests/application/modules/admin/controllers/AlbumControllerTest.php b/tests/application/modules/admin/controllers/AlbumControllerTest.php
index f9d229f9044..0643ba8b4af 100644
--- a/tests/application/modules/admin/controllers/AlbumControllerTest.php
+++ b/tests/application/modules/admin/controllers/AlbumControllerTest.php
@@ -2638,8 +2638,20 @@ class Admin_AlbumControllerImportDilicomTest extends Admin_AlbumControllerTestCa
 
 
   /** @test */
-  public function titleShouldBeImportOffresPNB() {
-    $this->assertXPathContentContains('//h1', 'Import des offres Dilicom/PNB');
+  public function titleShouldBeImportPnbDilicom() {
+    $this->assertXPathContentContains('//h1', 'PNB Dilicom');
+  }
+
+
+  /** @test */
+  public function importOffresPnbDilicomShouldBePresent() {
+    $this->assertXPathContentContains('//h2', 'Import des offres Dilicom/PNB');
+  }
+
+
+  /** @test */
+  public function usedRessourcesShouldBePresent() {
+    $this->assertXPathContentContains('//h2', 'Utilisation des ressources PNB Dilicom');
   }
 
 
diff --git a/tests/application/modules/admin/controllers/IndexControllerTest.php b/tests/application/modules/admin/controllers/IndexControllerTest.php
index 652d3ed1fe7..92ad891ff35 100644
--- a/tests/application/modules/admin/controllers/IndexControllerTest.php
+++ b/tests/application/modules/admin/controllers/IndexControllerTest.php
@@ -18,10 +18,20 @@
  * along with BOKEH; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
+
 require_once 'AdminAbstractControllerTestCase.php';
 
+abstract class Admin_IndexControllerTestCase extends Admin_AbstractControllerTestCase {
+  protected
+    $_storm_default_to_volatile = true,
+    $_cms_menu_path = '//div[@class="menuGaucheAdmin"][.//td[text()="Gestionnaire de contenu"]]',
+    $_bibnum_menu_path = '//div[@class="menuGaucheAdmin"][.//td[text()="Bibliothèque numérique"]]';
+}
+
+
+
+class Admin_IndexControllerTest extends Admin_IndexControllerTestCase {
 
-class IndexControllerIndexTest extends Admin_AbstractControllerTestCase {
   public function setUp() {
     parent::setUp();
     $this->fixture('Class_AdminVar',
@@ -51,6 +61,7 @@ class IndexControllerIndexTest extends Admin_AbstractControllerTestCase {
     $this->assertXPathContentContains('//div/b', 'http://bokeh-library-portal.org');
   }
 
+
   /** @test */
   public function channelAccessShouldPresent() {
     $this->assertXPathContentContains('//div[@class="modules"]/h2', 'Salle de discussion #Bokeh :');
@@ -83,17 +94,7 @@ class IndexControllerIndexTest extends Admin_AbstractControllerTestCase {
 
 
 
-abstract class IndexControllerIndexSitothequeTestCase extends Admin_AbstractControllerTestCase {
-  protected
-    $_storm_default_to_volatile = true,
-    $_cms_menu_path = '//div[@class="menuGaucheAdmin"][.//td[text()="Gestionnaire de contenu"]]',
-    $_bibnum_menu_path = '//div[@class="menuGaucheAdmin"][.//td[text()="Bibliothèque numérique"]]';
-
-}
-
-
-
-class IndexControllerIndexDefaultSitothequeTest extends IndexControllerIndexSitothequeTestCase {
+class Admin_IndexControllerSitothequeTest extends Admin_IndexControllerTestCase {
   public function setUp() {
     parent::setUp();
     $this->dispatch('/admin/index/index');
@@ -115,7 +116,7 @@ class IndexControllerIndexDefaultSitothequeTest extends IndexControllerIndexSito
 
 
 
-class IndexControllerIndexSitothequeInAlbumsTest extends IndexControllerIndexSitothequeTestCase {
+class Admin_IndexControllerSitothequeInAlbumsTest extends Admin_IndexControllerTestCase {
   public function setUp() {
     parent::setUp();
     $this->fixture('Class_AdminVar', ['id' => 'BIBNUM', 'valeur' => '1']);
@@ -138,7 +139,7 @@ class IndexControllerIndexSitothequeInAlbumsTest extends IndexControllerIndexSit
 
 
 
-class IndexControllerHeartBeatTest extends Admin_AbstractControllerTestCase {
+class Admin_IndexControllerHeartBeatTest extends Admin_IndexControllerTestCase {
   /** @test */
   public function adminPageShouldContainsHeartbeatScript() {
     $this->dispatch('/admin/index/index', true);
@@ -155,7 +156,7 @@ class IndexControllerHeartBeatTest extends Admin_AbstractControllerTestCase {
 
 
 
-class IndexControllerClearCacheActionTest extends Admin_AbstractControllerTestCase {
+class Admin_IndexControllerClearCacheActionTest extends Admin_IndexControllerTestCase {
   public function setUp() {
     parent::setUp();
     Storm_Cache::beVolatile();
@@ -168,3 +169,28 @@ class IndexControllerClearCacheActionTest extends Admin_AbstractControllerTestCa
     $this->assertRedirectTo('/admin/index/adminvar');
   }
 }
+
+
+
+class Admin_IndexControllerDilicomTest extends Admin_IndexControllerTestCase {
+  public function setUp() {
+    parent::setUp();
+
+    $this->fixture('Class_AdminVar',
+                   ['id' => 'DILICOM_PNB_GLN_CONTRACTOR',
+                    'clef' => 'DILICOM_PNB_GLN_CONTRACTOR',
+                    'valeur' => 1]);
+
+    $this->fixture('Class_AdminVar',
+                   ['id' => 'DILICOM_PNB_SERVER_URL',
+                    'clef' => 'DILICOM_PNB_SERVER_URL',
+                    'valeur' => 1]);
+
+    $this->dispatch('/admin/index/index', true);
+  }
+
+/** @test */
+  public function PnbDilicomnShouldBePresent() {
+     $this->assertXPathContentContains($this->_bibnum_menu_path . '//a', 'PNB Dilicom');
+  }
+}
\ No newline at end of file
diff --git a/tests/library/Class/WebService/Dilicom/PNBOffersParserTest.php b/tests/library/Class/WebService/Dilicom/PNBOffersParserTest.php
index fae8ec30035..a04e9f55d22 100644
--- a/tests/library/Class/WebService/Dilicom/PNBOffersParserTest.php
+++ b/tests/library/Class/WebService/Dilicom/PNBOffersParserTest.php
@@ -48,7 +48,7 @@ abstract class DilicomPNBOfferParserTestCase extends Storm_Test_ModelTestCase {
 class DilicomPNBOfferParserTest extends DilicomPNBOfferParserTestCase {
   public function setUp() {
     parent::setUp();
-
+    Class_Album_UsageConstraints::setTimeSource(new TimeSourceForTest('2015-11-24 09:00:00'));
     $this->_books = Class_WebService_BibNumerique_Dilicom_PNBOffersFile::booksFromXML($this->_xml);
   }
 
@@ -166,7 +166,7 @@ class DilicomPNBOfferParserTest extends DilicomPNBOfferParserTestCase {
   }
 
 
-    /**
+   /**
    * @depends firstAlbumShouldBePlusJamaisSansElle
    * @test
    */
@@ -176,6 +176,15 @@ class DilicomPNBOfferParserTest extends DilicomPNBOfferParserTestCase {
   }
 
 
+   /**
+   * @depends firstAlbumShouldBePlusJamaisSansElle
+   * @test
+   */
+  public function albumLicenseShouldBeAvailableFor1254Days($album) {
+    $this->assertEquals(1254, $album->getUsageConstraints()->getAvailabilityRemainingDaysBeforeEndDate());
+  }
+
+
   /** @test */
   public function secondAlbumShouldBeJournalDunDegonfle() {
     $album = $this->_books[1]->import();
-- 
GitLab