diff --git a/application/modules/opac/controllers/AbonneController.php b/application/modules/opac/controllers/AbonneController.php index 57fc24cd93cfc2adbd7cef11c6baecb4eb9c05e1..2e40a64aa1bf04d2568807d84cfa29922f8a27b5 100644 --- a/application/modules/opac/controllers/AbonneController.php +++ b/application/modules/opac/controllers/AbonneController.php @@ -26,11 +26,11 @@ class AbonneController extends ZendAfi_Controller_Action { public function init() { parent::init(); - if ("authenticate" == $this->getRequest()->getActionName()) + if ('authenticate' == $this->getRequest()->getActionName()) return; $this->_user = Class_Users::getLoader()->getIdentity(); - + $this->clearEmprunteurCache(); $this->view->getHelper('PageContext')->setContextHelper('Abonne_Resume', [$this->_user]); @@ -902,7 +902,7 @@ class AbonneController extends ZendAfi_Controller_Action { } - public function suggestionAchatOkAction() { } + public function suggestionAchatOkAction() {} public function webkioskReservationAction() { @@ -916,8 +916,6 @@ class AbonneController extends ZendAfi_Controller_Action { } - - public function getPaniersJsonAction() { $this->_helper->viewRenderer->setNoRender(); @@ -926,10 +924,30 @@ class AbonneController extends ZendAfi_Controller_Action { if ($this->_user->canAccessBackend()) $data[] = (new Class_Catalogue())->getDomainesJson(['removeCheckbox' => true]); $JSON = json_encode($data); - $this->getResponse()->setHeader('Content-Type', 'application/json; charset=utf-8'); $this->getResponse()->setBody($JSON); } + + + public function loanExportAction() { + $this->_helper->viewRenderer->setNoRender(); + + $datas = []; + foreach($this->_user->getEmprunts() as $emprunt) { + if (!$exemplaire = $emprunt->getExemplaireOPAC()) + continue; + + $datas[] = $exemplaire->toUnimarcIso2709(); + } + + $response = $this->_response; + $response->clearAllHeaders(); + $filename = 'prets_' . $this->_user->getId() . '-' . uniqid() . '.txt'; + + $response->setHeader('Content-Type', 'application/octet-stream; name="' . $filename . '"', true); + $response->setHeader('Content-Disposition', 'attachment; filename="'.$filename.'"', true); + $response->setBody(implode('', $datas)); + } } ?> \ No newline at end of file diff --git a/application/modules/opac/views/scripts/abonne/prets.phtml b/application/modules/opac/views/scripts/abonne/prets.phtml index 8a8f689f6bdbe7bb0a9db01edd98389055949f9e..060b43e0d2791378aacaa515559486252c350d42 100644 --- a/application/modules/opac/views/scripts/abonne/prets.phtml +++ b/application/modules/opac/views/scripts/abonne/prets.phtml @@ -1,49 +1,60 @@ -<?php $this->openBoite("Prêts en cours"); -echo '<div class="abonneTitre">'.$this->fiche["nom_aff"].'</div>'; - -if($this->fiche["message"]) echo '<p class="error">'.$this->fiche["message"].'</p>'; -if($this->fiche["erreur"]) echo '<p class="error">' . $this->fiche["erreur"] . '</p>'; +<?php $this->openBoite('Prêts en cours');?> +<div class="abonneTitre"><?php echo $this->fiche['nom_aff'];?></div> +<?php +// messages +foreach (['message', 'error'] as $type) + if (isset($this->fiche[$type]) && $this->fiche[$type]) + echo '<p class="error">' . $this->fiche[$type] . '</p>'; +?> +<?php if (isset($this->fiche['fiche']) + && !empty($this->fiche['fiche']->getEmprunts())) { + echo $this->abonne_LoanExport(); +} ?> <table width="100%" class="tablesorter"> <thead> <tr> - <th style="text-align:left; white-space:nowrap"><?php echo $this->_('n°') ?></th> - <th style="text-align:left"><?php echo $this->_('Titre') ?></th> - <th style="text-align:left"><?php echo $this->_('Auteur') ?></th> - <th style="text-align:left"><?php echo $this->_('Bibliothèque') ?></th> - <th style="text-align:center"><?php echo $this->_('Retour prévu') ?></th> - <th style="text-align:center"><?php echo $this->_('Informations') ?></th> + <th style="text-align:left; white-space:nowrap"><?php echo $this->_('n°'); ?></th> + <th style="text-align:left"><?php echo $this->_('Titre'); ?></th> + <th style="text-align:left"><?php echo $this->_('Auteur'); ?></th> + <th style="text-align:left"><?php echo $this->_('Bibliothèque'); ?></th> + <th style="text-align:center"><?php echo $this->_('Retour prévu'); ?></th> + <th style="text-align:center"><?php echo $this->_('Informations'); ?></th> </tr> </thead> <tbody> - <?php - $num=1; - - if(isset($this->fiche["fiche"])) { - foreach($this->fiche["fiche"]->getEmprunts() as $emprunt) { - $class_retard = $emprunt->enRetard() ? 'class="pret_en_retard"' : ''; - echo '<tr '.$class_retard.'>'; - echo '<td width="15px" align="center"><b>'.$num++.'</b></td>'; - echo '<td>'.$this->tagAnchor($this->url(array('controller' => 'recherche', - 'action' => 'viewnotice', - 'id' => $emprunt->getNoticeOPACId(), - 'retour_abonne' => 'prets')), - $emprunt->getTitre()).'</td>'; - echo '<td>'.$emprunt->getAuteur().'</td>'; - echo '<td>'.$emprunt->getBibliotheque().'</td>'; - echo '<td class="date_retour">'.$emprunt->getDateRetour().' '; - if ($emprunt->isRenewable()) - echo $this->tagAnchor($this->url(array('action' => 'prolongerPret', - 'id_pret' => $emprunt->getId())), - $this->_('Prolonger')); - echo '</td>'; - echo '<td>'.$emprunt->getType().'</td>'; - echo '</tr>'; - } - } - ?> + <?php + $num = 1; + if (isset($this->fiche['fiche'])) { + foreach ($this->fiche["fiche"]->getEmprunts() as $emprunt) { + $class_retard = $emprunt->enRetard() ? 'class="pret_en_retard"' : '';?> + <tr <?php echo $class_retard;?>> + <td width="15px" align="center"><b><?php echo $num++;?></b></td> + <td> + <?php + echo $this->tagAnchor( + $this->url(['controller' => 'recherche', + 'action' => 'viewnotice', + 'id' => $emprunt->getNoticeOPACId(), + 'retour_abonne' => 'prets']), + $emprunt->getTitre()); + ?></td> + <td><?php echo $emprunt->getAuteur();?></td> + <td><?php echo $emprunt->getBibliotheque();?></td> + <td class="date_retour"> + <?php echo $emprunt->getDateRetour() . ' ';?> + <?php + if ($emprunt->isRenewable()) + echo $this->tagAnchor($this->url(['action' => 'prolongerPret', + 'id_pret' => $emprunt->getId()]), + $this->_('Prolonger'));?> + </td> + <td><?php echo $emprunt->getType();?></td> + </tr> + <?php } + } ?> </tbody> </table> diff --git a/library/ZendAfi/View/Helper/Abonne/LoanExport.php b/library/ZendAfi/View/Helper/Abonne/LoanExport.php new file mode 100644 index 0000000000000000000000000000000000000000..2376397fa4d07dfe4872d7aa24cb4c1789d3f774 --- /dev/null +++ b/library/ZendAfi/View/Helper/Abonne/LoanExport.php @@ -0,0 +1,35 @@ +<?php +/** + * Copyright (c) 2012-2014, Agence Française Informatique (AFI). All rights reserved. + * + * AFI-OPAC 2.0 is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * AFI-OPAC 2.0 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with AFI-OPAC 2.0; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class ZendAfi_View_Helper_Abonne_LoanExport extends ZendAfi_View_Helper_Abonne_Abstract { + public function abonne_LoanExport() { + if (!$user = Class_Users::getIdentity()) + return ''; + + return $this->view->tagAnchor($this->view->url(['controller' => 'abonne', + 'action' => 'loan-export'], + null, true), + $this->view->_('Export unimarc'), + ['class' => 'loan-export']); + } +} +?> \ No newline at end of file diff --git a/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php b/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php index 655b08c6bf318989cfc265e4929b52cc2e2be823..b643d54380fd39690cf2e29c590bbb4a3cdcd7e4 100644 --- a/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php +++ b/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php @@ -56,11 +56,9 @@ abstract class AbstractAbonneControllerPretsTestCase extends AbstractControllerT - -class AbonneControllerPretsListTwoPretsTest extends AbstractAbonneControllerPretsTestCase { +class AbonneControllerPretsListTwoPretsTestCase extends AbstractAbonneControllerPretsTestCase { public function setUp() { parent::setUp(); - $potter = new Class_WebService_SIGB_Emprunt('12', new Class_WebService_SIGB_Exemplaire(123)); $potter->getExemplaire()->setTitre('Potter'); $potter->parseExtraAttributes(['Dateretourprevue' => '29/10/2022', @@ -70,41 +68,91 @@ class AbonneControllerPretsListTwoPretsTest extends AbstractAbonneControllerPret 'N° de notice' => '1234', 'Type' => 'P1']); + $this->fixture('Class_Exemplaire', + ['id' => 967, + 'id_origine' => 1234, + 'zone995' => serialize([['clef' => 'a', 'valeur' => 'PotterItem']]), + 'notice' => $this->fixture('Class_Notice', + ['id' => 889, + 'titre_principal' => 'Potter', + 'unimarc' => '00577nam0 2200181 450 001001500000010001800015100004100033101000800074200010700082210003000189215001100219461002000230606002900250676000800279700004500287801005600332940000700388frOr1314913787 a9781408812792 a20140320 0103 aEng1 aHarry Potter and the deathly hallowsdHarry Potter et les reliques de la mortfJoanne Kathleen Rowling aLondrescBloomsburyd2010 a831 p. 1tHarry Potterv7 aAnglais (langue)2Rameau a420 1aRowlingbJoanne Kathleenf1965-....4070 aFRbBibliothèque de l\'agglomération de Saint-Omer apm'])]); + $alice = new Class_WebService_SIGB_Emprunt('13', new Class_WebService_SIGB_Exemplaire(456)); $alice->getExemplaire()->setTitre('Alice'); - $alice->parseExtraAttributes(array( - 'Dateretourprevue' => '21/10/2010', - 'Section' => 'Espace jeunesse', - 'Auteur' => 'Lewis Caroll', - 'Bibliotheque' => 'Almont', - 'N° de notice' => '5678')); - - $exemplaire_alice = Class_Exemplaire::newInstanceWithId(918, ['id_origine' => 5678, - 'notice' => Class_Notice::newInstanceWithId(827, - ['titre_principal' => 'Alice'])]); - Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Exemplaire') - ->whenCalled('findFirstBy') - ->with(['id_origine' => 5678]) - ->answers($exemplaire_alice); - + $alice->parseExtraAttributes(['Dateretourprevue' => '21/10/2010', + 'Section' => 'Espace jeunesse', + 'Auteur' => 'Lewis Caroll', + 'Bibliotheque' => 'Almont', + 'N° de notice' => '5678']); + + $this->fixture('Class_Exemplaire', + ['id' => 918, + 'id_origine' => 5678, + 'zone995' => serialize([['clef' => 'a', 'valeur' => 'AliceItem']]), + 'notice' => $this->fixture('Class_Notice', + ['id' => 827, + 'titre_principal' => 'Alice', + 'unimarc' => '01175cam0 22002771 450 001001500000010003700015100004100052101000800093102000700101105001800108106000600126200009300132210002400225211001300249215006400262300002400326307002900350330027300379345001800652461005600670700001800726701003000744801003300774856008300807940000700890frOr0354235228 a978-2-35592-635-8bbr.d7,65 EUR a20140225d2014 | |0fre|0103||||ba afre aFR a 0||y| ar1 aAlice au royaume de TrèfleeCheshire cat Waltzh5fQuinRosegdessin Mamenosuke Fujimaru aPariscKi-oond2014 1a20140227 a1 vol. (164 p.)cillustrations en noir et blancd18 x 13 cm aTraduit du japonais aSens de lecture japonais aPerdue dans la forêt aux portes, Alice tombe nez à nez avec Ace. Devenue malgré elle la confidente du chevalier, elle ne sait comment repousser ses avances. Lorsque le chat du Cheshire, qui a assisté à la scène, intervient, la rencontre tourne à l\'affrontement. b9782355926358 1tAlice au royaume de Trèfle : Cheshire cat Waltzv5 1aQuinRose4070 1aFujimarubMamenosuke4440 aFRbElectrec20140225gAFNOR uhttp://www.electre.com//GetBlob.ashx?Ean=9782355926358,0-1913692&Size=Original aLR'])]); $emprunteur = new Class_WebService_SIGB_Emprunteur('1234', 'Florence'); - $emprunteur->empruntsAddAll(array($potter, $alice)); + $emprunteur->empruntsAddAll([$potter, $alice]); + + $this->florence + ->setFicheSigb(['type_comm' => 2, //OPSYS + 'fiche' => $emprunteur, + 'message' => '', + 'erreur' => '', + 'nom_aff' => 'FloFlo']) + ->setPseudo('FloFlo'); + } +} + + +class AbonneControllerPretsExportTwoPretsTest extends AbonneControllerPretsListTwoPretsTestCase { + public function setUp() { + parent::setUp(); + $this->dispatch('/opac/abonne/loan-export'); + } + + + /** @test */ + public function controllerAndActionShouldBeAbonnePrets() { + $this->assertController('abonne'); + $this->assertAction('loan-export'); + } + + + /** @test */ + public function responseBodyShouldBeAttachment() { + $this->assertHeaderContains('Content-Disposition', 'attachment'); + } + + + /** @test */ + public function responseFileNameShouldContainsPrets() { + $this->assertHeaderContains('Content-Disposition', 'filename="prets_'); + $this->assertHeaderContains('Content-Type', 'name="prets_'); + } + + + /** @test */ + public function bodyShouldContainsUnimarcs() { + $this->assertSame('01200nam0 22002891 450 001001400000010003700014100004100051101000800092102000700100105001800107106000600125200009300131210002400224211001300248215006400261300002400325307002900349330027300378345001800651461005600669700001800725701003000743801003300773856008300806940000700889995001400896frOr0354235228 a978-2-35592-635-8bbr.d7,65 EUR a20140225d2014 | |0fre|0103||||ba afre aFR a 0||y| ar1 aAlice au royaume de TrÁefleeCheshire cat Waltzh5fQuinRosegdessin Mamenosuke Fujimaru aPariscKi-oond2014 1a20140227 a1 vol. (164 p.)cillustrations en noir et blancd18 x 13 cm aTraduit du japonais aSens de lecture japonais aPerdue dans la forÃet aux portes, Alice tombe nez Áa nez avec Ace. Devenue malgrÂe elle la confidente du chevalier, elle ne sait comment repousser ses avances. Lorsque le chat du Cheshire, qui a assistÂe Áa la scÁene, intervient, la rencontre tourne Áa l\'affrontement. b9782355926358 1tAlice au royaume de TrÁefle : Cheshire cat Waltzv5 1aQuinRose4070 1aFujimarubMamenosuke4440 aFRbElectrec20140225gAFNOR uhttp://www.electre.com//GetBlob.ashx?Ean=9782355926358,0-1913692&Size=Original aLR 1aAliceItem00603nam0 22001931 450 001001400000010001800014100004100032101000800073200010700081210003000188215001100218461002000229606002900249676000800278700004500286801005600331940000700387995001500394frOr1314913787 a9781408812792 a20140320 0103 aEng1 aHarry Potter and the deathly hallowsdHarry Potter et les reliques de la mortfJoanne Kathleen Rowling aLondrescBloomsburyd2010 a831 p. 1tHarry Potterv7 aAnglais (langue)2Rameau a420 1aRowlingbJoanne Kathleenf1965-....4070 aFRbBibliothÁeque de l\'agglomÂeration de Saint-Omer apm 1aPotterItem', + $this->_response->getBody()); + } +} - $fiche_sigb = array('type_comm' => 2, //OPSYS - 'fiche' => $emprunteur, - 'message' => '', - 'erreur' => '', - 'nom_aff' => 'FloFlo'); - $this->florence->setFicheSigb($fiche_sigb) - ->setPseudo('FloFlo'); +class AbonneControllerPretsListTwoPretsTest extends AbonneControllerPretsListTwoPretsTestCase { + public function setUp() { + parent::setUp(); $this->dispatch('/opac/abonne/prets'); } - public function testPageIsRendered() { + /** @test */ + public function controllerAndActionShouldBeAbonnePrets() { $this->assertController('abonne'); $this->assertAction('prets'); } @@ -116,8 +164,16 @@ class AbonneControllerPretsListTwoPretsTest extends AbstractAbonneControllerPret } - public function testNomAffiche() { - $this->assertQueryContentContains("div.abonneTitre", 'FloFlo'); + /** @test */ + public function userNameShouldBePresent() { + $this->assertQueryContentContains('div.abonneTitre', 'FloFlo'); + } + + + /** @test */ + public function loanExportLinkShouldBePresent() { + $this->assertXPathContentContains('//a[contains(@href, "/abonne/loan-export")]', + 'Export unimarc'); } @@ -134,49 +190,70 @@ class AbonneControllerPretsListTwoPretsTest extends AbstractAbonneControllerPret $this->assertXPathContentContains('//script', '$(".tablesorter").tablesorter()'); } - public function testViewTitreAlice() { + + /** @test */ + public function aliceLoanShouldBePresent() { $this->assertXPathContentContains("//tbody/tr[1][@class=\"pret_en_retard\"]//td//a[contains(@href, '/recherche/viewnotice/id/827/retour_abonne/prets')]", 'Alice'); } - public function testViewBibAliceIsAlmont() { + + /** @test */ + public function aliceLibraryShouldBeAlmont() { $this->assertXPathContentContains("//tbody/tr[1]//td", 'Almont'); } - public function testViewAuteurAliceIsLewisCaroll() { + + /** @test */ + public function aliceAuthorShouldBeLewisCaroll() { $this->assertXPathContentContains("//tbody/tr[1]//td", 'Lewis Caroll'); } - public function testViewDateRetourAliceIsTwentyOneOctober() { + + /** @test */ + public function aliceDueDateShouldBeTwentyOneOctober() { $this->assertXPathContentContains("//tbody/tr[1]//td", '21/10/2010'); } - public function testLinkProlongerForAlice() { + + /** @test */ + public function aliceLoanShouldHaveExtendLink() { $this->assertXPathContentContains("//tbody/tr[1]//td//a[@href='/abonne/prolongerPret/id_pret/13']", 'Prolonger'); } - public function testViewTitrePotter() { + + /** @test */ + public function potterLoanShouldBePresent() { $this->assertXPathContentContains("//tbody/tr[2]//td", 'Potter', $this->_response->getBody()); } - public function testViewBibPotterIsAstrolabe() { + + /** @test */ + public function potterLibraryShouldBeAstrolab() { $this->assertXPathContentContains("//tbody/tr[2]//td", 'Astrolabe'); } - public function testViewAuteurPotterIsJKRolling() { + + /** @test */ + public function potterAuthorShouldBeJKRolling() { $this->assertXPathContentContains("//tbody/tr[2]//td", 'JK Rowling'); } - public function testViewDateRetourPotterIsTwentyNineOctober2022() { + + /** @test */ + public function potterDueDateShouldBeTwentyNineOctober2022() { $this->assertXPathContentContains("//tbody/tr[2][not(@class)]//td", '29/10/2022'); } - public function testLinkProlongerForPotter() { + + /** @test */ + public function potterLoanShouldHaveExtendLink() { $this->assertXPathContentContains("//tbody/tr[2]//td//a[@href='/abonne/prolongerPret/id_pret/12']", 'Prolonger'); } + /** @test **/ public function colonneInformationShouldBeDisplay(){ $this->assertXPathContentContains('//thead//th','Informations'); @@ -187,7 +264,6 @@ class AbonneControllerPretsListTwoPretsTest extends AbstractAbonneControllerPret public function colonneInformationShouldContainsP1(){ $this->assertXPathContentContains('//tbody//td','P1', $this->_response->getBody()); } - }