diff --git a/FEATURES/187054 b/FEATURES/187054 new file mode 100644 index 0000000000000000000000000000000000000000..9e5a25dcd9e8a47dd77069767c8a8047dc6900e1 --- /dev/null +++ b/FEATURES/187054 @@ -0,0 +1,10 @@ + '187054' => + ['Label' => $this->_('Gestion par bibliothèque des codifications genre section et annexe'), + 'Desc' => $this->_('Dans cosmogramme, il est maintenant possible de spécifier par bibliothèque les codifications : section, genre et emplacement.'), + 'Image' => '', + 'Video' => '', + 'Category' => $this->('Cosmogramme'), + 'Right' => function($feature_description, $user) {return true;}, + 'Wiki' => '', + 'Test' => '', + 'Date' => '2023-11-02'], \ No newline at end of file diff --git a/FEATURES/204687 b/FEATURES/204687 new file mode 100644 index 0000000000000000000000000000000000000000..a6698c5d283379a74e7629a68c260cb5851c09c8 --- /dev/null +++ b/FEATURES/204687 @@ -0,0 +1,10 @@ + '204687' => + ['Label' => $this->_('Réservation d\'un doc BDP par un compte dépôt de la BDP : la fenêtre des sites de retrait est proposée'), + 'Desc' => '', + 'Image' => '', + 'Video' => '', + 'Category' => '', + 'Right' => function($feature_description, $user) {return true;}, + 'Wiki' => '', + 'Test' => '', + 'Date' => '2024-07-10'], \ No newline at end of file diff --git a/FEATURES/204690 b/FEATURES/204690 new file mode 100644 index 0000000000000000000000000000000000000000..cda282ea0b2f90c43546ace21cfcdf135fd07c55 --- /dev/null +++ b/FEATURES/204690 @@ -0,0 +1,10 @@ + '204690' => + ['Label' => $this->_('Compte BDP : Badge de prêts en retard'), + 'Desc' => '', + 'Image' => '', + 'Video' => '', + 'Category' => '', + 'Right' => function($feature_description, $user) {return true;}, + 'Wiki' => '', + 'Test' => '', + 'Date' => '2024-07-11'], \ No newline at end of file diff --git a/VERSIONS_WIP/187054 b/VERSIONS_WIP/187054 new file mode 100644 index 0000000000000000000000000000000000000000..f758c79001a83f41e0cd879ff52af846e27fc33b --- /dev/null +++ b/VERSIONS_WIP/187054 @@ -0,0 +1 @@ + - fonctionnalité #187054 : Cosmogramme : Dans cosmogramme, il est maintenant possible de spécifier par bibliothèque les codifications : section, genre et emplacement. \ No newline at end of file diff --git a/VERSIONS_WIP/193099 b/VERSIONS_WIP/193099 new file mode 100644 index 0000000000000000000000000000000000000000..136546b0884dd3a215da8efc6eecf6e2a42de20b --- /dev/null +++ b/VERSIONS_WIP/193099 @@ -0,0 +1 @@ + - fonctionnalité #193099 : Compte lecteur : Il est maintenant possible de réserver un exemplaire via la bibliothèque centrale (BDP). \ No newline at end of file diff --git a/VERSIONS_WIP/196022 b/VERSIONS_WIP/196022 new file mode 100644 index 0000000000000000000000000000000000000000..05df97f1e7c43a6c58bf85fc4d484fd58a2f54e4 --- /dev/null +++ b/VERSIONS_WIP/196022 @@ -0,0 +1 @@ + - fonctionnalité #196022 : Compte lecteur : la création de compte à la première connexion rattache correctement celui-ci à sa bibliohtèque. \ No newline at end of file diff --git a/VERSIONS_WIP/204687 b/VERSIONS_WIP/204687 new file mode 100644 index 0000000000000000000000000000000000000000..ee41fe9209ea6736fc07ac50de4c834dd084fbc6 --- /dev/null +++ b/VERSIONS_WIP/204687 @@ -0,0 +1 @@ + - fonctionnalité #204687 : Réservation d'un doc BDP par un compte dépôt de la BDP : la fenêtre des sites de retrait est proposée \ No newline at end of file diff --git a/VERSIONS_WIP/204690 b/VERSIONS_WIP/204690 new file mode 100644 index 0000000000000000000000000000000000000000..39786e3343d75c0fdd58233661d87792f06ff209 --- /dev/null +++ b/VERSIONS_WIP/204690 @@ -0,0 +1 @@ + - fonctionnalité #204690 : Compte BDP : Badge de prêts en retard \ No newline at end of file diff --git a/application/modules/admin/controllers/CmsController.php b/application/modules/admin/controllers/CmsController.php index 4d0011c237a99c1ab31c0b47393e4fdfecd52624..a423b82412aaec424f99d374070ad4d0df2912c9 100644 --- a/application/modules/admin/controllers/CmsController.php +++ b/application/modules/admin/controllers/CmsController.php @@ -42,6 +42,11 @@ class Admin_CmsController extends ZendAfi_Controller_Action { protected function _renderList() { $bibs = Class_Bib::findAllForCurrentUserAndPortal(); + + $current_library = (Class_Users::isCurrentUserCanAccessAllBibs()) + ? null + : $this->identity->getBib(); + $ids = array_map(fn($model) => $model->getId(), $bibs); $search = $this->_getParam('title_search', ''); diff --git a/application/modules/opac/controllers/AuthController.php b/application/modules/opac/controllers/AuthController.php index 80123f390cc1000c8bef0949d3566039b9259bbe..9cdc439fe2ed707c74d845314280962dd56d5a65 100644 --- a/application/modules/opac/controllers/AuthController.php +++ b/application/modules/opac/controllers/AuthController.php @@ -332,7 +332,7 @@ class AuthController extends ZendAfi_Controller_Action { $strategy->setDefaultUrl($url); $on_fail = function() use($strategy, $referer): void { - $strategy->setRedirectUrl($referer); + $strategy->setRedirectUrl($referer ?? ''); }; if ($target) diff --git a/application/modules/opac/controllers/RechercheController.php b/application/modules/opac/controllers/RechercheController.php index 4ed5978b90cac95de95cd80ff2e8f041f3274855..dd140a66302f77e72ace15818682bab0f2b7a2bb 100644 --- a/application/modules/opac/controllers/RechercheController.php +++ b/application/modules/opac/controllers/RechercheController.php @@ -1,6 +1,6 @@ <?php /** - * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved. + * Copyright (c) 2025, Agence Française Informatique (AFI). All rights reserved. * * BOKEH is free software; you can redistribute it and/or modify * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by @@ -18,21 +18,26 @@ * along with BOKEH; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + + class RechercheController extends ZendAfi_Controller_Action { protected $moteur; protected $preferences; + protected string $_code_annexe = ''; + + public function __call($method_name, $args) { try { parent::__call($method_name, $args); } catch (Exception $e) { $this->_forward('simple', - 'recherche', - 'opac', - array_merge($this->_request->getParams(), - ['q' => urldecode($this->_request->getActionName())])); + 'recherche', + 'opac', + array_merge($this->_request->getParams(), + ['q' => urldecode($this->_request->getActionName())])); } } @@ -64,7 +69,7 @@ class RechercheController extends ZendAfi_Controller_Action parent::preDispatch(); if ('json' === $this->_getParam('format') && 'viewnotice' === $this->_request->getActionName()) - $this->_forward('json-record'); + $this->_forward('json-record'); } public function guideeAction() @@ -72,7 +77,7 @@ class RechercheController extends ZendAfi_Controller_Action $this->_request->setActionName('simple'); $this->_helper->catalogSearch(Class_Template::current() ->getSearchCriteria() - ->updateRubrique('guidee')); + ->updateRubrique('guidee')); } public function indexAction() @@ -98,11 +103,20 @@ class RechercheController extends ZendAfi_Controller_Action $this->_helper->catalogSearch(Class_Template::current()->getSearchCriteria()); } + + protected function _getTitreRechercheViewNotice($criteres_recherche): void + { + if($title = $this->view->search_Title($criteres_recherche, $this->_request, $this)) + $this->view->titreAdd($title); + } + + public function appelmenuAction() { $this->_forward('simple'); } + public function avanceeAction() { $this->view->annexes = Class_CodifAnnexe::getMultiOptions(); @@ -152,8 +166,8 @@ class RechercheController extends ZendAfi_Controller_Action new Class_Notice_NavigationRecherche(Class_Template::current() ->getSearchCriteria() ->setParams($this->_request->getParams()), - $this->moteur, - $notice); + $this->moteur, + $notice); if ($navigation = $this->_getParam('navigation')) { $notice_to_show = ('suivant' === $navigation @@ -167,12 +181,14 @@ class RechercheController extends ZendAfi_Controller_Action if ($this->_getParam('code_rebond', false) || !$this->_getParam('retour_abonne', false) && !$this->_getParam('retour_avis', false)) - $this->view->notice_navigation = $notice_navigation; + $this->view->notice_navigation = $notice_navigation; $current_module = $this->_getParam('current_module'); - $current_module['preferences'] = $this->preferences = $this->extractProfilFromUrl() - ->getCfgModulesPreferences('recherche', 'viewnotice', $notice->getTypeDoc()); + $current_module['preferences'] = + $this->preferences = + $this->extractProfilFromUrl() + ->getCfgModulesPreferences('recherche', 'viewnotice', $notice->getTypeDoc()); $current_module['action2'] = $notice->getTypeDoc(); $this->view->_current_module = $current_module; @@ -184,7 +200,7 @@ class RechercheController extends ZendAfi_Controller_Action $criteres_recherche = Class_Template::current() ->getSearchCriteria() ->setParams($this->_request->getParams(), - $this->preferences); + $this->preferences); $this->view->criteres_recherche = $criteres_recherche; $this->view->display_modifier_vignette_link = Class_Users::isCurrentUserCanAccesBackend() && $notice->isVignetteUpdatableToCacheServer(); @@ -206,46 +222,72 @@ class RechercheController extends ZendAfi_Controller_Action $this->view->url_panier = $this->view->url(['controller' => 'panier', 'action' => 'add-record-ajax', 'id_notice' => $id_notice], - null, - true); + null, + true); $this->_helper->trackEvent('recherche', - 'notice', - ['titre' => $notice->getTitrePrincipal(), - 'auteur' => $notice->getAuteurPrincipal(), - 'editeur' => $notice->getFirstEditeur(), - 'tome' => $notice->getTomeAlpha(), - 'support' => $notice->getTypeDocLabel(), - ], - $notice->getId()); + 'notice', + ['titre' => $notice->getTitrePrincipal(), + 'auteur' => $notice->getAuteurPrincipal(), + 'editeur' => $notice->getFirstEditeur(), + 'tome' => $notice->getTomeAlpha(), + 'support' => $notice->getTypeDocLabel(), + ], + $notice->getId()); $stat = new Class_StatsNotices; $stat->addStatVisu($id_notice); Class_ScriptLoader::getInstance()->loadBabeltheque(); + return null; + } + + + protected function _authorityFromParams() + { + if ((!$authority_id = $this->_getParam('authority_id')) + || (!$thesaurus_id = $this->_getParam('thesaurus_id'))) + return null; + + $items = Class_Exemplaire::findAllBy(['type' => Class_Notice::TYPE_AUTHORITY, + 'id_origine' => $authority_id]); + foreach ($items as $item) + if ($record = $this->_recordWithThesaurusFacet($thesaurus_id, $item)) + return $record; return null; } - public function customizedInputAction() + + protected function _recordWithThesaurusFacet($thesaurus_id, $item) { + if (!$record = $item->getNotice()) + return null; + + return in_array(Class_CodifThesaurus::CODE_FACETTE . $thesaurus_id, $record->getFacetCodes()) + ? $record + : null; + } + + + public function customizedInputAction() { session_write_close(); $this->_helper->getHelper('viewRenderer')->setNoRender(); if ((!$form = Class_SearchForm::find($this->_getParam('form'))) || (!$form = $form->getForm())) - return; + return; if ((!$element = $form->getElement($this->_getParam('element'))) || (!$axe = $element->getAxe($this->_getParam('axe'))) || (!$type = (new Class_CriteresRecherche_AxesParamTypes)->typeFor($axe))) - return; + return; $name = $element->getName() . '_' . $axe['name']; $id = $name . '_' . bin2hex(random_bytes(8)); $element = $form->createElement($type->input(), - $name, - array_merge(['id' => $id], - $type->inputOptions())); + $name, + array_merge(['id' => $id], + $type->inputOptions())); if ($value = $this->_getParam('value')) $element->setValue($value); @@ -265,7 +307,7 @@ class RechercheController extends ZendAfi_Controller_Action $this->_helper->getHelper('viewRenderer')->setNoRender(); $result = $this->_findRecordByKeyOrId((string) $this->_getParam('clef'), - (int) $this->_getParam('id')); + (int) $this->_getParam('id')); ($record = $result->getRecord()) ? $this->_helper->json($record ->acceptVisitor(new Class_Notice_JsonVisitor) @@ -314,10 +356,10 @@ class RechercheController extends ZendAfi_Controller_Action if (!($record = Class_Notice::find((int) $this->_getParam('id_notice')))) return $this->_redirectToIndex(); $this->_redirect($this->view->absoluteUrl($record->fetchUrlLocalVignette())); - return null; } + public function rawThumbnailAction() { $viewRenderer = $this->getHelper('ViewRenderer'); @@ -327,24 +369,24 @@ class RechercheController extends ZendAfi_Controller_Action $this->_response->setHeader('Content-Type', 'image/png'); if (!($record = Class_Notice::find((int) $this->_getParam('id')))) return $this->_redirectToIndex(); + (new Class_WebService_Vignette) ->renderThumbnail($record->getId(), - $record->getTitrePrincipal(), - $record->getTypeDoc()); + $record->getTitrePrincipal(), + $record->getTypeDoc()); return null; } + public function reservationAction() { if (!$this->userConnected()) - return; - if ((!$library = Class_Bib::find((int) $this->_getParam('id_bib'))) - || !$record = Class_Notice::find((int) $this->_getParam('id_notice'))) { - $this->_redirectToIndex(); - return; - } + + if ((!$library = Class_Bib::find((int)$this->_getParam('id_bib'))) + || !$record = Class_Notice::find((int)$this->_getParam('id_notice'))) + return $this->_redirectToIndex(); $form = new ZendAfi_Form_Hold(['action' => $this->view->url(), 'data-backurl' => $this->view->url(['action' => 'viewnotice']), @@ -380,7 +422,7 @@ class RechercheController extends ZendAfi_Controller_Action if ($message = (new Class_Mail) ->setFrom(Class_Mail::getNoReplyMail()) ->sendMail($subject, $message_user . $message, $form->getValue('user_mail'))) - $this->_helper->notify($this->_("Erreur d'envoi du mail : %s", $message), ['class' => 'error']); + $this->_helper->notify($this->_("Erreur d'envoi du mail : %s", $message), ['class' => 'error']); $this->_redirect('opac/recherche/viewnotice/id/' . $record->getId() . '?type_doc=' . $record->getTypeDoc()); @@ -409,14 +451,15 @@ class RechercheController extends ZendAfi_Controller_Action $data = Zend_Controller_Action_HelperBroker::getStaticHelper('Json')->encodeJson($json); $this->_response->setBody($data); - return null; } + public function consultationajaxAction() { if (!$this->userConnected()) return null; + $title = $this->view->_('Consultation sur place'); if (!$exemplaire = Class_Exemplaire::find($this->_getParam('copy_id'))) return $this->renderPopupResult($title, $this->view->_('L\'exemplaire n\'existe pas')); @@ -426,10 +469,9 @@ class RechercheController extends ZendAfi_Controller_Action ->onPlaceConsultationBooking(Class_Users::getIdentity(), $exemplaire, $service_point); $this->renderPopupResult($title, $this->_getConsultationBookingMessage($response)); - - return null; } + public function reservationajaxAction() { $viewRenderer = $this->getHelper('ViewRenderer'); @@ -439,31 +481,26 @@ class RechercheController extends ZendAfi_Controller_Action return null; $id_bib = (int) $this->_getParam('id_bib'); $id_exemplaire = $this->_getParam('copy_id'); - $code_annexe = $this->_getParam('code_annexe', ''); - - if (Class_CosmoVar::isSiteRetraitResaPatronLibrary()) - $code_annexe = $user->getUserIdSite(); if (!$item = Class_Exemplaire::find($id_exemplaire)) return $this->renderPopupResult($this->view->_('Réservation'), - $this->_('Document introuvable')); + $this->_('Document introuvable')); - if (Class_CosmoVar::isSiteRetraitResaItemLibrary()) - $code_annexe = $item->getAnnexe(); + $code_annexe = $this->_getCodeAnnexe($user, $item); if ($item->requiresCalendarHold()) - return $this->_redirect(sprintf('/recherche/reservation-calendar-ajax/id_bib/%s/copy_id/%s/code_annexe/%s', - $id_bib, - $id_exemplaire, - $code_annexe)); - - $ret = Class_CommSigb::getInstance()->reserveItem($item, - $code_annexe ?? ''); - - $this->renderPopupResult($this->view->_('Réservation'), - $this->_getHoldMessage($user, $id_exemplaire, $ret)); - - return null; + return $this->_redirect($this + ->view + ->url(['module' => 'opac', + 'controller' => 'recherche', + 'action' => 'reservation-calendar-ajax', + 'id_bib' => $id_bib, + 'copy_id' => $id_exemplaire, + 'code_annexe' => $code_annexe ?? ''])); + + $ret = Class_CommSigb::getInstance()->reserveItem($item, $code_annexe ?? ''); + return $this->renderPopupResult($this->view->_('Réservation'), + $this->_getHoldMessage($user, $item, $ret)); } public function reservationCalendarAjaxAction() @@ -477,20 +514,20 @@ class RechercheController extends ZendAfi_Controller_Action ->newForm(['id' => 'reservation-calendar']) ->setAction($this->view->url()) ->addElement('dateRangePicker', - 'reservation-date', - ['label' => $this->_('Période de réservation'), - 'start' => ['name' => 'reservedate', - 'allowEmpty' => false, - 'DateFormat' => 'DD/MM/YYYY', - 'validators' => [new Zend_Validate_Date('DD/MM/YYYY')]], - 'end' => ['name' => 'expirationdate', - 'allowEmpty' => false, - 'DateFormat' => 'DD/MM/YYYY', - 'validators' => [new Zend_Validate_Date('DD/MM/YYYY')]], - ]) + 'reservation-date', + ['label' => $this->_('Période de réservation'), + 'start' => ['name' => 'reservedate', + 'allowEmpty' => false, + 'DateFormat' => 'DD/MM/YYYY', + 'validators' => [new Zend_Validate_Date('DD/MM/YYYY')]], + 'end' => ['name' => 'expirationdate', + 'allowEmpty' => false, + 'DateFormat' => 'DD/MM/YYYY', + 'validators' => [new Zend_Validate_Date('DD/MM/YYYY')]], + ]) ->addElement('Submit', $this->_('Valider')) ->addElement('Button', $this->_('Annuler'), - ['onclick' => 'opacDialogClose();return false;']) + ['onclick' => 'opacDialogClose();return false;']) ->addUniqDisplayGroup('hold'); if ($this->_request->isPost() && $form->isValid($this->_request->getPost())) { @@ -499,16 +536,16 @@ class RechercheController extends ZendAfi_Controller_Action $comm_sigb = Class_CommSigb::getInstance(); $comm_sigb->holdCalendar( - $id_exemplaire, - $code_annexe, - $reservedate, - $expirationdate); + $id_exemplaire, + $code_annexe, + $reservedate, + $expirationdate); - if (!$comm_sigb->hasErrors()) + if ( !$comm_sigb->hasErrors()) return $this->renderPopupResult($this->view->_('Réservation'), - $this->_getHoldMessage($this->userConnected(), - $id_exemplaire, - ['erreur' => ''])); + $this->_getHoldMessage($this->_userConnected(), + Class_Exemplaire::find($id_exemplaire), + ['erreur' =>''])); $form ->addErrors($comm_sigb->getErrors()) @@ -519,15 +556,140 @@ class RechercheController extends ZendAfi_Controller_Action $form = $this->view->renderForm($form); return $this->renderPopupResult($this->view->_('Réservation'), - Class_ScriptLoader::getInstance()->html() - . $holds - . $form); + Class_ScriptLoader::getInstance()->html() + . $holds + . $form); } + + protected function _renderHolds($id_exemplaire) { + $item = Class_Exemplaire::find($id_exemplaire); + $holds = Class_CommSigb::getInstance()->holdsForItem($item)['holds'] ?? []; + usort($holds, + fn($a, $b) => strcmp($a->getReserveDate(), $b->getReserveDate())); + + $html = implode('', + array_map(fn($hold) => $this->view->tag('li', + $hold->renderRange()), + $holds)); + + $js_holds = json_encode(array_map( + fn($hold) => [$hold->getReserveDate(), $hold->getExpirationDate()], + $holds)); + + Class_ScriptLoader::getInstance() + ->addAdminScript('jquery_ui_datepicker_i18n/datepicker-fr.js') + ->addJQueryReady(' + Date.prototype.withoutTime = function () { + var d = new Date(this); + d.setHours(0, 0, 0, 0); + return d; + } + $.datepicker.setDefaults($.datepicker.regional["' . ((Zend_Registry::get('locale') == 'en_US') ? '' : 'fr' ). '"]); + $("input").blur(); + $("#holds_view").datepicker( + { + numberOfMonths: 3, + beforeShowDay: function(date) { + var holds = '. $js_holds . '; + var day = date.withoutTime(); + var hold = holds.find( (hold) => { + return (new Date(hold[0]).withoutTime() <= day) && (day <= new Date(hold[1]).withoutTime()); + }); + + if (undefined == hold) + return [false, "day-without-hold"]; + + return [false, "day-with-hold", "' . $this->_("Reservation déjà présente ce jour") . '"]; + }} + );'); + + return '<div id="holds_view"></div><div>' + . $this->view->tag('span', $this->_('Réservations non disponibles : ')) + . $this->view->tag('ul',$html) . '</div>'; + } + + + protected function _getHoldMessage(Class_Users $user, + ?Class_Exemplaire $item, + array $response): string + { + if ($response['erreur'] ?? false) + return $response['erreur']; + + if (isset($response['popup']) && $response['popup']) + return '<iframe src="' . $response['popup'] . '"></iframe>'; + + $content = $this->_('Votre réservation est enregistrée.<br>Nous vous informerons quand le document%s sera disponible', + $this->_getMessageNoticeLabel($item->getId())); + + return ($location_label = $this->_getPickupLocationLabelForUserAndItem($user, $item)) + ? $content . $this->_(' pour être retiré à : %s',$location_label) + : $content; + } + + + protected function _getPickupLocationLabelForUserAndItem(Class_Users $user, Class_Exemplaire $item) : string { + $current_hold = null; + $item_id = $item->getId(); + $current_hold = (new Storm_Collection($user->getReservations())) + ->detect(fn($hold) => ($opac_item = $hold->getExemplaireOPAC()) && ($item_id == $opac_item->getId())); + + return ($current_hold && $location_label = $current_hold->getPickupLocationLabel()) + ? $location_label + : ''; + } + + + protected function _getMessageNoticeLabel($item_id) + { + if (!$item_id + || !($item = Class_Exemplaire::find($item_id)) + || !($notice = $item->getNotice())) + return ''; + + $title = strip_tags($notice->getTitrePrincipal()); + + if (!$notice->getAuteurPrincipal()) + return sprintf(" '%s'", $title); + + return sprintf(" '%s / %s'", + $title, + $notice->getAuteurPrincipal()); + } + + + + protected function _userConnected():?Class_Users { + if (! $user = Class_Users::getIdentity()) + $this->_forwardToLogin($this->view->url(), ''); + + return $user; + } + + + protected function getReservationForm($action = 'reservation-pickup-ajax') + { + return $this->view + ->newForm(['id' => 'pickup', + 'class' => 'zend_form reservation_pickup', + 'action' => $this->view->url(['controller' => 'recherche', + 'action' => $action])]) + ->addElement('Radio', + 'code_annexe', + ['required' => true, + 'allowEmpty' => false, + 'escape' => false]) + + ->addDisplayGroup(['code_annexe'], 'group', ['legend' => 'Site de retrait']); + } + + public function consultationPickupAjaxAction() { if (!$this->userConnected()) return null; + if ($this->_request->isPost()) { return $this->_forward('consultationajax'); } @@ -538,141 +700,106 @@ class RechercheController extends ZendAfi_Controller_Action if (!$exemplaire = Class_Exemplaire::find($this->_getParam('copy_id'))) return $this->renderPopupResult($this->view->_('Lieu de mise à disposition demandé'), $this->view->_('L\'exemplaire n\'existe pas')); $locations = Class_CommSigb::getInstance()->pickupLocation(Class_Users::getIdentity(), $exemplaire); + foreach ($locations as $location) { foreach ($location->getServicePoints() as $service_point) $radio->addMultiOption($service_point->getCode(), $service_point->getLabel()); } - $this->renderPopupResult($this->view->_('Lieu de mise à disposition demandé'), - $this->view->renderForm($form)); - - return null; + return $this->renderPopupResult($this->view->_('Lieu de mise à disposition demandé'), + $this->view->renderForm($form)); } - public function reservationPickupAjaxAction() - { - if (!$this->userConnected()) - return null; - if (($central_library_id = Class_CosmoVar::get('centralized_hold_mode')) - && in_array($central_library_id, [ $this->_getParam('code_annexe'), - $this->_getParam('int_bib'), - ])) { - $this->_forward('reservationajax'); - - return null; - } - - if (!Class_CosmoVar::isSiteRetraitResaChoiceEnabled()) - return $this->_forward('reservationajax'); - $form = $this->getReservationForm(); - $radio = $form->getElement('code_annexe'); - $locations = $this->arePickupLocationsProvidedByComm() - ? $this->_addLocationsFromCommTo($radio) - : $this->_addLocationsFromCodifTo($radio); - - $this->_setLocationTo($radio, $locations); - if ($this->_request->isPost() - && $form->isValid($this->_request->getPost())) { - return $this->_redirect($this->view->url(['module' => 'opac', - 'controller' => 'recherche', - 'action' => 'reservationajax', - 'render' => null, - 'code_annexe' => $this->_request->getPost('code_annexe')])); - } - $html = []; - if ($message = trim(Class_AdminVar::getValueOrDefault('HOLD_SITE_SELECTION_CUSTOM_MESSAGE'))) - $html[] = $this->view->div(['class' => 'hold_site_selection_message'], $message); + public function reservationPickupAjaxAction() { + if ( ! $user = $this->_userConnected()) + return ; - $html[] = (empty($radio->getMultiOptions()) - ? $this->view->tag('p', - $this->_('Aucun site de retrait disponible'), - ['class' => 'error']) - : $this->view->renderForm($form)); + if ( ! $item = Class_Exemplaire::find($this->_getParam('copy_id'))) + return $this->renderPopupResult($this->view->_('Réservation'), + $this->_('Document introuvable')); - $this->renderPopupResult($this->view->_('Lieu de mise à disposition demandé'), - implode('', $html)); + if ( ! $this->_shouldDisplayPickupLocations($user)) + return $this->_holdItem($user, $item); - return null; + return ($item->canBeHeldFromCentralizedLibrary()) + ? $this->_holdItem($user, $item) + : $this->_pickupLocationForm($user); } - public function setMoteurRecherche($moteur) - { - $this->moteur = $moteur; + + protected function _holdItemUnavailable(): void { + $this->renderPopupResult($this->_('Réservation impossible'), + $this->_('Vous ne pouvez pas réserver cet exemplaire !')); } - public function downloadRecordAction() - { - if (!$record = Class_Notice::find($this->_getParam('id', 0))) - return $this->_redirect('/'); - $this->_helper->binaryDownload($record->getUnimarc(), $record->getId() . '.txt'); - return null; - } + protected function _holdItem(Class_Users $user, Class_Exemplaire $item): void { + $code_annexe = $this->_getCodeAnnexe($user, $item); - public function downloadItemAction() - { - if (!$item = Class_Exemplaire::find($this->_getParam('id', 0))) - return $this->_redirect('/'); - if (!$raw_record = Class_Cosmogramme_Integration_RawRecord::findFor($item)) - return $this->_redirect('/'); - $this->_helper->binaryDownload($raw_record->getData(), $raw_record->getName()); + $response = Class_CommSigb::getInstance()->reserveItem($item, + $code_annexe); - return null; + $this->renderPopupResult($this->_('Réservation'), + $this->_getHoldMessage($user, $item, $response)); } - public function clearLastSearchSessionAction() - { - $this->_helper->getHelper('viewRenderer')->setNoRender(); - Zend_Registry::get('session')->last_search = null; - } - public function reserverAction() + protected function _getCodeAnnexe( Class_Users $user, + Class_Exemplaire $item): string { - $this->view->titre = $this->_('Réserver un document'); + if ($this->_code_annexe) + return $this->_code_annexe; - if (!$record = Class_Notice::find($this->_getParam('record_id', 0))) - return $this->view->_error_message = $this->_('Document introuvable'); - if (!$record->hasExemplaires()) - return $this->view->_error_message = $this->_('Le document n\'a pas d\'exemplaire.'); - $this->view->items = (new Intonation_Library_Record($record)) - ->getItemsFromSIGB(); + $code_annexe = $this->_getParam('code_annexe', ''); - return null; - } + if (Class_CosmoVar::isSiteRetraitResaPatronLibrary()) + $code_annexe = $user->getUserIdSite(); - protected function _getTitreRechercheViewNotice($criteres_recherche) - { - if ($title = $this->view->search_Title($criteres_recherche, $this->_request, $this)) - return $this->view->titreAdd($title); + if (Class_CosmoVar::isSiteRetraitResaItemLibrary()) + $code_annexe = $item->annexeCode(); - return null; + return $this->_code_annexe = $code_annexe; } - protected function _authorityFromParams() + + protected function _pickupLocationForm(Class_Users $user): void { - if ((!$authority_id = $this->_getParam('authority_id')) - || (!$thesaurus_id = $this->_getParam('thesaurus_id'))) - return null; - $items = Class_Exemplaire::findAllBy(['type' => Class_Notice::TYPE_AUTHORITY, - 'id_origine' => $authority_id]); - foreach ($items as $item) - if ($record = $this->_recordWithThesaurusFacet($thesaurus_id, $item)) - return $record; + $form = $this->getReservationForm(); - return null; - } + $radio = $form->getElement('code_annexe'); - protected function _recordWithThesaurusFacet($thesaurus_id, $item) - { - if (!$record = $item->getNotice()) - return null; + if (($user = Class_Users::getIdentity()) + && ($comm = $user->getSIGBComm())) + $this->_setPickupLocations($radio, $comm); - return in_array(Class_CodifThesaurus::CODE_FACETTE . $thesaurus_id, $record->getFacetCodes()) - ? $record - : null; + if ($this->_request->isPost() + && $form->isValid($this->_request->getPost())) + { + + $this->_redirect($this->view->url(['module' => 'opac', + 'controller' => 'recherche', + 'action' => 'reservationajax', + 'render' => null, + 'code_annexe' => $this->_request->getPost('code_annexe')])); + return; + } + + $html = []; + if ($message = trim(Class_AdminVar::getValueOrDefault('HOLD_SITE_SELECTION_CUSTOM_MESSAGE'))) + $html[] = $this->view->div(['class' => 'hold_site_selection_message'], $message); + + $html[] = (empty($radio->getMultiOptions()) + ? $this->view->tag('p', + $this->_('Aucun site de retrait disponible'), + ['class' => 'error']) + : $this->view->renderForm($form)); + + $this->renderPopupResult($this->view->_('Lieu de mise à disposition demandé'), + implode('', $html)); } + protected function _findRecordByKeyOrId($key, $id) { $result = new RechercheController_FindRecordByKeyOrIdResult; @@ -696,171 +823,142 @@ class RechercheController extends ZendAfi_Controller_Action return $this->view->_('Votre réservation est enregistrée.'); } - protected function _renderHolds($id_exemplaire) + + protected function userConnected() { - $item = Class_Exemplaire::find($id_exemplaire); - $holds = Class_CommSigb::getInstance()->holdsForItem($item)['holds'] ?? []; - usort($holds, - fn($a, $b) => strcmp($a->getReserveDate(), $b->getReserveDate())); + if (!$user = Class_Users::getIdentity()) { + $this->_forwardToLogin($this->view->url(), ''); - $html = implode('', - array_map(fn($hold) => $this->view->tag('li', - $hold->renderRange()), - $holds)); + return false; + } - $js_holds = json_encode(array_map( - fn($hold) => [$hold->getReserveDate(), $hold->getExpirationDate()], - $holds)); + return $user; + } - Class_ScriptLoader::getInstance() - ->addAdminScript('jquery_ui_datepicker_i18n/datepicker-fr.js') - ->addJQueryReady(' - Date.prototype.withoutTime = function () { - var d = new Date(this); - d.setHours(0, 0, 0, 0); - return d; - } - $.datepicker.setDefaults($.datepicker.regional["' . (('en_US' == Zend_Registry::get('locale')) ? '' : 'fr') . '"]); - $("input").blur(); - $("#holds_view").datepicker( - { - numberOfMonths: 3, - beforeShowDay: function(date) { - var holds = ' . $js_holds . '; - var day = date.withoutTime(); - var hold = holds.find( (hold) => { - return (new Date(hold[0]).withoutTime() <= day) && (day <= new Date(hold[1]).withoutTime()); - }); - if (undefined == hold) - return [false, "day-without-hold"]; + protected function _addLocationsFromCodifTo(Class_WebService_SIGB_LibraryWrapper $comm): array + { + $locations = []; - return [false, "day-with-hold", "' . $this->_('Reservation déjà présente ce jour') . '"]; - }} - );'); + foreach ($comm->codifAnnexesForUrlServer() as $annexe) + $locations[$annexe->getCode()] = $annexe->getLibelle(); - return '<div id="holds_view"></div><div>' - . $this->view->tag('span', $this->_('Réservations non disponibles : ')) - . $this->view->tag('ul', $html) . '</div>'; + + return $locations; } - protected function _getHoldMessage($user, $item_id, $response) + + protected function _setPickupLocations(Zend_Form_Element $element, + Class_WebService_SIGB_LibraryWrapper $comm): self { - if ($response['erreur']) - return $response['erreur']; - if (isset($response['popup']) && $response['popup']) - return '<iframe src="' . $response['popup'] . '"></iframe>'; - $current_hold = null; - foreach ($user->getReservations() as $hold) { - if (!$opac_item = $hold->getExemplaireOPAC()) - continue; - if ($item_id == $opac_item->getId()) { - $current_hold = $hold; - - break; - } - } + $locations = $this->_arePickupLocationsProvidedByUserComm($comm) + ? $this->_addLocationsFromCommTo($comm) + : $this->_addLocationsFromCodifTo($comm); - return ($current_hold && ($location_label = $current_hold->getPickupLocationLabel())) - ? $this->view->_('Votre réservation est enregistrée.<br>Nous vous informerons quand le document%s sera disponible pour être retiré à : %s', - $this->_getMessageNoticeLabel($item_id), $location_label) - : $this->view->_('Votre réservation est enregistrée.<br>Nous vous informerons quand le document%s sera disponible', - $this->_getMessageNoticeLabel($item_id)); + return $this->_setLocationTo($element, $locations); } - protected function _getMessageNoticeLabel($item_id) + + protected function _setLocationTo(Zend_Form_Element $element, array $locations): self { - if (!$item_id - || !($item = Class_Exemplaire::find($item_id)) - || !($notice = $item->getNotice())) - return ''; - $title = strip_tags($notice->getTitrePrincipal()); + $requested_location = $this->_getParam('code_annexe'); + if (($user = Class_Users::getIdentity()) + && ($user_location = $user->getLibraryCode()) + && ($locations[$user_location] ?? '')) + $requested_location = $user_location; - if (!$notice->getAuteurPrincipal()) - return sprintf(" '%s'", $title); + foreach ($locations as $k => $v) + $element->addMultiOption($k, $v); - return sprintf(" '%s / %s'", - $title, - $notice->getAuteurPrincipal()); + if ($locations[$requested_location] ?? '') + $element->setValue($requested_location); + + return $this; } - protected function userConnected() + + protected function _addLocationsFromCommTo(Class_WebService_SIGB_LibraryWrapper $comm): array { - if (!$user = Class_Users::getIdentity()) { - $this->_forwardToLogin($this->view->url(), ''); + if ( ! $item = Class_Exemplaire::find($this->_getParam('copy_id'))) + return []; + + $first = ''; + $locations = $comm->pickupLocationsFor(Class_Users::getIdentity(), $item); + return ((isset($locations['statut']) && ! $locations['statut']) + ? [] + : $locations); + } + + protected function _shouldDisplayPickupLocations(Class_Users $user): bool + { + if ( ! Class_CosmoVar::isSiteRetraitResaChoiceEnabled()) return false; - } - return $user; + if ( ! $comm = Class_Users::getIdentity()->getSIGBComm()) + return false; + + return $comm->providesPickupLocations() + || (count($comm->codifAnnexesForUrlServer()) > 1); } - protected function getReservationForm($action = 'reservation-pickup-ajax') + + protected function _arePickupLocationsProvidedByUserComm(Class_WebService_SIGB_LibraryWrapper $comm): bool { - return $this->view - ->newForm(['id' => 'pickup', - 'class' => 'zend_form reservation_pickup', - 'action' => $this->view->url(['controller' => 'recherche', - 'action' => $action])]) - ->addElement('Radio', - 'code_annexe', - ['required' => true, - 'allowEmpty' => false, - 'escape' => false]) + if ( !Class_CosmoVar::isSiteRetraitResaChoiceEnabled()) + return false; - ->addDisplayGroup(['code_annexe'], 'group', ['legend' => 'Site de retrait']); + return $comm->providesPickupLocations(); } - protected function _addLocationsFromCodifTo(Zend_Form_Element $element): array - { - $locations = []; - foreach (Class_CodifAnnexe::findAllByPickup() as $annexe) { - $element->addMultiOption($annexe->getCode(), $annexe->getLibelle()); - $locations[$annexe->getCode()] = $annexe->getLibelle(); - } + public function setMoteurRecherche($moteur) { + $this->moteur = $moteur; + } - return $locations; + + public function downloadRecordAction() { + if (!$record = Class_Notice::find($this->_getParam('id', 0))) + return $this->_redirect('/'); + + $this->_helper->binaryDownload($record->getUnimarc(), $record->getId() . '.txt'); } - protected function _setLocationTo(Zend_Form_Element $element, array $locations) - { - $requested_location = $this->_getParam('code_annexe'); - if (($user = Class_Users::getIdentity()) - && ($user_location = $user->getUserIdSite()) - && ($locations[$user_location] ?? '')) - $requested_location = $user_location; - if ($locations[$requested_location] ?? '') - $element->setValue($requested_location); + public function downloadItemAction() { + if (!$item = Class_Exemplaire::find($this->_getParam('id', 0))) + return $this->_redirect('/'); + + if (!$raw_record = Class_Cosmogramme_Integration_RawRecord::findFor($item)) + return $this->_redirect('/'); + + $this->_helper->binaryDownload($raw_record->getData(), $raw_record->getName()); } - protected function _addLocationsFromCommTo(Zend_Form_Element $element): array - { - if ((!$user = Class_Users::getIdentity()) - || (!$comm = $user->getSIGBComm()) - || (!$item = Class_Exemplaire::find($this->_getParam('copy_id')))) - return []; - $locations = $comm->pickupLocationsFor($user, $item); - if (isset($locations['statut']) && !$locations['statut']) - return []; - foreach ($locations as $k => $v) - $element->addMultiOption($k, $v); - return $locations; + public function clearLastSearchSessionAction() { + $this->_helper->getHelper('viewRenderer')->setNoRender(); + Zend_Registry::get('session')->last_search = null; } - protected function arePickupLocationsProvidedByComm() - { - if ((!$user = Class_Users::getIdentity()) - || (!Class_Exemplaire::find($this->_getParam('copy_id')))) - return false; - return ($comm = $user->getSIGBComm()) ? - $comm->providesPickupLocations() : false; + public function reserverAction() { + $this->view->titre = $this->_('Réserver un document'); + + if ( ! $record = Class_Notice::find($this->_getParam('record_id', 0))) + return $this->view->_error_message = $this->_('Document introuvable'); + + if ( ! $record->hasExemplaires() ) + return $this->view->_error_message = $this->_('Le document n\'a pas d\'exemplaire.'); + + $this->view->items = (new Intonation_Library_Record($record)) + ->getItemsFromSIGB(); } } + + + class RechercheController_FindRecordByKeyOrIdResult { protected $_record; diff --git a/cosmogramme/cosmozend/application/modules/cosmo/controllers/DataProfileController.php b/cosmogramme/cosmozend/application/modules/cosmo/controllers/DataProfileController.php index 415e2414e6d27e270583a6ede655546030fa5942..02031bf3fd6a17fa609e696f29c9d312d1789644 100644 --- a/cosmogramme/cosmozend/application/modules/cosmo/controllers/DataProfileController.php +++ b/cosmogramme/cosmozend/application/modules/cosmo/controllers/DataProfileController.php @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +require_once(__DIR__ . '/../../../../../php/classes/classe_profil_donnees.php'); class Cosmo_DataProfileController extends ZendAfi_Controller_Action { @@ -35,4 +36,27 @@ class Cosmo_DataProfileController extends ZendAfi_Controller_Action { $url .= '/'.$scope_field.'/'.$scope_value; $this->_redirect($url); } + + + public function copyCodifAction() { + $this->view->target_profile = $this->_getParam('id'); + $this->view->titre = $this->_('Copier des règles de codification dans le profil: %s', + Class_IntProfilDonnees::getLabel($this->view->target_profile)); + } + + + public function copyCodifConfirmAction() { + $importer = + (new Class_Cosmogramme_CodifImporter((int) $this->_getParam('id'), + (int) $this->_getParam('profile'), + (array) $this->_getParam('codif_types'), + (int) $this->_getParam('from'))) + ->import(); + + ($errors = $importer->getErrors()) + ? $this->_helper->notifyError(implode(BR, $errors), ['status' => 'error']) + : $this->_helper->notify($this->_('Les règles de codificatin ont été importées')); + + return $this->_redirectToIndex(); + } } diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/annexe/index.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/annexe/index.phtml index b93efb0e76c423a1f7b061f8e9d67022ed2f20fc..d9c431d365bf706fdd5da0d34138d6d048defa45 100644 --- a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/annexe/index.phtml +++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/annexe/index.phtml @@ -4,13 +4,15 @@ echo $this->tagAnchor(['action' => 'add', $this->_('Ajouter une annexe')); echo $this->tagModelTable($this->annexes, - [$this->_('Bibliothèque'), + [$this->_('id'), + $this->_('Bibliothèque'), $this->_('Code dans le SIGB'), $this->_('Code facette calculé'), $this->_('libellé'), $this->_('Rejeter les exemplaires'), $this->_('Exclu du PEB')], - ['library_label', + ['id_annexe', + 'library_label', 'id_origine', 'code', 'libelle', diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/data-profile/copy-codif.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/data-profile/copy-codif.phtml new file mode 100644 index 0000000000000000000000000000000000000000..e04def3c1f364e6217b48b15f5bc6794d7204dfe --- /dev/null +++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/data-profile/copy-codif.phtml @@ -0,0 +1,2 @@ +<?php +echo $this->Cosmo_CodifsImporter(); diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/data-profile/index.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/data-profile/index.phtml index 16501c5a2e4442396a0366c27714135bf8ce2d3e..e0998d7564d8459d13b2904a9410a2d57215f40d 100644 --- a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/data-profile/index.phtml +++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/data-profile/index.phtml @@ -15,6 +15,13 @@ $isUsed = function($model, $attrib) { return $this->tag('div', $this->_('Oui (?)') . $html, ['class' => 'table_tooltip_wrapper']); }; +$hasCodifRules = function($profile) { + return $profile->hasCodifRules() + ? $this->tagAnchor(['action' => 'copy-codif', 'id' => $profile->getId()], + $this->boutonIco('type=copy_codifs')) + : ''; +}; + echo $this->tagModelTable($this->data_profiles, [$this->_('Libellé'), $this->_('Type de fichier'), @@ -25,7 +32,8 @@ echo $this->tagModelTable($this->data_profiles, 'format-label', 'isUsed'], [['action' => 'edit', 'content' => $this->boutonIco('type=edit')], - ['action' => 'delete', 'content' => $this->boutonIco('type=del')] ], + ['action' => 'delete', 'content' => $this->boutonIco('type=del')], + $hasCodifRules], '', null, ['isUsed' => $isUsed]); diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/AnnexeControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/AnnexeControllerTest.php index bda0264b70c06c4e37d06864c5a430482c8de6d9..b2fb2175713cb986513431fb2ac28bd95cedb0e0 100644 --- a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/AnnexeControllerTest.php +++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/AnnexeControllerTest.php @@ -71,12 +71,24 @@ class AnnexeControllerIndexTest extends AnnexeControllerTestCase { } + /** @test */ + public function annexeAnnecyIdShouldBeInTable() { + $this->assertXPathContentContains('//table//td', 98); + } + + /** @test */ public function annexeAnnecyShouldBeInTable() { $this->assertXPathContentContains('//table//td', 'Annexe Annecy'); } + /** @test */ + public function lostAnnexIdShouldBeInTable() { + $this->assertXPathContentContains('//table//td', 120); + } + + /** @test */ public function lostAnnexShouldBeInTable() { $this->assertXPathContentContains('//table//td', 'Annex lost'); diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerCodificationsTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerCodificationsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..73cd4ea8a1cd598a5dfa5fef2d11d44921f56518 --- /dev/null +++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerCodificationsTest.php @@ -0,0 +1,295 @@ +<?php +/** + * Copyright (c) 2012-2023, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class DataProfileControllerCodificationsSectionAddTest + extends CosmoControllerTestCase +{ + + public function setUp() : void + { + parent::setUp(); + $this->dispatch('/cosmo/data-profile/add'); + } + + + /** @test */ + public function sectionTabShouldExist() { + $this->assertXPathContentContains('//fieldset[@id="fieldset-section_group"]/legend', + 'Sections'); + } + + + /** @test */ + public function sectionLabelShouldExist() { + $this->assertXPathContentContains('//tr[@class="sections_field"]/td', + 'Rechercher les sections dans'); + } +} + + + + +class DataProfileControllerCodificationsSectionPostAddTest + extends CosmoControllerTestCase +{ + + protected $_prefs; + + public function setUp() :void + { + parent::setUp(); + + $this->postDispatch('cosmo/data-profile/add', + ['libelle' => 'Section test profile', + 'accents' => Class_IntProfilDonnees::ENCODING_ISO2709, + 'type_fichier' => Class_IntProfilDonnees::FT_RECORDS, + 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'sections_label' => ['LabelOne', 'LabelTwo'], + 'sections_zone' => ['919$a', '929$b'], + 'sections_mode' => ['equals', 'starts'], + 'sections_value' => ['L1', 'L2'], + 'sections_whitespace' => [0, 1], + 'sections_skipitems' => [1, 0]]); + + $this->_prefs = Class_IntProfilDonnees::findFirstBy(['libelle' => 'Section test profile']) + ->getProfilePrefs() + ->getSections(); + + } + + + public function sectionsPrefs() : array { + return [['sections_label', ['LabelOne', 'LabelTwo']], + ['sections_zone', ['919$a', '929$b']], + ['sections_mode', ['equals', 'starts']], + ['sections_value', ['L1', 'L2']], + ['sections_whitespace', [0, 1]]]; + } + + + /** + * @dataProvider sectionsPrefs + * @test */ + public function profileDataShouldMatchSectionsPrefs($pref_key, $values) { + $this->assertEquals($this->_prefs[$pref_key], $values); + } +} + + + + +class DataProfileControllerCodificationsSortAddTest + extends CosmoControllerTestCase +{ + + public function setUp() :void + { + parent::setUp(); + $this->dispatch('/cosmo/data-profile/add'); + } + + + /** @test */ + public function sortTabShouldExist() { + $this->assertXPathContentContains('//fieldset[@id="fieldset-sort_group"]/legend', + 'Genres'); + } + + + /** @test */ + public function sortLabelShouldExist() { + $this->assertXPathContentContains('//tr[@class="sorts_field"]/td', + 'Rechercher les genres dans'); + } +} + + + + +class DataProfileControllerCodificationsSortPostAddTest + extends CosmoControllerTestCase +{ + + protected $_prefs; + + public function setUp() : void + { + parent::setUp(); + + $this->postDispatch('cosmo/data-profile/add', + ['libelle' => 'Sort test profile', + 'accents' => Class_IntProfilDonnees::ENCODING_ISO2709, + 'type_fichier' => Class_IntProfilDonnees::FT_RECORDS, + 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'sorts_label' => ['SortOne', 'SortTwo'], + 'sorts_zone' => ['995$2', '995$3'], + 'sorts_mode' => ['starts', 'contains'], + 'sorts_value' => ['S1', 'S2'], + 'sorts_whitespace' => [1, 0]]); + + $this->_prefs = Class_IntProfilDonnees::findFirstBy(['libelle' => 'Sort test profile']) + ->getProfilePrefs() + ->getSorts(); + + } + + + public function sortsPrefs() : array { + return [['sorts_label', ['SortOne', 'SortTwo']], + ['sorts_zone', ['995$2', '995$3']], + ['sorts_mode', ['starts', 'contains']], + ['sorts_value', ['S1', 'S2']], + ['sorts_whitespace', [1, 0]]]; + } + + + /** + * @dataProvider sortsPrefs + * @test */ + public function profileDataShouldMatchSortsPrefs($pref_key, $values) { + $this->assertEquals($this->_prefs[$pref_key], $values); + } +} + + + + +class DataProfileControllerCodificationsLocationAddTest + extends CosmoControllerTestCase +{ + + public function setUp() : void + { + parent::setUp(); + $this->dispatch('/cosmo/data-profile/add'); + } + + + /** @test */ + public function locationTabShouldExist() { + $this->assertXPathContentContains('//fieldset[@id="fieldset-location_group"]/legend', + 'Emplacements'); + } + + + /** @test */ + public function locationLabelShouldExist() { + $this->assertXPathContentContains('//tr[@class="locations_field"]/td', + 'Rechercher les emplacements dans'); + } +} + + + + +class DataProfileControllerCodificationsLocationPostAddTest + extends CosmoControllerTestCase +{ + + protected $_prefs; + + public function setUp() : void + { + parent::setUp(); + + $this->postDispatch('cosmo/data-profile/add', + ['libelle' => 'Location test profile', + 'accents' => Class_IntProfilDonnees::ENCODING_ISO2709, + 'type_fichier' => Class_IntProfilDonnees::FT_RECORDS, + 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'locations_label' => ['LocOne', 'LocTwo'], + 'locations_zone' => ['995$4', '995$5'], + 'locations_mode' => ['starts', 'equals'], + 'locations_value' => ['L1', 'L2'], + 'locations_whitespace' => [1, 1]]); + + $this->_prefs = Class_IntProfilDonnees::findFirstBy(['libelle' => 'Location test profile']) + ->getProfilePrefs() + ->getLocations(); + + } + + + public function locationsPrefs() : array { + return [['locations_label', ['LocOne', 'LocTwo']], + ['locations_zone', ['995$4', '995$5']], + ['locations_mode', ['starts', 'equals']], + ['locations_value', ['L1', 'L2']], + ['locations_whitespace', [1, 1]]]; + } + + + /** + * @dataProvider locationsPrefs + * @test */ + public function profileDataShouldMatchLocationsPrefs($pref_key, $values) { + $this->assertEquals($this->_prefs[$pref_key], $values); + } +} + + + + +class DataProfileControllerCodificationsEmptyPostAddTest + extends CosmoControllerTestCase +{ + + protected $_prefs; + + public function setUp() : void + { + parent::setUp(); + + $this->postDispatch('cosmo/data-profile/add', + ['libelle' => 'Location test profile', + 'accents' => Class_IntProfilDonnees::ENCODING_ISO2709, + 'type_fichier' => Class_IntProfilDonnees::FT_RECORDS, + 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'locations_label' => [''], + 'locations_zone' => [''], + 'locations_mode' => ['='], + 'locations_value' => [''], + 'locations_whitespace' => [0]]); + + $this->_prefs = Class_IntProfilDonnees::findFirstBy(['libelle' => 'Location test profile']) + ->getProfilePrefs() + ->getLocations(); + + } + + + public function locationsPrefs() : array { + return [['locations_label', []], + ['locations_zone', []], + ['locations_mode', []], + ['locations_value', []], + ['locations_whitespace', []]]; + } + + + /** + * @dataProvider locationsPrefs + * @test */ + public function profileDataShouldMatchLocationsPrefs($pref_key, $values) { + $this->assertEquals($this->_prefs[$pref_key], $values); + } +} diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerCodifsImporterTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerCodifsImporterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5f1157a90b425b4d551abc933f6f01477cd5490a --- /dev/null +++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerCodifsImporterTest.php @@ -0,0 +1,765 @@ +<?php +/** + * Copyright (c) 2012-2023, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +abstract class DataProfileControllerCodifsImporterTestCase extends CosmoControllerTestCase { + + protected + $_target, + $_incoming; + + public function setUp() : void + { + parent::setUp(); + + $this->fixture(Class_IntProfilDonnees::class, + ['id' => 17, + 'libelle' => 'Notices unimarc', + 'type_fichier' => Class_IntProfilDonnees::FT_RECORDS, + 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'attributs' => []]); + + $this->fixture(Class_IntProfilDonnees::class, + ['id' => 18, + 'libelle' => 'Astrolabe', + 'type_fichier' => Class_IntProfilDonnees::FT_RECORDS, + 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'attributs' => ['sorts' => ['sorts_label' => ['SortOne', 'SortTwo'], + 'sorts_zone' => ['995$b', '995$b'], + 'sorts_mode' => ['=', '*'], + 'sorts_value' => ['A', 'S'], + 'sorts_whitespace' => [1, 0]], + 'sections' => ['sections_label' => ['SecOne', 'SecTwo'], + 'sections_zone' => ['902$a', '995$k'], + 'sections_mode' => ['/', '='], + 'sections_value' => ['Disque', 'R WIC'], + 'sections_whitespace' => [0, 1]], + 'locations' => ['locations_label' => ['LocOne', 'LocTwo'], + 'locations_zone' => ['995$q', '995$q'], + 'locations_mode' => ['=', '='], + 'locations_value' => ['Disque', 'R;A'], + 'locations_whitespace' => [0, 0]]]]); + + $this->fixture(Class_IntProfilDonnees::class, + ['id' => 19, + 'libelle' => 'Unimarc Koha', + 'type_fichier' => Class_IntProfilDonnees::FT_RECORDS, + 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'attributs' => []]); + + $this->fixture(Class_IntProfilDonnees::class, + ['id' => 20, + 'libelle' => 'Unimarc standard', + 'type_fichier' => Class_IntProfilDonnees::FT_AUTHORITY, + 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'attributs' => []]); + + $this->fixture(Class_IntProfilDonnees::class, + ['id' => 21, + 'libelle' => 'Non Unimarc', + 'type_fichier' => Class_IntProfilDonnees::FT_RECORDS, + 'format' => Class_IntProfilDonnees::FORMAT_CSV, + 'attributs' => []]); + + $this->fixture(Class_CodifGenre::class, + ['id' => 1, + 'libelle' => 'Jeux', + 'regles' => '995$q=0@@J']); + + $this->fixture(Class_CodifGenre::class, + ['id' => 2, + 'libelle' => 'Politique', + 'regles' => '995$q=1@@POL;P']); + + $this->fixture(Class_CodifGenre::class, + ['id' => 3, + 'libelle' => 'Codif without rule', + 'regles' => '']); + + $this->fixture(Class_CodifGenre::class, + ['id' => 4, + 'libelle' => 'Null codif rule']); + + $this->fixture(Class_CodifSection::class, + ['id' => 5, + 'libelle' => 'Jeunesse', + 'regles' => '995$a=0@@J']); + + $this->fixture(Class_CodifEmplacement::class, + ['id' => 6, + 'libelle' => 'Étage', + 'regles' => '995$b=1@@1']); + + $this->fixture(Class_CodifEmplacement::class, + ['id' => 7, + 'libelle' => 'RDC', + 'regles' => '995$b=0@@0']); + } + + + public function getTarget(string $key) : array { + $attributes = Class_IntProfilDonnees::find($this->_target) + ->getAttributsAsArray(); + + return isset($attributes[$key]) ? $attributes[$key] : []; + } + + + public function getIncoming(string $key) : array { + $attributes = Class_IntProfilDonnees::find($this->_incoming) + ->getAttributsAsArray(); + + return isset($attributes[$key]) ? $attributes[$key] : []; + } +} + + + + +class DataProfileControllerCodifsImporterFormTest + extends DataProfileControllerCodifsImporterTestCase { + + public function setUp() :void + { + parent::setUp(); + + $this->dispatch('/cosmo/data-profile/copy-codif/id/17'); + } + + + /** @test */ + public function pageShouldContainTitle() { + $this + ->assertXPathContentContains('//h1', + 'Copier des règles de codification dans le profil: Notices unimarc'); + } + + + /** @test */ + public function formActionShouldBeDataProfileCodifImportConfirm() + { + $this->assertXPath('//form[@action="/cosmo/data-profile/copy-codif-confirm/id/17"]'); + } + + + /** @test */ + public function fromGlobalsRulesOptionShouldBeInFromSelect() { + $this->assertXPathContentContains('//select[@id="from"]/option[@value="1"]', + 'Les règles globales'); + } + + + /** @test */ + public function fromDataProfileRulesOptionShouldBeInFromSelect() { + $this->assertXPathContentContains('//select[@id="from"]/option[@value="2"]', + 'Un profil de données'); + } + + + /** @test */ + public function SortsOptionShouldBeInCodifTypesSelect() { + $this->assertXPath('//input[@type="checkbox"][@name="codif_types[]"][@value="sorts"]'); + } + + + /** @test */ + public function SectionsOptionShouldBeInCodifTypesSelect() { + $this->assertXPath('//input[@type="checkbox"][@name="codif_types[]"][@value="sections"]'); + } + + + /** @test */ + public function LocationsOptionShouldBeInCodifTypesSelect() { + $this->assertXPath('//input[@type="checkbox"][@name="codif_types[]"][@value="locations"]'); + } + + + /** @test */ + public function astrolabeShouldBeInProfileSelect() { + $this->assertXPathContentContains('//select[@id="profile"]/option[@value="18"]', + 'Astrolabe'); + } + + + /** @test */ + public function unimarcKohaShouldBeInProfileSelect() { + $this->assertXPathContentContains('//select[@id="profile"]/option[@value="19"]', + 'Unimarc Koha'); + } + + + /** @test */ + public function authorityProfileShouldNotBeInProfileSelect() { + $this->assertNotXPath('//select[@id="profile"]/option[@value="20"]'); + } + + + /** @test */ + public function targetProfileShouldNotBeInProfileSelect() { + $this->assertNotXPath('//select[@id="profile"]/option[@value="17"]'); + } + + + /** @test */ + public function nonUnimarcProfileShouldNotBeInProfileSelect() { + $this->assertNotXPath('//select[@id="profile"]/option[@value="21"]'); + } +} + + + + +class DataProfileControllerCodifsImporterNoTargetProfileTestCase + extends DataProfileControllerCodifsImporterTestCase { + + protected $flash; + public function setUp() : void + { + parent::setUp(); + + $this->_target = 90; + $this->_incoming = 18; + + $this->postDispatch('/cosmo/data-profile/copy-codif-confirm/id/' . $this->_target, + ['from' => Class_Cosmogramme_CodifImporter::FROM_PROFILE, + 'codif_types' => ['sorts'], + 'profile' => $this->_incoming]); + } + + + /** @test */ + public function flashMessengerContentShouldBeProfilDeDonneesWithError() { + $flash = new Zend_Session_Namespace('FlashMessenger'); + $this->assertEquals(['message' => 'Profil de données cible inconnu', + 'status' => 'error'], + reset($flash->__get('default'))['notification']); + } +} + + + + +class DataProfileControllerCodifsImporterNoIncomingProfileTestCase + extends DataProfileControllerCodifsImporterTestCase { + + public function setUp() : void + { + parent::setUp(); + + $this->_target = 17; + $this->_incoming = 90; + + $this->postDispatch('/cosmo/data-profile/copy-codif-confirm/id/' . $this->_target, + ['from' => Class_Cosmogramme_CodifImporter::FROM_PROFILE, + 'codif_types' => ['sorts'], + 'profile' => $this->_incoming]); + } + + + /** @test */ + public function contextShouldExpectation() { + $this->assertFlashMessengerContentContains('Profil de données inconnu'); + } +} + + + + +class DataProfileControllerCodifsImporterSortsFromExistingProfile + extends DataProfileControllerCodifsImporterTestCase { + + public function setUp() : void + { + parent::setUp(); + + $this->_target = 17; + $this->_incoming = 18; + + $this->postDispatch('/cosmo/data-profile/copy-codif-confirm/id/' . $this->_target, + ['from' => Class_Cosmogramme_CodifImporter::FROM_PROFILE, + 'codif_types' => ['sorts'], + 'profile' => $this->_incoming]); + } + + + /** @test */ + public function profile17SortsShouldEqualsProfile18() { + $this->assertEquals($this->getTarget('sorts'), $this->getIncoming('sorts')); + } + + + /** @test */ + public function profile17SectionsShouldNotBeErased() { + $this->assertEmpty($this->getTarget('sections')); + } + + + /** @test */ + public function profile17LocationsShouldNotBeErased() { + $this->assertEmpty($this->getTarget('locations')); + } + + + /** @test */ + public function contextShouldExpectation() { + $this->assertFlashMessengerContentContains('Les règles de codificatin ont été importées'); + } +} + + + + +class DataProfileControllerCodifsImporterSectionsFromExistingProfile + extends DataProfileControllerCodifsImporterTestCase { + + protected $_sorts; + + public function setUp() : void + { + parent::setUp(); + + $this->_target = 17; + $this->_incoming = 18; + $this->_sorts = ['sorts_label' => ['MySort'], + 'sorts_zone' => ['995$a'], + 'sorts_mode' => ['='], + 'sorts_value' => ['A'], + 'sorts_whitespace' => [0]]; + + Class_IntProfilDonnees::find($this->_target) + ->setAttributs(['sorts' => $this->_sorts]) + ->save(); + + $this->postDispatch('/cosmo/data-profile/copy-codif-confirm/id/' . $this->_target, + ['from' => Class_Cosmogramme_CodifImporter::FROM_PROFILE, + 'codif_types' => ['sections'], + 'profile' => $this->_incoming]); + } + + + /** @test */ + public function profile17SortsShouldEqualsProfile18() { + $this->assertEquals($this->getTarget('sections'), $this->getIncoming('sections')); + } + + + /** @test */ + public function targetProfileSortsShouldNotBeErased() { + $this->assertEquals($this->_sorts, $this->getTarget('sorts')); + } + + + /** @test */ + public function targetProfileLocationsShouldNotBeErased() { + $this->assertEmpty($this->getTarget('locations')); + } +} + + + + +class DataProfileControllerCodifsImporterLocationsFromExistingProfile + extends DataProfileControllerCodifsImporterTestCase { + + public function setUp() : void + { + parent::setUp(); + + $this->_target = 17; + $this->_incoming = 18; + + $this->postDispatch('/cosmo/data-profile/copy-codif-confirm/id/' . $this->_target, + ['from' => Class_Cosmogramme_CodifImporter::FROM_PROFILE, + 'codif_types' => ['locations'], + 'profile' => $this->_incoming]); + } + + + /** @test */ + public function profile17SortsShouldEqualsProfile18() { + $this->assertEquals($this->getTarget('locations'), $this->getIncoming('locations')); + } + + + /** @test */ + public function IncomingProfileSortsShouldNotBeErased() { + $this->assertNotEmpty($this->getIncoming('sorts')); + } + + + /** @test */ + public function IncomingProfileSectionsShouldNotBeErased() { + $this->assertNotEmpty($this->getIncoming('sections')); + } + + + /** @test */ + public function IncomingProfileLocationsShouldNotBeErased() { + $this->assertNotEmpty($this->getIncoming('locations')); + } +} + + + + +class DataProfileControllerCodifsImporterSortsAndLocationsFromExistingProfile + extends DataProfileControllerCodifsImporterTestCase { + + public function setUp() : void + { + parent::setUp(); + + $this->_target = 17; + $this->_incoming = 18; + + $this->postDispatch('/cosmo/data-profile/copy-codif-confirm/id/' . $this->_target, + ['from' => Class_Cosmogramme_CodifImporter::FROM_PROFILE, + 'codif_types' => ['sorts', 'locations'], + 'profile' => $this->_incoming]); + } + + + /** @test */ + public function profile17SortsShouldEqualsProfile18() { + $this->assertEquals($this->getTarget('sorts'), $this->getIncoming('sorts')); + } + + + /** @test */ + public function profile17LocationsShouldEqualsProfile18() { + $this->assertEquals($this->getTarget('locations'), $this->getIncoming('locations')); + } + + + /** @test */ + public function profile17SectionsShouldNotBeErased() { + $this->assertEmpty($this->getTarget('sections')); + } +} + + + + +class DataProfileControllerCodifsImporterAllFromExistingProfile + extends DataProfileControllerCodifsImporterTestCase { + + public function setUp() : void + { + parent::setUp(); + + $this->_target = 17; + $this->_incoming = 18; + + $this->postDispatch('/cosmo/data-profile/copy-codif-confirm/id/' . $this->_target, + ['from' => Class_Cosmogramme_CodifImporter::FROM_PROFILE, + 'codif_types' => ['sorts', 'sections', 'locations'], + 'profile' => $this->_incoming]); + } + + + /** @test */ + public function profile17SortsShouldEqualsProfile18() { + $this->assertEquals($this->getTarget('sorts'), $this->getIncoming('sorts')); + } + + + /** @test */ + public function profile17SectionsShouldEqualsProfile18() { + $this->assertEquals($this->getTarget('sections'), $this->getIncoming('sections')); + } + + + /** @test */ + public function profile17LocationsShouldEqualsProfile18() { + $this->assertEquals($this->getTarget('locations'), $this->getIncoming('locations')); + } +} + + + + +class DataProfileControllerCodifsImporterSortsFromGlobals + extends DataProfileControllerCodifsImporterTestCase { + + protected $_expected = ['sorts_label' => ['Jeux', 'Politique'], + 'sorts_zone' => ['995$q', '995$q'], + 'sorts_mode' => ['=', '='], + 'sorts_value' => ['J', 'POL;P'], + 'sorts_whitespace' => ['0', '1']]; + + public function setUp() : void + { + parent::setUp(); + + $this->_target = 17; + + + $this->postDispatch('/cosmo/data-profile/copy-codif-confirm/id/' . $this->_target, + ['from' => Class_Cosmogramme_CodifImporter::FROM_GLOBALS, + 'codif_types' => ['sorts']]); + } + + + /** @test */ + public function profile17SortsShouldEqualsProfile18() { + $this->assertEquals($this->_expected, $this->getTarget('sorts')); + } + + + /** @test */ + public function profile17SectionsShouldBeEmpty() { + $this->assertEquals([], $this->getTarget('sections')); + } + + + /** @test */ + public function profile17LocationsShouldBeEmpty() { + $this->assertEquals([], $this->getTarget('locations')); + } +} + + + + +class DataProfileControllerCodifsImporterSectionsFromGlobals + extends DataProfileControllerCodifsImporterTestCase { + + protected $_expected = ['sections_label' => ['Jeunesse'], + 'sections_zone' => ['995$a'], + 'sections_mode' => ['='], + 'sections_value' => ['J'], + 'sections_whitespace' => ['0']]; + + public function setUp() : void + { + parent::setUp(); + + $this->_target = 17; + + + $this->postDispatch('/cosmo/data-profile/copy-codif-confirm/id/' . $this->_target, + ['from' => Class_Cosmogramme_CodifImporter::FROM_GLOBALS, + 'codif_types' => ['sections']]); + } + + + /** @test */ + public function profile17SectionsShouldEqualsProfile18() { + $this->assertEquals($this->_expected, $this->getTarget('sections')); + } +} + + + + +class DataProfileControllerCodifsImporterLocationsFromGlobals + extends DataProfileControllerCodifsImporterTestCase { + + protected $_expected = ['locations_label' => ['Étage', 'RDC'], + 'locations_zone' => ['995$b', '995$b'], + 'locations_mode' => ['=', '='], + 'locations_value' => ['1', '0'], + 'locations_whitespace' => ['1', '0']]; + + public function setUp() : void + { + parent::setUp(); + + $this->_target = 17; + + + $this->postDispatch('/cosmo/data-profile/copy-codif-confirm/id/' . $this->_target, + ['from' => Class_Cosmogramme_CodifImporter::FROM_GLOBALS, + 'codif_types' => ['locations']]); + } + + + /** @test */ + public function profile17LocationsShouldEqualsProfile18() { + $this->assertEquals($this->_expected, $this->getTarget('locations')); + } +} + + + + +class DataProfileControllerCodifsImporterAllFromGlobals + extends DataProfileControllerCodifsImporterTestCase { + + protected $_expected_sort = ['sorts_label' => ['Jeux', 'Politique'], + 'sorts_zone' => ['995$q', '995$q'], + 'sorts_mode' => ['=', '='], + 'sorts_value' => ['J', 'POL;P'], + 'sorts_whitespace' => ['0', '1']]; + + protected $_expected_sec = ['sections_label' => ['Jeunesse'], + 'sections_zone' => ['995$a'], + 'sections_mode' => ['='], + 'sections_value' => ['J'], + 'sections_whitespace' => ['0']]; + + protected $_expected_loc = ['locations_label' => ['Étage', 'RDC'], + 'locations_zone' => ['995$b', '995$b'], + 'locations_mode' => ['=', '='], + 'locations_value' => ['1', '0'], + 'locations_whitespace' => ['1', '0']]; + + public function setUp() : void + { + parent::setUp(); + + $this->_target = 17; + + + $this->postDispatch('/cosmo/data-profile/copy-codif-confirm/id/' . $this->_target, + ['from' => Class_Cosmogramme_CodifImporter::FROM_GLOBALS, + 'codif_types' => ['sorts', 'sections', 'locations']]); + } + + + /** @test */ + public function profile17SortsShouldEqualsProfile18() { + $this->assertEquals($this->_expected_sort, $this->getTarget('sorts')); + } + + + /** @test */ + public function profile17SectionsShouldEqualsProfile18() { + $this->assertEquals($this->_expected_sec, $this->getTarget('sections')); + } + + + /** @test */ + public function profile17LocationsShouldEqualsProfile18() { + $this->assertEquals($this->_expected_loc, $this->getTarget('locations')); + } +} + + + + +class DataProfileControllerCodifsImporterEmptySortsFromExistingProfile + extends DataProfileControllerCodifsImporterTestCase { + + protected $_expected_sort = ['sorts_label' => ['SortOne', 'SortTwo'], + 'sorts_zone' => ['995$b', '995$b'], + 'sorts_mode' => ['=', '*'], + 'sorts_value' => ['A', 'S'], + 'sorts_whitespace' => [1, 0]]; + + protected $_expected_sec = ['sections_label' => ['SecOne', 'SecTwo'], + 'sections_zone' => ['902$a', '995$k'], + 'sections_mode' => ['/', '='], + 'sections_value' => ['Disque', 'R WIC'], + 'sections_whitespace' => [0, 1]]; + + protected $_expected_loc = ['locations_label' => ['LocOne', 'LocTwo'], + 'locations_zone' => ['995$q', '995$q'], + 'locations_mode' => ['=', '='], + 'locations_value' => ['Disque', 'R;A'], + 'locations_whitespace' => [0, 0]]; + + public function setUp() : void + { + parent::setUp(); + + $this->_target = 18; + $this->_incoming = 17; + + $this->postDispatch('/cosmo/data-profile/copy-codif-confirm/id/' . $this->_target, + ['from' => Class_Cosmogramme_CodifImporter::FROM_PROFILE, + 'codif_types' => ['sorts', 'sections', 'locations'], + 'profile' => $this->_incoming]); + } + + + /** @test */ + public function emptyIncomingSortsShouldNotEraseExistingTarget() { + $this->assertEquals($this->_expected_sort, $this->getTarget('sorts')); + } + + + /** @test */ + public function emptyIncomingSectionsShouldNotEraseExistingTarget() { + $this->assertEquals($this->_expected_sec, $this->getTarget('sections')); + } + + + /** @test */ + public function emptyIncomingLocationsShouldNotEraseExistingTarget() { + $this->assertEquals($this->_expected_loc, $this->getTarget('locations')); + } +} + + + + +class DataProfileControllerCodifsImporterNothingFromExistingProfile + extends DataProfileControllerCodifsImporterTestCase { + + public function setUp() : void + { + parent::setUp(); + + $this->_target = 17; + $this->_incoming = 18; + + $this->postDispatch('/cosmo/data-profile/copy-codif-confirm/id/' . $this->_target, + ['from' => Class_Cosmogramme_CodifImporter::FROM_PROFILE, + 'codif_types' => [], + 'profile' => $this->_incoming]); + } + + + /** @test */ + public function wihtoutCodifTypeProvidedMessengerShouldContainNoTypeMessage() { + $this + ->assertFlashMessengerContentContains('Pas de type de règle fournie. Rien n\'a été importé'); + } +} + + + + + +class DataProfileControllerCodyCodifConfirmErrorsTest + extends DataProfileControllerCodifsImporterTestCase { + + public function setUp() : void { + parent::setUp(); + $this->dispatch('/cosmo/data-profile/copy-codif-confirm'); + } + + + /** @test */ + public function shouldRedirectToIndex() + { + $this->assertRedirectTo('/cosmo/data-profile/index'); + } + + + /** @test */ + public function flashMessengerContentShouldBeProfilDeDonneesWithError() { + $_flashnotifications = $this->_getFlashMessengerNotifications(); + $this->assertEquals('error', + reset($_flashnotifications)['notification']['status']); + } +} diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php index 092502fe63da5dc43ec258a9f5d50e10d9dcb67d..a8c2c3f807635f216244154ec63900e731fb6b1e 100644 --- a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php +++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php @@ -123,6 +123,12 @@ class Cosmo_DataProfileControllerIndexTest } + /** @test */ + public function secondTrShouldContainsLinkImportCodificationInProfile() { + $this->assertXPath('//table//tr[2]/td/a[contains(@href, "/cosmo/data-profile/copy-codif/id/56")]'); + } + + /** @test */ public function thirdTrShouldContainsNanook() { $this->assertXPathContentContains('//table//tr[3]/td', 'Nanook'); diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/EmplacementControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/EmplacementControllerTest.php index 43390fe19be4640734294d6b871532fd07e64840..e0d657a86bb008ae223244c61e5365768bc92402 100644 --- a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/EmplacementControllerTest.php +++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/EmplacementControllerTest.php @@ -32,6 +32,12 @@ abstract class Cosmo_EmplacementControllerTestCase extends CosmoControllerTestCa 'regles' => '995$x=' . Class_Codification_Rule::REMOVE_SPACE_PREFIX . '55', 'ne_pas_afficher' => 0]); + + $this->fixture(Class_CodifEmplacement::class, + ['id' => 19, + 'libelle' => 'Location without rule', + 'regles' => '', + 'ne_pas_afficher' => 0]); } } @@ -61,6 +67,12 @@ class Cosmo_EmplacementControllerIndexTest } + /** @test */ + public function codifWithoutRuleShouldNotBeDisplayed() { + $this->assertNotXPathContentContains('//td', 'Location without rule'); + } + + /** @test */ public function albumRuleShouldBePresent() { $this->assertXPathContentContains('//table//tr//td/ul//li', @@ -186,7 +198,7 @@ class Cosmo_EmplacementControllerAddTest extends Cosmo_EmplacementControllerTest /** @test */ public function defaultRuleShouldBePresent() { - $this->assertXpathContentContains('//script', '"values":{"rule_zone":["995"],"rule_field":["k"],"rule_sign":["\/"],"rule_values":["R"],"rule_space":["0"]}'); + $this->assertXpathContentContains('//script', '"values":{"rule_zone":["995"],"rule_field":["k"],"rule_sign":["\/"],"rule_values":["R"],"rule_space":[0]}'); } diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/GenreControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/GenreControllerTest.php index 74b6fec0e729631a754f171ba13310d2da872037..c5b36664e61b49fa3e8a138458efe4ea9a877ddc 100644 --- a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/GenreControllerTest.php +++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/GenreControllerTest.php @@ -25,23 +25,27 @@ abstract class Cosmo_GenreControllerTestCase extends CosmoControllerTestCase { public function setUp(): void { parent::setUp(); - - $this->fixture('Class_CodifGenre', + $this->fixture(Class_CodifGenre::class, ['id' => 5, 'libelle' => '01 Energie Enjeux', 'regles' => '995$q=0@@98']); - $this->fixture('Class_CodifGenre', + $this->fixture(Class_CodifGenre::class, ['id' => 7, 'libelle' => '01 Energie Politique', 'regles' => '995$q=0@@99']); - $this->fixture('Class_CodifGenre', + $this->fixture(Class_CodifGenre::class, ['id' => 9, 'libelle' => '01 Energie Vertes', 'regles' => '997$a=0@@11 998$b/1@@22;33 999$c*1@@44']); + + $this->fixture(Class_CodifGenre::class, + ['id' => 10, + 'libelle' => 'Sort without rules', + 'regles' => '']); } } @@ -77,6 +81,12 @@ class Cosmo_GenreControllerIndexTest extends Cosmo_GenreControllerTestCase { } + /** @test */ + public function codifWithoutRuleShouldNotBeDisplayed() { + $this->assertNotXPathContentContains('//table//tr//td', 'Sort without rules'); + } + + /** @test */ public function energieVertesReglesShouldBeInTable() { $this->assertXPathContentContains('//table//tr//td/ul//li', @@ -121,7 +131,7 @@ class Cosmo_GenreControllerEditTest extends Cosmo_GenreControllerTestCase { /** @test */ public function reglesValueShouldBe995DollarQEquals99WithoutSpace() { - $this->assertXpathContentContains('//script', '"rule_zone":["995"],"rule_field":["q"],"rule_sign":["="],"rule_values":["99"],"rule_space":["0"]'); + $this->assertXpathContentContains('//script', '"rule_zone":["995"],"rule_field":["q"],"rule_sign":["="],"rule_values":["99"],"rule_space":[0]'); } } diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/SectionControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/SectionControllerTest.php index f7224f758974d97f1bd01e6386ee430dd59f4a63..e6e1729183b06a23d447636d29e4e53e166537f2 100644 --- a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/SectionControllerTest.php +++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/SectionControllerTest.php @@ -25,16 +25,20 @@ abstract class Cosmo_SectionControllerTestCase extends CosmoControllerTestCase { public function setUp(): void { parent::setUp(); - - $this->fixture('Class_CodifSection', + $this->fixture(Class_CodifSection::class, ['id' => 5, 'libelle' => '01 Energie Enjeux', 'regles' => '995$q=98']); - $this->fixture('Class_CodifSection', + $this->fixture(Class_CodifSection::class, ['id' => 7, 'libelle' => '01 Energie Politique', 'regles' => '995$q=99']); + + $this->fixture(Class_CodifSection::class, + ['id' => 8, + 'libelle' => 'Section without rules', + 'regles' => '']); } } @@ -70,6 +74,12 @@ class Cosmo_SectionControllerIndexTest extends Cosmo_SectionControllerTestCase { } + /** @test */ + public function codifWithoutRuleShouldNotBeDisplayed() { + $this->assertNotXPathContentContains('//table//tr//td', 'Section without rules'); + } + + /** @test */ public function editEnergiePolitiqueShouldBePresent() { $this->assertXPath('//table//tr//td//a[contains(@href, "/cosmo/section/edit/id/7")]'); diff --git a/cosmogramme/css/form.css b/cosmogramme/css/form.css index 8cad5ee477adc16b2b11c43389024578e44a2d5b..3210f023e01abf49d0ad9a43383858ba9e9f3924 100644 --- a/cosmogramme/css/form.css +++ b/cosmogramme/css/form.css @@ -1,59 +1,59 @@ div.form { - margin-bottom:10px; + margin-bottom:10px; } span.form { - background-color:#FFFFCF; - color:#B73901; - margin-top:15px; - font-weight:bold; + background-color:#FFFFCF; + color:#B73901; + margin-top:15px; + font-weight:bold; } table.form { - width:100%; - border:1px solid; - border-color:#E0E0E0; - background-color:#FFFFCF; + width:100%; + border:1px solid; + border-color:#E0E0E0; + background-color:#FFFFCF; } th.form { - background-color:#E9F6A7; - color:#003687; - font-weight:bold; - border: none; - padding-top:7px; - padding-bottom:7px; + background-color:#E9F6A7; + color:#003687; + font-weight:bold; + border: none; + padding-top:7px; + padding-bottom:7px; } td.form { - border: none; - background-color:#FFFFCF; - padding-top:0px; - padding-bottom:5px; - height:10px; + border: none; + background-color:#FFFFCF; + padding-top:0px; + padding-bottom:5px; + height:10px; } td.form_milieu { - border: none; - background-color:#FFFFCF; - padding-top:0px; - padding-bottom:5px; - height:30px; - vertical-align:middle; + border: none; + background-color:#FFFFCF; + padding-top:0px; + padding-bottom:5px; + height:30px; + vertical-align:middle; } td.form_first { - border: none; - background-color:#FFFFCF; - padding-top:5px; - padding-bottom:5px; - height:10px; + border: none; + background-color:#FFFFCF; + padding-top:5px; + padding-bottom:5px; + height:10px; } form { - margin:0px; + margin:0px; } form.form { @@ -69,4 +69,8 @@ form label { text-align: right; width: 100%; display: inline-block; -} \ No newline at end of file +} + +.dropdown { + min-height: 30px; +} diff --git a/cosmogramme/php/classes/classe_notice_integration.php b/cosmogramme/php/classes/classe_notice_integration.php index 6a98fb6f65556dfe50b66e9fdba742e505ca0e8e..52ad5d1f372625d821a57967a7baef7d29a29a96 100644 --- a/cosmogramme/php/classes/classe_notice_integration.php +++ b/cosmogramme/php/classes/classe_notice_integration.php @@ -513,7 +513,8 @@ class notice_integration { $this->notice_sgbd->add_field('995', ' ', $table_champs); $this->notice_sgbd->update(); - $this->traiteNotice($this->notice_sgbd->getFullRecord(), new notice_unimarc); + $this->traiteNotice($this->notice_sgbd->getFullRecord(), + new notice_unimarc($this->id_bib)); $this->flag_koha = false; } @@ -815,9 +816,10 @@ class notice_integration { * we can have one file with items for different libraries. We use "annexe" codification to find * to put each item in the library it belongs to. **/ - if ($exemplaire->hasAnnexe() && ($annexe = CodifAnnexeCache::getInstance()->find($ex['annexe']))) { - $exemplaire->setIdBib($annexe->getIdBib()); - } + if ($exemplaire->hasAnnexe() + && ($annexe = Class_CodifAnnexe::find($exemplaire->getAnnexe()))) + $exemplaire + ->setIdBib($annexe->getIdBib()); $exemplaires []= $exemplaire; } diff --git a/cosmogramme/php/classes/classe_unimarc.php b/cosmogramme/php/classes/classe_unimarc.php index e3ec07847a50277b8dad96f0a5b0e1c949506be5..d1a3b3d06941012cde2c2fed29c89410da3b1283 100644 --- a/cosmogramme/php/classes/classe_unimarc.php +++ b/cosmogramme/php/classes/classe_unimarc.php @@ -100,6 +100,7 @@ class notice_unimarc extends iso2709_record if ( ! $decode_string) $this->profil['accents'] = 0; + $this->_codif_rules->setDataProfile($this->profil); $this->setNotice($data, $this->profil['accents']); $this->_fluent = null; return true; @@ -261,6 +262,7 @@ class notice_unimarc extends iso2709_record $counter = count($notice["exemplaires"]); for($i=0; $i <$counter; $i++) { $exemplaire = $notice["exemplaires"][$i]; + if (isset($exemplaire["section"]) && $exemplaire["section"]) $notice["sections"][]=$exemplaire["section"]; @@ -269,8 +271,8 @@ class notice_unimarc extends iso2709_record if(isset($exemplaire["genre"]) && $exemplaire["genre"]) $notice["genres"][]=$exemplaire["genre"]; - elseif (isset($ret['genre']) && $ret['genre'] !== []) - $notice["exemplaires"][$i]["genre"] = $ret["genre"][0]; + elseif (isset($ret['genre']) && !empty($ret['genre'])) + $notice["exemplaires"][$i]["genre"] = reset($ret["genre"]); if (!$notice['cote'] && isset($exemplaire['cote']) && $exemplaire['cote']) $notice['cote']=$exemplaire['cote']; @@ -617,11 +619,13 @@ class notice_unimarc extends iso2709_record $ex['ignore_exemplaire'] = true; } - if ($champ_annexe == $champ['code'] ) { - $annexe = CodifAnnexeCache::getInstance()->find($champ['valeur']); + if ( $champ_annexe == $champ['code'] ) { + $annexe = Class_CodifAnnexe::findByCodeAndBib($champ['valeur'] ?? '', + $this->_id_bib ?? 0); + if ($annexe && !$annexe->isVisible()) $ex['ignore_exemplaire'] = true; - $ex['annexe'] = ($annexe) ? $annexe->getCode() : $champ['valeur']; + $ex['annexe'] = ($annexe) ? $annexe->getId() : $champ['valeur']; } if ($champ_availability == $champ['code'] ) @@ -791,7 +795,9 @@ class notice_unimarc extends iso2709_record return; } - $ex["annexe"] = $champ["valeur"]; + $ex["annexe"] = ($annexe = Class_CodifAnnexe::findByCodeAndBib($champ["valeur"], $this->id_bib ?? 0)) + ? $annexe->getId() + : $champ['valeur']; return; } @@ -920,9 +926,13 @@ class notice_unimarc extends iso2709_record if (($champ["code"] == "9") && (0 === strpos($champ['valeur'], 'locdoc_codage_import:'))){ - $ex['annexe'] = trim(str_replace('locdoc_codage_import:', - '', - $champ['valeur'])); + $annexe_code = trim(str_replace('locdoc_codage_import:', + '', + $champ['valeur'])); + $ex['annexe'] = ($annexe = Class_CodifAnnexe::findByCodeAndBib($annexe_code, + $this->id_bib ?? 0)) + ? $annexe->getId() + : $annexe_code; return $ex; } @@ -1549,6 +1559,11 @@ class notice_unimarc extends iso2709_record } + public function getProfile() : array { + return $this->profil; + } + + private function getIdCodeExemplaire($type, $champ, $sous_champ, $valeur) { $champ = $champ . '$' . $sous_champ; return $this->_codif_rules->getCodifId($type, $champ, $valeur); diff --git a/cosmogramme/sql/patch/476.php b/cosmogramme/sql/patch/476.php new file mode 100644 index 0000000000000000000000000000000000000000..a453b43a8e6ef36aa2b6be922f4b6747f98b0199 --- /dev/null +++ b/cosmogramme/sql/patch/476.php @@ -0,0 +1,13 @@ +<?php +try { + (new Class_Migration_BranchFromCodeToIdNotice)->run(); +} catch (Exception $e) {} + +$adapter = Zend_Db_Table::getDefaultAdapter(); + +try +{ + $adapter->query('ALTER TABLE `codif_annexe` ADD INDEX IF NOT EXISTS (`id_bib`);'); +} +catch (Exception $e) +{} diff --git a/cosmogramme/sql/patch/patch_476.php b/cosmogramme/sql/patch/patch_476.php new file mode 100644 index 0000000000000000000000000000000000000000..a453b43a8e6ef36aa2b6be922f4b6747f98b0199 --- /dev/null +++ b/cosmogramme/sql/patch/patch_476.php @@ -0,0 +1,13 @@ +<?php +try { + (new Class_Migration_BranchFromCodeToIdNotice)->run(); +} catch (Exception $e) {} + +$adapter = Zend_Db_Table::getDefaultAdapter(); + +try +{ + $adapter->query('ALTER TABLE `codif_annexe` ADD INDEX IF NOT EXISTS (`id_bib`);'); +} +catch (Exception $e) +{} diff --git a/cosmogramme/tests/php/classes/AbonneIntegrationTest.php b/cosmogramme/tests/php/classes/AbonneIntegrationTest.php index 2eb977e7f7b57d2082a3544ff31ae8f0e6a48ff8..9a1e0939dbebb026e82b9bec350bbf2fb6c1da83 100644 --- a/cosmogramme/tests/php/classes/AbonneIntegrationTest.php +++ b/cosmogramme/tests/php/classes/AbonneIntegrationTest.php @@ -88,7 +88,6 @@ abstract class AbonneIntegrationXMLTestCase extends AbonneIntegrationTestCase { class AbonneIntegrationPipedASCIITest extends AbonneIntegrationASCIITestCase { - public $user; public function setUp(): void { @@ -98,7 +97,7 @@ class AbonneIntegrationPipedASCIITest extends AbonneIntegrationASCIITestCase { ['id' => 28, 'id_origine' => 'CHAMOIS', 'code' => 'CHAMWOIS', - 'id_bib' => 42]); + 'id_bib' => 2]); @@ -131,8 +130,8 @@ class AbonneIntegrationPipedASCIITest extends AbonneIntegrationASCIITestCase { /** @test */ - public function idSiteShouldBe42() { - $this->assertEquals(42, $this->user->getIdSite()); + public function idSiteShouldBe2() { + $this->assertEquals(2, $this->user->getIdSite()); } diff --git a/cosmogramme/tests/php/classes/KohaPeriodiquesTest.php b/cosmogramme/tests/php/classes/KohaPeriodiquesTest.php index 84e4def3ae873eada561e852d153a63e39ac1652..641dbc82ed792bd26354f84c62abba99a7e3aae9 100644 --- a/cosmogramme/tests/php/classes/KohaPeriodiquesTest.php +++ b/cosmogramme/tests/php/classes/KohaPeriodiquesTest.php @@ -699,35 +699,35 @@ class KohaPeriodiquesMatriculeAngesTest extends KohaPeriodiquesWithArticlesTestC /** @test */ - public function allMatriculeAngesSerialFacettesShouldContainsYCHYJR() { + public function allMatriculeAngesSerialFacettesShouldContainsY3() { $records = Class_Notice::findAllBy(['type_doc' => Class_TypeDoc::PERIODIQUE, 'clef_chapeau' => 'MATRICULE DES ANGES LE']); foreach($records as $index => $record) - $this->assertContains('YCHYJR', $record->getFacettes(), + $this->assertContains('Y3', $record->getFacettes(), 'at position: ' . $index . ', title: ' . $record->getTitrePrincipal()); } /** @test */ - public function allMatriculeAngesArticlesFacettesShouldContainsYCHYJR() { + public function allMatriculeAngesArticlesFacettesShouldContainsY3() { $records = Class_Notice::findAllBy(['type_doc' => Class_TypeDoc::PERIODIQUE_ARTICLE, 'clef_chapeau' => 'MATRICULE DES ANGES LE 202']); foreach($records as $index => $record) { $record->updateFacetsFromExemplaires(); - $this->assertContains('YCHYJR', $record->getFacettes(), + $this->assertContains('Y3', $record->getFacettes(), 'at position: ' . $index . ', title: ' . $record->getTitrePrincipal()); } } /** @test */ - public function titleRecordMatriculeFacettesShouldContainsYCHYJR() { + public function titleRecordMatriculeFacettesShouldContainsY3() { $title = Class_Notice::findFirstBy(['order' => 'id desc', 'type_doc' => Class_TypeDoc::PERIODIQUE_TITLE]); $title->updateFacetsFromExemplaires(); - $this->assertEquals('D800 Lfre Tper_title B1 YCHYJR HNRNR0001', + $this->assertEquals('D800 Lfre Tper_title B1 Y3 HNRNR0001', $title->getFacettes()); } } diff --git a/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php b/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php index 3e706d3c3e21ca31fc47d6b5e0cded38e2a8cb3c..17a83749dba6ab4a136f417d29a775c4ad3b0771 100644 --- a/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php +++ b/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php @@ -289,6 +289,19 @@ class KohaRecordIntegrationFacetPresseTest extends KohaRecordIntegrationTestCase 'rule_list_label_length' => [2] ]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 122, + 'id_bib' => 2, + 'id_origine' => 'MEDSTMAR', + 'code' => 'MEDSTMAR']); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 123, + 'id_bib' => 1, + 'id_origine' => 'MEDSTMAR', + 'code' => 'MEDSTMAR']); + Class_CosmoVar::setValueOf('mode_doublon', Class_CosmoVar::DOUBLE_SEARCH_ALPHA_KEY); $this->loadNotice('unimarc_koha_okapi'); } @@ -330,7 +343,7 @@ class KohaRecordIntegrationFacetPresseTest extends KohaRecordIntegrationTestCase /** @test */ public function facettesShouldContainsT2AndHANNE0001AndHMOIS0001AndJOUR0001() { - $this->assertEquals('HANNE0001 HMOIS0001 HJOUR0001 Lfre T2 B1 YMEDSTMAR HNRNR0001', + $this->assertEquals('HANNE0001 HMOIS0001 HJOUR0001 Lfre T2 B1 Y123 HNRNR0001', Class_Notice::find(1) ->updateFacetsFromExemplaires() ->getFacettes()); @@ -339,7 +352,7 @@ class KohaRecordIntegrationFacetPresseTest extends KohaRecordIntegrationTestCase /** @test */ public function facettesForRecord25ShouldContainsT2AndHANNE0001AndHMOIS0001() { - $this->assertEquals('HANNE0001 HMOIS0007 HJOUR0006 Lfre T2 B1 YMEDSTMAR HNRNR0001', + $this->assertEquals('HANNE0001 HMOIS0007 HJOUR0006 Lfre T2 B1 Y123 HNRNR0001', Class_Notice::find(25) ->updateFacetsFromExemplaires() ->getFacettes()); @@ -674,7 +687,7 @@ class KohaRecordIntegrationEscapableAnnexeCodesTest /** @test */ public function firstItemAnnexeShouldBeCHYJR() { - $this->assertEquals('CHYJR', $this->notice_data['exemplaires'][0]['annexe']); + $this->assertEquals(43, $this->notice_data['exemplaires'][0]['annexe']); } } diff --git a/cosmogramme/tests/php/classes/NoticeIntegrationAloesTest.php b/cosmogramme/tests/php/classes/NoticeIntegrationAloesTest.php index 827a279bc390eed7281fb0dfc2c7b4518db4a94d..ae441992ee3d431083c1835ba06c82bceee5b5a6 100644 --- a/cosmogramme/tests/php/classes/NoticeIntegrationAloesTest.php +++ b/cosmogramme/tests/php/classes/NoticeIntegrationAloesTest.php @@ -346,11 +346,13 @@ class NoticeIntegrationAloesDimancheALaPiscineTest extends NoticeIntegrationAloe 'regles' => '902$a=Roman']); $this->fixture(Class_CodifAnnexe::class, - ['id' => 1, + ['id' => 27, + 'code' => 'A', 'id_origine' => 'A', 'libelle' => 'Antibes', 'id_bib' => 4, - 'invisible' => 0]); + 'invisible' => 0]) + ->assertSave(); $this->onLoaderOfModel(Class_Exemplaire::class); $this->loadNotice("unimarc_dimanche_a_la_piscine"); @@ -426,7 +428,7 @@ class NoticeIntegrationAloesDimancheALaPiscineTest extends NoticeIntegrationAloe * @depends exemplaireShouldHaveBeenSavedForNotice1 */ public function exemplaireAnnexeShouldBeAntibes($exemplaire) { - $this->assertEquals('A', $exemplaire->getAnnexe()); + $this->assertEquals(27, $exemplaire->getAnnexe()); } diff --git a/cosmogramme/tests/php/classes/NoticeIntegrationCodificationRulesTest.php b/cosmogramme/tests/php/classes/NoticeIntegrationCodificationRulesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a6ef890fefd908d6f1de627031715372cadde381 --- /dev/null +++ b/cosmogramme/tests/php/classes/NoticeIntegrationCodificationRulesTest.php @@ -0,0 +1,412 @@ +<?php +/** + * Copyright (c) 2012-2023, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +require_once 'NoticeIntegrationTest.php'; + +abstract class NoticeIntegrationCodificationRulesTestCase extends NoticeIntegrationTestCase { + + public function setUp() : void + { + parent::setUp(); + + $this->_loadFixtures(); + + $this->loadNotice("unimarc_dimanche_a_la_piscine"); + } + + public function getProfilDonnees() { + return $this->fixture(Class_IntProfilDonnees::class, + ['id' => 102, + 'libelle' => 'Unimarc avec codifications', + 'accents' => Class_IntProfilDonnees::ENCODING_UTF8, + 'type_fichier' => Class_IntProfilDonnees::FT_RECORDS, + 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'attributs' => []]); + + } + + + protected function _loadFixtures() { + } +} + + + + +class NoticeIntegrationStandarCodificationRulesTest + extends NoticeIntegrationCodificationRulesTestCase { + + public function getProfilDonnees() { + return parent::getProfilDonnees() + ->setAttributs([['champ_code_barres' => 'f', + 'champ_cote' => 'k', + 'champ_type_doc' => 'r', + 'champ_annexe' => 'b', + 'champ_section' => 'v', + 'champ_emplacement' => 'r']]) + ->getRawAttributes(); + } + + + protected function _loadFixtures() { + $this->fixture(Class_CodifGenre::class, ['id' => 8, + 'libelle' => 'Roman', + 'regles' => '902$a/1@@Roman']); + + $this->fixture(Class_CodifSection::class, ['id' => 9, + 'libelle' => 'BD Adultes', + 'regles' => '995$v=0@@n']); + + $this->fixture(Class_CodifEmplacement::class, ['id' => 10, + 'libelle' => 'Exposition', + 'regles' => '995$r=1@@LIV']); + + $this->fixture(Class_CodifGenre::class, ['id' => 11, + 'libelle' => 'Unmatched sort', + 'regles' => '902$a/1@@empire']); + + $this->fixture(Class_CodifSection::class, ['id' => 12, + 'libelle' => 'Unmatched section', + 'regles' => '902$a/1@@empire']); + + $this->fixture(Class_CodifEmplacement::class, ['id' => 13, + 'libelle' => 'Unmatched location', + 'regles' => '902$a/1@@empire']); + } + + + /** @test */ + public function sortShouldBe8() { + $this->assertEquals(8, $this->notice_data['exemplaires'][0]['genre']); + } + + + /** @test */ + public function SectionShould9() { + $this->assertEquals(9, $this->notice_data['exemplaires'][0]['section']); + } + + + /** @test */ + public function locationShould10() { + $this->assertEquals(10, $this->notice_data['exemplaires'][0]['emplacement']); + } +} + + + + +class NoticeIntegrationDataProfileCodificationRulesTest + extends NoticeIntegrationCodificationRulesTestCase { + + protected + $_sortone, + $_sectiontwo, + $_loctwo; + + public function getProfilDonnees() { + return parent::getProfilDonnees() + ->setAttributs([['champ_code_barres' => 'f', + 'champ_cote' => 'k', + 'champ_type_doc' => 'r', + 'champ_annexe' => 'a', + 'champ_genre' => 'b', + 'champ_section' => 'k', + 'champ_emplacement' => 'q'], + 'sorts' => ['sorts_label' => ['SortOne', 'SortTwo', ''], + 'sorts_zone' => ['995$b', '995$b', ''], + 'sorts_mode' => ['=', '*', '='], + 'sorts_value' => ['A', 'S', ''], + 'sorts_whitespace' => [1, 0]], + 'sections' => ['sections_label' => ['SectionOne', 'SectionTwo'], + 'sections_zone' => ['902$a', '995$k'], + 'sections_mode' => ['/', '='], + 'sections_value' => ['Disque', 'R WIC'], + 'sections_whitespace' => [0, 1]], + 'locations' => ['locations_label' => ['LocOne', 'LocTwo'], + 'locations_zone' => ['995$q', '995$q'], + 'locations_mode' => ['=', '='], + 'locations_value' => ['Disque', 'R;A'], + 'locations_whitespace' => [0, 0]]]) + ->getRawAttributes(); + } + + + public function setUp() : void + { + parent::setUp(); + $this->_sortone = Class_CodifGenre::findFirstBy(['libelle' => 'SortOne']); + $this->_sectiontwo = Class_CodifSection::findFirstBy(['libelle' => 'SectionTwo']); + $this->_loctwo = Class_CodifEmplacement::findFirstBy(['libelle' => 'LocTwo']); + } + + + /** @test */ + public function sortOneCodoficationShouldBeCreated() { + $this->assertNotNull($this->_sortone); + } + + + /** @test */ + public function sectionTwoCodoficationShouldBeCreated() { + $this->assertNotNull($this->_sectiontwo); + } + + + /** @test */ + public function locTwoCodoficationShouldBeCreated() { + $this->assertNotNull($this->_loctwo); + } + + + /** @test */ + public function sortShouldBeSortOneId() { + $this->assertEquals($this->_sortone->getId(), $this->notice_data['exemplaires'][0]['genre']); + } + + + /** @test */ + public function sectionShouldBeSectionTwoId() { + $this->assertEquals($this->_sectiontwo->getId(), $this->notice_data['exemplaires'][0]['section']); + } + + + /** @test */ + public function locationShouldBeLocTwoId() { + $this->assertEquals($this->_loctwo->getId(), $this->notice_data['exemplaires'][0]['emplacement']); + } +} + + + + +class NoticeIntegrationDataProfileCodificationRulesWithExistingRulesTest + extends NoticeIntegrationCodificationRulesTestCase { + + public function getProfilDonnees() { + return parent::getProfilDonnees() + ->setAttributs([['champ_code_barres' => 'f', + 'champ_cote' => 'k', + 'champ_type_doc' => 'r', + 'champ_annexe' => 'b', + 'champ_section' => 'm', + 'champ_emplacement' => 'b'], + 'sorts' => ['sorts_label' => ['SortThree'], + 'sorts_zone' => ['902$a'], + 'sorts_mode' => ['=',], + 'sorts_value' => ['Roman'], + 'sorts_whitespace' => [1]], + 'sections' => ['sections_label' => ['SectionThree'], + 'sections_zone' => ['676$a'], + 'sections_mode' => ['='], + 'sections_value' => ['R'], + 'sections_whitespace' => [1]], + 'locations' => ['locations_label' => ['LocThree'], + 'locations_zone' => ['995$b'], + 'locations_mode' => ['='], + 'locations_value' => ['A'], + 'locations_whitespace' => [0]]]) + ->getRawAttributes(); + } + + + protected function _loadFixtures() { + $this->fixture(Class_CodifGenre::class, ['id' => 40, + 'libelle' => 'SortThree', + 'regles' => '901$b/1@@Doc']); + + $this->fixture(Class_CodifSection::class, ['id' => 41, + 'libelle' => 'SectionThree', + 'regles' => '995$m=1@@20140322']); + + $this->fixture(Class_CodifEmplacement::class, ['id' => 42, + 'libelle' => 'LocThree', + 'regles' => '995$b=1@@A']); + } + + + /** @test */ + public function sortOneCodificationShouldNotBeDuplicated() { + $this->assertCount(1, Class_CodifGenre::findAllBy(['libelle' => 'SortThree'])); + } + + + /** @test */ + public function sortIdShouldBe40() { + $this->assertEquals(40, $this->notice_data['exemplaires'][0]['genre']); + } + + + /** @test */ + public function sectionTwoCodificationShouldNotBeDuplicated() { + $this->assertCount(1, Class_CodifSection::findAllBy(['libelle' => 'SectionThree'])); + } + + + /** @test */ + public function sectionIdShouldBe41() { + $this->assertEquals(41, $this->notice_data['exemplaires'][0]['section']); + } + + + /** @test */ + public function locTwoCodificationShouldNotBeDuplicated() { + $this->assertCount(1, Class_CodifEmplacement::findAllBy(['libelle' => 'LocThree'])); + } + + + /** @test */ + public function locationIdShouldBe42() { + $this->assertEquals(42, $this->notice_data['exemplaires'][0]['emplacement']); + } +} + + + + +class NoticeIntegrationDataProfileCodificationRulesWithFallBackOnDefaultRulesTest + extends NoticeIntegrationCodificationRulesTestCase { + + public function getProfilDonnees() { + return parent::getProfilDonnees() + ->setAttributs([['champ_code_barres' => 'f', + 'champ_cote' => 'k', + 'champ_type_doc' => 'r', + 'champ_annexe' => 'b', + 'champ_section' => 'v', + 'champ_emplacement' => 'r'], + 'sorts' => ['sorts_label' => ['Unmatched Sort'], + 'sorts_zone' => ['902$a'], + 'sorts_mode' => ['=',], + 'sorts_value' => ['Foo'], + 'sorts_whitespace' => [1]], + 'sections' => ['sections_label' => ['Unmatched Section'], + 'sections_zone' => ['676$a'], + 'sections_mode' => ['='], + 'sections_value' => ['U'], + 'sections_whitespace' => [1]], + 'locations' => ['locations_label' => ['Unmatched Loc'], + 'locations_zone' => ['995$b'], + 'locations_mode' => ['='], + 'locations_value' => ['H'], + 'locations_whitespace' => [0]]]) + ->getRawAttributes(); + } + + + protected function _loadFixtures() { + $this->fixture(Class_CodifGenre::class, ['id' => 43, + 'libelle' => 'SortThree', + 'regles' => '902$a=1@@Roman']); + + $this->fixture(Class_CodifSection::class, ['id' => 44, + 'libelle' => 'SectionThree', + 'regles' => '995$v=1@@n']); + + $this->fixture(Class_CodifEmplacement::class, ['id' => 45, + 'libelle' => 'LocThree', + 'regles' => '995$r=1@@LIV']); + } + + + /** @test */ + public function sortShouldBeSortOneId() { + $this->assertEquals(43, $this->notice_data['exemplaires'][0]['genre']); + } + + + /** @test */ + public function sectionShouldBeSectionTwoId() { + $this->assertEquals(44, $this->notice_data['exemplaires'][0]['section']); + } + + + /** @test */ + public function locationShouldBeLocTwoId() { + $this->assertEquals(45, $this->notice_data['exemplaires'][0]['emplacement']); + } +} + + + + +class NoticeIntegrationDataProfileCodificationRulesWithNoRulesTest + extends NoticeIntegrationCodificationRulesTestCase { + + public function getProfilDonnees() { + return parent::getProfilDonnees() + ->setAttributs([['champ_code_barres' => 'f', + 'champ_cote' => 'k', + 'champ_type_doc' => 'r', + 'champ_annexe' => 'b', + 'champ_section' => 'v', + 'champ_emplacement' => 'r'], + 'sorts' => ['sorts_label' => [], + 'sorts_zone' => [], + 'sorts_mode' => [], + 'sorts_value' => [], + 'sorts_whitespace' => []], + 'sections' => ['sections_label' => [], + 'sections_zone' => [], + 'sections_mode' => [], + 'sections_value' => [], + 'sections_whitespace' => []], + 'locations' => ['locations_label' => [], + 'locations_zone' => [], + 'locations_mode' => [], + 'locations_value' => [], + 'locations_whitespace' => []]]) + ->getRawAttributes(); + } + + + protected function _loadFixtures() { + $this->fixture(Class_CodifGenre::class, ['id' => 43, + 'libelle' => 'SortThree', + 'regles' => '902$a=1@@Roman']); + + $this->fixture(Class_CodifSection::class, ['id' => 44, + 'libelle' => 'SectionThree', + 'regles' => '995$v=1@@n']); + + $this->fixture(Class_CodifEmplacement::class, ['id' => 45, + 'libelle' => 'LocThree', + 'regles' => '995$r=1@@LIV']); + } + + + /** @test */ + public function sortShouldBeSortOneId() { + $this->assertEquals(43, $this->notice_data['exemplaires'][0]['genre']); + } + + + /** @test */ + public function sectionShouldBeSectionTwoId() { + $this->assertEquals(44, $this->notice_data['exemplaires'][0]['section']); + } + + + /** @test */ + public function locationShouldBeLocTwoId() { + $this->assertEquals(45, $this->notice_data['exemplaires'][0]['emplacement']); + } +} diff --git a/cosmogramme/tests/php/classes/NoticeIntegrationTest.php b/cosmogramme/tests/php/classes/NoticeIntegrationTest.php index d6e939ca84eef3fb5f67a0835b8dcfbc5d47b4f8..1790ce614a893b920d14a9d0d1610f36609c1653 100644 --- a/cosmogramme/tests/php/classes/NoticeIntegrationTest.php +++ b/cosmogramme/tests/php/classes/NoticeIntegrationTest.php @@ -1476,6 +1476,11 @@ class NoticeIntegrationArchivesAlsaceTest extends NoticeIntegrationTestCase Class_CosmoVar::newInstanceWithId('unimarc_zone_matiere', ['valeur' => '600abcjxyz;601abcx;602ajxyz;605a;606ajxyz;607ajxyz;608ajxyz;610aejxyz;615amnx;616acfjxy;620abcdefghi']); + $this->fixture(Class_CodifAnnexe::class, ['id' => 99, + 'id_bib' => 1, + 'id_origine' => 'Bibliothèque des Dominicains', + 'code' => 'Bibliothèque des Dominicains']); + $this->loadNotice('unimarc_archives_alsace'); } @@ -1523,7 +1528,7 @@ class NoticeIntegrationArchivesAlsaceTest extends NoticeIntegrationTestCase /** @test */ public function facettesWithExemplairesShouldContainsM1AndM2AndD1() { - $this->assertEquals('D94438 A1 A2 M1 M2 Lfre T1 B1 YBibliothèque des Dominicains HNRNR0001', + $this->assertEquals('D94438 A1 A2 M1 M2 Lfre T1 B1 Y99 HNRNR0001', Class_Notice::find(1)->updateFacetsFromExemplaires()->getFacettes()); } } diff --git a/library/Class/Catalogue.php b/library/Class/Catalogue.php index 5e8970111f08e41c0dd4981fda2ee2dcf3d82235..973e70ab5c529bc4a70e07fd41f3e452526e0305 100644 --- a/library/Class/Catalogue.php +++ b/library/Class/Catalogue.php @@ -296,7 +296,7 @@ class Class_Catalogue extends Storm_Model_Abstract protected function _addThesaurusNovelty(array $multifacets) : array { - foreach(array_filter(explode(';', ($this->getThesaurusNovelty() ?? ''))) as $id) + foreach(array_filter(explode(';', ($this->_getThesaurusNovelty() ?? ''))) as $id) $multifacets[] = Class_CodifThesaurus::CODE_FACETTE . $id; return $multifacets; @@ -625,7 +625,7 @@ class Class_Catalogue extends Storm_Model_Abstract } - public function getThesaurusNovelty() { + protected function _getThesaurusNovelty() { if (!$this->getNouveaute()) return null; @@ -644,10 +644,11 @@ class Class_Catalogue extends Storm_Model_Abstract Class_CodifThesaurus::collectForModelsUnderFixed('LibraryNovelty', $models, $collector); - $parts = array_filter(explode(';', $this->getAnnexe())); - $models = array_filter(array_map( - fn($code) => Class_CodifAnnexe::findFirstBy(['code' => (string)$code]), - $parts)); + $models = []; + if ($parts = array_filter(explode(';', $this->getAnnexe()))) + $models = Class_CodifAnnexe::query() + ->in('id_annexe', $parts) + ->fetchAll(); Class_CodifThesaurus::collectForModelsUnderFixed('AnnexeNovelty', $models, $collector); diff --git a/library/Class/CodifAnnexe.php b/library/Class/CodifAnnexe.php index f6570a67627cbec2b00eab5cfb97a3447e1ca0ee..75507a01fe7262bb694fa075f1f5d01361ee8fb1 100644 --- a/library/Class/CodifAnnexe.php +++ b/library/Class/CodifAnnexe.php @@ -24,61 +24,170 @@ class CodifAnnexeLoader extends Storm_Model_Loader { use Trait_Translator, Trait_FacetableLoader; - public function findAllByPickup() { - return Class_CodifAnnexe::findAllBy(['no_pickup' => '0', - 'order' => 'libelle']); + protected array $_annexe_by_code_id_bib_service_cache; + protected array $_annexe_by_code_cache; + protected array $_annexe_by_id_bib_cache; + protected array $_annexes_by_id_bibs_cache; + + + public function reset(): self + { + unset($this->_annexe_by_code_id_bib_service_cache); + unset($this->_annexes_by_id_bibs_cache); + unset($this->_annexe_by_code_cache); + unset($this->_annexe_by_id_bib_cache); + return $this; + } + + + public function findAllByPickup(): array + { + return Class_CodifAnnexe::query() + ->select(['code', 'libelle']) + ->eq('no_pickup', '0') + ->order('libelle') + ->fetchAll(); } - public function findLibelleByCode($code) { + public function findLibelleByCode($code) + { return ($annexe = $this->findByCode($code)) ? $annexe->getLibelle() : ''; } - public function findByCode($code) { - if ($annexe = Class_CodifAnnexe::findFirstBy(['code' => $code])) - return $annexe; + public function findIdBibByCodeAndBib(string $code, int $id_bib) : int + { + return ($annexe = $this->findByCodeAndBib($code, $id_bib)) + ? $annexe->getIdBib() + : $id_bib; + } + + + public function findByCodeAndBib(?string $code, + ?int $id_bib = 0, + ?string $service = ''): ?Class_CodifAnnexe + { + $key = ($code ?? '') + . $id_bib + . $service; + + if ( isset($this->_annexe_by_code_id_bib_service_cache[$key])) + return $this->_annexe_by_code_id_bib_service_cache[$key]; + + if ($id_bib && $annexe = Class_CodifAnnexe::findFirstBy(['code' => $code, 'id_bib' => $id_bib])) + return $this->_annexe_by_code_id_bib_service_cache[$key] = $annexe; - return Class_CodifAnnexe::findFirstBy(['id_origine' => $code]); + if ($service && $annexe = $this->_findByCodeAndService($code ?? '', $service)) + return $this->_annexe_by_code_id_bib_service_cache[$key] = $annexe; + + return $this->_annexe_by_code_id_bib_service_cache[$key] = Class_CodifAnnexe::findByCode($code); + } + + + public function findByCodeAndCurrentUser(?string $code) : ?Class_CodifAnnexe + { + if (!($user = Class_Users::getIdentity())) + return $this->findByCode($code); + + return $this->findByCodeAndBib($code, $user->getIdIntBib()); + } + + + protected function _findByCodeAndService(string $code, string $service) : ?Class_CodifAnnexe + { + $codifs_selected = Class_CodifAnnexe::findAllBy(['code' => $code]); + foreach ($codifs_selected as $codif) + if (($int_bib = Class_IntBib::find($codif->getIntBibId())) + && ($int_bib->getUrlServer() == $service)) + return $codif; + + return null; + } + + + public function findByCode($code) { + $key = is_array($code) ? implode($code) : (string) $code; + return $this->_annexe_by_code_cache[$key] ??= + (Class_CodifAnnexe::findFirstBy(['code' => $code]) + ?? Class_CodifAnnexe::findFirstBy(['id_origine' => $code])); } - public function getMultiOptions() { + public function getMultiOptions(?Closure $callback = null): array + { + if ( ! $callback) + $callback = fn($annexe) => $annexe->getId(); + $annexes = Class_CodifAnnexe::findAllBy(['invisible' => 0, 'order' => 'libelle']); $options = ['' => $this->_('tous')]; + foreach($annexes as $annexe) - $options[$annexe->getCode()] = $annexe->getLibelle(); + $options[$callback($annexe)] = $annexe->getLibelle(); return $options; } - public function getMultiOptionsFacets() { - $multi_options_facets = []; - $annexes = ($annex_ids = array_filter(array_keys($this->getMultiOptions()))) - ? Class_CodifAnnexe::findAllBy(['id_annexe' => $annex_ids]) - : []; + public function getMultiOptionsFacets(): array + { + return $this->getMultiOptions(fn($annexe) => $annexe->getFacetCode()); + } - foreach ($annexes as $annexe) - $multi_options_facets[$annexe->getFacetCode()] = $annexe->getLabel(); - asort($multi_options_facets, SORT_NATURAL | SORT_FLAG_CASE); - array_unshift($multi_options_facets, $this->_('tous')); - return $multi_options_facets; + public function findFirstByLibrary(Class_Bib $library) : ?Class_CodifAnnexe + { + return Class_CodifAnnexe::findFirstBy(['id_bib' => $library->getId()]); } - public function findFirstByLibrary(Class_Bib $library) : ?Class_CodifAnnexe { - return Class_CodifAnnexe::findFirstBy(['id_bib' => $library->getId()]); + public function getLibrary(string $branch_id): ?Class_Bib + { + return ($annexe = Class_CodifAnnexe::find($branch_id)) + ? $annexe->getBib() + : null; + } + + + public function getLibraryLabelFromItem(Class_Exemplaire $item): string + { + if ( ! $annexe = $item->getAnnexe()) + return ''; + + return ($site = $this->find($annexe)) + ? $site->getLibelle() + : ''; + } + + + public function findByIdBib(int $id_bib): array + { + if (isset($this->_annexe_by_id_bib_cache[$id_bib])) + return $this->_annexe_by_id_bib_cache[$id_bib]; + + return $this->_annexe_by_id_bib_cache[$id_bib] = + Class_CodifAnnexe::findAllBy(['id_bib' => $id_bib]); } - protected function _criteriaOnQuery(Storm_Query $query, string $id): Storm_Query + public function findAllByIdBibs(array $id_bibs): array { - return $query->eq('code', addslashes($id)); + $key = implode('-', $id_bibs); + + if (isset($this->_annexes_by_id_bibs_cache[$key])) + return $this->_annexes_by_id_bibs_cache[$key]; + + if ($id_bibs && $annexes = Class_CodifAnnexe::query() + ->select(['code', 'libelle']) + ->not_eq('no_pickup', 1) + ->in('id_bib', $id_bibs) + ->fetchAll()) + return $this->_annexes_by_id_bibs_cache[$key] = $annexes; + + return $this->_annexes_by_id_bibs_cache[$key] = Class_CodifAnnexe::findAllByPickup(); } } @@ -96,6 +205,7 @@ class Class_CodifAnnexe extends Storm_Model_Abstract { $_loader_class = 'CodifAnnexeLoader', $_default_attribute_values = ['libelle' => '', 'id_bib' => 0, + 'code' => '', 'id_origine' => '', 'invisible' => 0, 'no_pickup' => 0, @@ -105,21 +215,33 @@ class Class_CodifAnnexe extends Storm_Model_Abstract { 'referenced_in' => 'id_bib'], 'int_bib' => ['through' => 'bib']]; - public function getMailIntBib() { + + public function getMailIntBib() + { return $this->hasIntBib() ? $this->getIntBib()->getMail() : ''; } - public function getLibraryLabel() { + public function getLibraryLabel() + { return $this->hasIntBib() ? $this->getIntBib()->getLabel() : ''; } - public function getLibraryId() { + public function getIntBibId() : int + { + return $this->hasIntBib() + ? $this->getIntBib()->getId() + : 0; + } + + + public function getBibId() : ?int + { return $this->hasBib() ? $this->getBib()->getId() : null; @@ -132,7 +254,7 @@ class Class_CodifAnnexe extends Storm_Model_Abstract { public function getFacetteIndex() { - return self::CODE_FACETTE . $this->getCode(); + return self::CODE_FACETTE . $this->getId(); } @@ -162,7 +284,7 @@ class Class_CodifAnnexe extends Storm_Model_Abstract { public function asFacet() { - return static::CODE_FACETTE . $this->getCode(); + return static::CODE_FACETTE . $this->getId(); } diff --git a/library/Class/CodifEmplacement.php b/library/Class/CodifEmplacement.php index fc1253c1d204e1d37968289c2bb7305ee7308f00..bc4303a0f43b5a9f86e1f4f3692279dba8439a25 100644 --- a/library/Class/CodifEmplacement.php +++ b/library/Class/CodifEmplacement.php @@ -20,16 +20,28 @@ */ + class Class_CodifEmplacementLoader extends Storm_Model_Loader { use Trait_FacetableLoader; - public function getLabel($id) + public function getLabel($id): string { return ($emplacement = Class_CodifEmplacement::find($id)) ? $emplacement->getLibelle() : ''; } + + + public function findOrCreateFromLabel(string $label): Class_CodifEmplacement + { + if ($emplacement = $this->findFirstBy(['libelle' => $label])) + return $emplacement; + + $emplacement = (new Class_CodifEmplacement())->setLibelle($label); + $emplacement->save(); + return $emplacement; + } } @@ -56,7 +68,6 @@ class Class_CodifEmplacement extends Storm_Model_Abstract public function validate() { $this->checkAttribute('libelle', '' != $this->getLibelle(), $this->_('Vous devez définir le libellé')); - $this->checkAttribute('regles', '' != $this->getRegles(), $this->_('Vous devez définir au moins une règle')); } diff --git a/library/Class/CodifSection.php b/library/Class/CodifSection.php index a187e4c6d06e2878673f5de57ee9d97713204eda..87b22d2d5a167d63d7d1c3e6c1fb717e9b11ea48 100644 --- a/library/Class/CodifSection.php +++ b/library/Class/CodifSection.php @@ -24,6 +24,15 @@ class Class_CodifSectionLoader extends Storm_Model_Loader { use Trait_Translator, Trait_FacetableLoader; + public function findOrCreateFromLabel(string $label) : Class_CodifSection { + if ($section = $this->findFirstBy(['libelle' => $label])) + return $section; + $section = (new Class_CodifSection())->setLibelle($label); + $section->save(); + return $section; + } + + public function labelsOfIds($ids) { if (empty($ids)) return new Storm_Model_Collection(); diff --git a/library/Class/Codification/DataProfileRule.php b/library/Class/Codification/DataProfileRule.php new file mode 100644 index 0000000000000000000000000000000000000000..c9918768edf7b1290c4b74bd5101b64b0357ec70 --- /dev/null +++ b/library/Class/Codification/DataProfileRule.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright (c) 2012-2023, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Class_Codification_DataProfileRule extends Class_Codification_Rule { + + public static function newInstance(string $zone = '', + string $operator = '', + int $with_space = 0, + string $values = '', + string $label = '') : Class_Codification_DataProfileRule { + + $values = array_unique(array_filter(explode(static::VALUE_SEPARATOR, + static::_formatValue($with_space, + $values)), + fn($value) => '' !== trim($value))); + + return $values + ? new static($zone, $operator, $values, $with_space, $label) + : static::nullinstance(); + } + + + public static function nullinstance() : Class_Codification_DataProfileRuleNull { + return new Class_Codification_DataProfileRuleNull; + } +} + + + + +class Class_Codification_DataProfileRuleNull extends Class_Codification_DataProfileRule { +} diff --git a/library/Class/Codification/Rule.php b/library/Class/Codification/Rule.php index 9f01c2c985137a91eaa8dc53c531d6d9e968a27d..21b3cd608c7f88b42cd9c3817fe5b51164406354 100644 --- a/library/Class/Codification/Rule.php +++ b/library/Class/Codification/Rule.php @@ -33,6 +33,7 @@ class Class_Codification_Rule { $_operator, $_with_space, $_values = [], + $_label, $_type, $_codif; @@ -57,11 +58,17 @@ class Class_Codification_Rule { } - public function __construct($zone, $operator, $values, $with_space) { + public function __construct(string $zone = '', + string $operator = '', + array $values = [], + int $with_space = 0, + string $label = '') + { $this->_zone = $zone; $this->_operator = $operator; $this->_values = $values; $this->_with_space = $with_space; + $this->_label = $label; } @@ -110,7 +117,13 @@ class Class_Codification_Rule { public function getCodif() { - return $this->_codif; + return $this->_codif ??= $this->createCodif(); + } + + + public function createCodif() : Storm_Model_Abstract { + $classname = 'Class_Codif' . ucfirst($this->_type); + return $classname::findOrCreateFromLabel($this->_label); } @@ -135,11 +148,21 @@ class Class_Codification_Rule { } - public function isGenre() { + public function isGenre() : bool { return Class_Codification_RulesHelper::TYPE_GENRE === $this->getType(); } + public function isSection() : bool { + return Class_Codification_RulesHelper::TYPE_SECTION === $this->getType(); + } + + + public function isLocation() : bool { + return Class_Codification_RulesHelper::TYPE_EMPLACEMENT === $this->getType(); + } + + public function getValuesAsString() { return implode(static::VALUE_SEPARATOR, array_unique($this->_values)); } @@ -192,7 +215,7 @@ class Class_Codification_Rule { return $this->_zone . $this->_getOperatorAsHumanRead() . $this->_getValuesAsHumanRead() - . ('1' === $this->getWithSpace() + . (1 === $this->getWithSpace() ? $this->_(' avec espace(s)') : $this->_(' sans espace(s)')); } diff --git a/library/Class/Codification/RulesHelper.php b/library/Class/Codification/RulesHelper.php index e16ca14b2d09c808c8f292dad6ba2928a7cc774e..75444f0ce4dfc07d89ecde6dffcc2792bfe593b5 100644 --- a/library/Class/Codification/RulesHelper.php +++ b/library/Class/Codification/RulesHelper.php @@ -25,16 +25,33 @@ class Class_Codification_RulesHelper { const TYPE_GENRE = 'genre', TYPE_SECTION = 'section', - TYPE_EMPLACEMENT = 'emplacement'; - - protected $_list_rules; + TYPE_EMPLACEMENT = 'emplacement', + ZONE_KEY = '_zone', + MODE_KEY = '_mode', + WS_KEY = '_whitespace', + VALUE_KEY = '_value', + LABEL_KEY = '_label', + DEFAULT_ITEM_FIELD = '995$0'; + + protected + $_list_rules, + $_profile_list_rules_cache, + $_data_profile; public function getCodifId($type, $zone_field, $value) { + $detect_closure = fn($codif_rule) => $codif_rule->isZoneContainsValue($zone_field, $value) + || $codif_rule->isZoneContainsValue(self::DEFAULT_ITEM_FIELD, $value); + + $detect = $this + ->_getProfileListRules() + ->detect($detect_closure); + + if ($detect && $id = $detect->getCodif()->getId()) + return $id; + $detect = $this ->_getListRules() - ->detect( - fn($codif_rule) => $codif_rule->isZoneContainsValue($zone_field, $value) - || $codif_rule->isZoneContainsValue('995$0', $value)); + ->detect($detect_closure); return $detect ? $detect->getCodif()->getId() @@ -43,18 +60,92 @@ class Class_Codification_RulesHelper { public function getCodifIdByGenre($notice_unimarc) { + $select_closure = fn($rule) => $rule->isGenre(); + + $inject_closure = fn($next_result, $rule) => $this->_extractFieldsValues($next_result, + $rule, + $notice_unimarc); + + $profile_list_rules = $this + ->_getProfileListRules() + ->select($select_closure) + ->injectInto([], $inject_closure); + + if (!empty(array_filter($profile_list_rules))) + return array_filter($profile_list_rules); + + $list_result = $this ->_getListRules() - ->select(fn($rule) => $rule->isGenre()) - ->injectInto([], - fn($next_result, $rule) => $this->_extractFieldsValues($next_result, - $rule, - $notice_unimarc)); + ->select($select_closure) + ->injectInto([], $inject_closure); return array_filter($list_result); } + public function _getProfileListRules() : Storm_Collection { + if (isset($this->_profile_list_rules_cache)) + return $this->_profile_list_rules_cache; + + $this->_profile_list_rules_cache = new Storm_Collection; + + foreach ([Class_Cosmogramme_CodifImporter::SORT_KEY, + Class_Cosmogramme_CodifImporter::SECTION_KEY, + Class_Cosmogramme_CodifImporter::LOCATION_KEY] as $type) + $this->_getProfileListRulesForType($type); + + return $this->_profile_list_rules_cache; + } + + + public function resetListRules() : self { + unset($this->_profile_list_rules_cache, + $this->_data_profile); + + return $this; + } + + + protected function _getProfileListRulesForType(string $type) : self { + if (!$profile_rules = $this->getDataProfileAttribute($type)) + return $this; + + $key = $type . '_label'; + + if ( ! isset($profile_rules[$key])) + return $this; + + foreach ($profile_rules[$key] as $i => $rule) + $this->_profile_list_rules_cache + ->add(Class_Codification_DataProfileRule::newInstance(...$this->_profileRuleFromIndex($i, $type, $profile_rules)) + ->setType($this->_ruleType($type))); + + return $this; + } + + + protected function _ruleType(string $type) : string { + if ($type == 'sorts') + return static::TYPE_GENRE; + + if ($type == 'sections') + return static::TYPE_SECTION; + + if ($type == 'locations') + return static::TYPE_EMPLACEMENT; + } + + + protected function _profileRuleFromIndex(int $index, string $type, array $rules) : array { + return [$rules[$type.static::ZONE_KEY][$index] ?? '', + $rules[$type.static::MODE_KEY][$index] ?? '', + $rules[$type.static::WS_KEY][$index] ?? 0, + $rules[$type.static::VALUE_KEY][$index] ?? '', + $rules[$type.static::LABEL_KEY][$index] ?? '']; + } + + public function _getListRules() { if ($this->_list_rules === null) $this->_init(); @@ -63,6 +154,17 @@ class Class_Codification_RulesHelper { } + public function setDataProfile(array $profile) : self { + $this->_data_profile = $profile; + return $this; + } + + + public function getDataProfileAttribute(string $key) : array { + return $this->_data_profile['attributs'][$key] ?? []; + } + + protected function _init() { $this->_list_rules = new Storm_Collection; diff --git a/library/Class/CommSigb.php b/library/Class/CommSigb.php index 0c8e4efe0db983d3c4ffe26031c24b0838dc9710..79b88da326d3a7955aa66154c385b84a7b511b51 100644 --- a/library/Class/CommSigb.php +++ b/library/Class/CommSigb.php @@ -81,12 +81,6 @@ class Class_CommSigb { if ($emplacement = $sigb_exemplaire->getEmplacement()) $exemplaire->setEmplacement($emplacement); - if (!$code_annexe = $sigb_exemplaire->getCodeAnnexe()) - return $exemplaire; - - if ($annexe = Class_CodifAnnexe::findFirstBy(['id_origine' => $code_annexe])) - $exemplaire->setIdBib($annexe->getIdBib()); - return $exemplaire; } @@ -151,6 +145,13 @@ class Class_CommSigb { if (($central_library_id = $this->_isHoldCentralizedAndGetCentralLibrary($user, $exemplaire)) !== 0) return $this->_centralizedHold($user, $exemplaire, $central_library_id); + if ( ! $this->SIGBConnect($user) ) + return $this->_error('Impossible de contacter le serveur de votre bibliothèque.'); + + if ( ! $exemplaire->canBeHeldBy($user) ) + return $this->_error('Vous ne pouvez pas réserver cet exemplaire !'); + + $reserver = function ($user, $sigb) use ($exemplaire, $code_annexe) { $result = $sigb->reserverExemplaire($user, $exemplaire, $code_annexe); @@ -171,10 +172,12 @@ class Class_CommSigb { } - protected function _isHoldCentralizedAndGetCentralLibrary(Class_Users $user, Class_Exemplaire $exemplaire ) :int { - return ($central_library = Class_CosmoVar::get('centralized_hold_mode')) - && ($user->getIdIntBib() != $central_library) - && ($exemplaire->getIdIntBib() != $user->getIdIntBib()) + protected function _isHoldCentralizedAndGetCentralLibrary(Class_Users $user, Class_Exemplaire $item ): int + { + if ( ! $central_library = Class_CosmoVar::get('centralized_hold_mode')) + return 0; + + return $item->shouldUseCentralizedHold($user) ? $central_library : 0; } @@ -191,14 +194,16 @@ class Class_CommSigb { && !($use_cardnumber = $user->getUseCardNumber())) return $this->_error($this->_('Réservation impossible : votre bibliothèque n\'autorise pas la réservation des documents de la bibliotheque centrale')); - $sigb_central = $this->SIGBCentralLibraryConnect(); + if (!$sigb_central = $this->_SIGBCentralLibraryConnect()) + return $this->_error( implode(BR, $this->getErrors()) ); + $result = $sigb_central->reserverExemplaire($user, $exemplaire, $central_library_id); if (true === ($result['statut'] ?? false)) return ($this->notifyCentralizedHold($user, $exemplaire, $central_library_id)->hasErrors()) ? $this->_error(implode("\n",$sigb_central->getErrors())) : $result; - return null; + return $this->_error($result['erreur']); } @@ -299,21 +304,32 @@ class Class_CommSigb { return $this->withUserAndSIGBDo($std_user, $prolonger); } - public function SIGBCentralLibraryConnect() { - if (!$int_bib = Class_IntBib::find(Class_CosmoVar::get('centralized_hold_mode'))) - return $this->_error($this->_('Pas de paramètres pour la bibliothèque centralisée')); - if (($sigb = $int_bib->getSIGBComm()) && $sigb->isConnected()) + + protected function _SIGBCentralLibraryConnect() : ?Class_WebService_SIGB_LibraryWrapper{ + if (!$int_bib = Class_IntBib::find(Class_CosmoVar::get('centralized_hold_mode'))){ + $this->addError($this->_('Pas de paramètres pour la bibliothèque centralisée')); + return null; + } + + if (($sigb = $int_bib->getSIGBComm()) + && $sigb->isConnected()) return $sigb; - return $this->_error($this->_("Une erreur de communication avec le serveur a fait échouer la requête. Merci de signaler ce problème à la bibliothèque.")); + + $this->addError($this->_("Une erreur de communication avec le serveur a fait échouer la requête. Merci de signaler ce problème à la bibliothèque.")); + return null; } public function SIGBConnect($user) { - if (null == $sigb = $user->getSIGBComm()) - return $this->_error($this->_('Communication SIGB indisponible')); + if (null == $sigb = $user->getSIGBComm()){ + $this->addError($this->_('Communication SIGB indisponible')); + return null; + } - if (!$sigb->isConnected()) - return $this->_error($this->_("Une erreur de communication avec le serveur a fait échouer la requête. Merci de signaler ce problème à la bibliothèque.")); + if (!$sigb->isConnected()){ + $this->addError($this->_("Une erreur de communication avec le serveur a fait échouer la requête. Merci de signaler ce problème à la bibliothèque.")); + return null; + } return $sigb; } @@ -328,8 +344,10 @@ class Class_CommSigb { function() use ($user): void { Class_WebService_SIGB_EmprunteurCache::newInstance()->remove($user); }); - $sigb = $this->SIGBConnect($user); - return (is_array($sigb)) ? $sigb : $closure($user, $sigb); + if ($sigb = $this->SIGBConnect($user)) + return $closure($user, $sigb); + + return $this->_error(implode(BR, $this->getErrors())); } diff --git a/library/Class/Cosmogramme/CodifImporter.php b/library/Class/Cosmogramme/CodifImporter.php new file mode 100644 index 0000000000000000000000000000000000000000..cf00a51db50b4f3d8c21c14f3290648cabddb6f2 --- /dev/null +++ b/library/Class/Cosmogramme/CodifImporter.php @@ -0,0 +1,153 @@ +<?php +/** + * Copyright (c) 2012-2023, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Class_Cosmogramme_CodifImporter { + use Trait_Translator, Trait_Errors; + + const SORT_KEY = 'sorts'; + const SECTION_KEY = 'sections'; + const LOCATION_KEY = 'locations'; + + const FROM_GLOBALS = 1; + const FROM_PROFILE = 2; + + protected + $_target_id, + $_incoming_id, + $_codif_types, + $_from, + $_target_attributes, + $_incoming_attributes; + + public function __construct(int $target_id = 0, + int $incoming_id = 0, + array $codif_types = [], + int $from = 0) { + $this->_target_id = $target_id; + $this->_incoming_id = $incoming_id; + $this->_codif_types = $codif_types; + $this->_from = $from; + + if (empty($this->_codif_types)) + return $this->addError($this->_('Pas de type de règle fournie. Rien n\'a été importé')); + + $this->_getTargetAttributes() + ->_getIncomingAttributes(); + } + + + public function import() : self { + if ($this->hasErrors()) + return $this; + + foreach ([static::SORT_KEY, static::SECTION_KEY, static::LOCATION_KEY] as $key) + $this->_incomingKeyToTarget($key); + + if (!$data_profile = Class_IntProfilDonnees::find($this->_target_id)) + return $this->addError($this->_('Profil de données inexistant')); + + $data_profile->setAttributs($this->_target_attributes) + ->save(); + + return $this; + } + + + protected function _incomingKeyToTarget(string $key) : self { + if (!in_array($key, $this->_codif_types)) + return $this; + + if ($rules = $this->_incoming_attributes[$key] ?? []) + $this->_target_attributes[$key] = $rules; + + return $this; + } + + + protected function _getTargetAttributes() : self { + if (null == $profile = Class_IntProfilDonnees::find($this->_target_id)) + return $this->addError($this->_('Profil de données cible inconnu')); + + $this->_target_attributes = $profile->getAttributsAsArray() ?? []; + + return $this; + } + + + protected function _getIncomingAttributes() : self { + if ($this->_from == static::FROM_GLOBALS) + return $this->_getGlobalCodifications(); + + if (null == $profile = Class_IntProfilDonnees::find($this->_incoming_id)) + return $this->addError($this->_('Profil de données inconnu')); + + $this->_incoming_attributes = $profile->getAttributsAsArray() ?? []; + + return $this; + } + + + protected function _getGlobalCodifications() : self { + $this->_incoming_attributes = + array_merge($this->_globalCodifsFor(Class_CodifGenre::findAllBy(['regles not' => '']), + 'sorts'), + $this->_globalCodifsFor(Class_CodifSection::findAllBy(['regles not' => '']), + 'sections'), + $this->_globalCodifsFor(Class_CodifEmplacement::findAllBy(['regles not' => '']) + ,'locations')); + return $this; + } + + + protected function _globalCodifsFor($codifs, string $prefix) : array { + $rules = []; + foreach ($codifs as $codif) + $rules = $this->_mergeRules($rules, $this->_extractRule($codif), $prefix); + + return $rules; + } + + + protected function _mergeRules(array $rules, array $rule, string $prefix) : array { + foreach (['_label', '_zone', '_mode', '_value', '_whitespace'] as $index => $key) + $rules[$prefix][$prefix . $key][] = $rule[$index]; + + return $rules; + } + + + protected function _extractRule($rule) : array { + $codif_rule = Class_Codification_DataProfileRule::newFrom($rule->getRegles()); + return [$rule->getLibelle(), + $this->_extractZone($codif_rule), + $codif_rule->getOperator(), + $codif_rule->getValuesAsString(), + $codif_rule->getWithSpace()]; + } + + + protected function _extractZone(Class_Codification_Rule $rule) : string { + return $rule->getField() + ? $rule->getZone() . '$' . $rule->getField() + : $rule->getZone(); + } +} diff --git a/library/Class/Cosmogramme/Integration/PhaseAbstract.php b/library/Class/Cosmogramme/Integration/PhaseAbstract.php index ec536306accca9c9c69eb13d724bd6c55f8b4761..2e560eab5ea06b50f360b98cb8ad213571cf95b9 100644 --- a/library/Class/Cosmogramme/Integration/PhaseAbstract.php +++ b/library/Class/Cosmogramme/Integration/PhaseAbstract.php @@ -51,6 +51,12 @@ abstract class Class_Cosmogramme_Integration_PhaseAbstract { } + protected function _resetCodificationRules() : self + { + return $this; + } + + protected function getSqlAdapter() { if(!$this->_sql_adapter) $this->_sql_adapter = Zend_Db_Table::getDefaultAdapter(); diff --git a/library/Class/Cosmogramme/Integration/PhaseNotice.php b/library/Class/Cosmogramme/Integration/PhaseNotice.php index cdfb68152b4cb03622de8765056a5d59cb029724..7fb1ae9960dcaab53c1003a60374bca7363dda27 100644 --- a/library/Class/Cosmogramme/Integration/PhaseNotice.php +++ b/library/Class/Cosmogramme/Integration/PhaseNotice.php @@ -33,6 +33,20 @@ class Class_Cosmogramme_Integration_PhaseNotice } + protected function _resetCodificationRules() : self { + if (null !== $this->_codification_rules) + $this->_codification_rules->resetListRules(); + + return $this; + } + + + protected function _initOne(){ + $this->_resetCodificationRules(); + parent::_initOne(); + } + + public function importRecord($data, $integration) { $integrator = new notice_integration(); $integrator->setCodificationRules($this->_codification_rules); diff --git a/library/Class/Cosmogramme/Integration/Record/Patron.php b/library/Class/Cosmogramme/Integration/Record/Patron.php index a53a45141e93261580d0011dc876dbb3bfd12c2d..39fbb323b275ba8ba44b0448bef0568f0db53de0 100644 --- a/library/Class/Cosmogramme/Integration/Record/Patron.php +++ b/library/Class/Cosmogramme/Integration/Record/Patron.php @@ -48,7 +48,9 @@ class Class_Cosmogramme_Integration_Record_Patron { $enreg = $this->prepareData($enreg); if ($library_code = $this->_known_fields->libraryCodeFrom($enreg)) { - $annexe = Class_CodifAnnexe::findFirstBy(['id_origine' => $library_code]); + $annexe = Class_CodifAnnexe::findByCodeAndBib($library_code, $this->_integration + ? $this->_integration->getIdBib() + : ''); $enreg['ID_SITE'] = $annexe ? $annexe->getIdBib() : $this->_integration->getIdBib(); } diff --git a/library/Class/Cosmogramme/Integration/SplitBySite.php b/library/Class/Cosmogramme/Integration/SplitBySite.php index 7cbb654599cad00d30c652150c5a9d5242b78868..9f236201f4aed6821abb7f338fd90822fadb1349 100644 --- a/library/Class/Cosmogramme/Integration/SplitBySite.php +++ b/library/Class/Cosmogramme/Integration/SplitBySite.php @@ -64,25 +64,30 @@ class Class_Cosmogramme_Integration_SplitBySite { $this->_logHash($this->_items_by_site, 'exemplaires'); $this->getLogger()->log(sprintf(' %d notices traitées au total', $count_processed)); + + $this->getFileSystem()->delete($file_path_to_split); + + $this->getLogger()->log(sprintf('Fichier %s supprimé', $file_path_to_split)); + return $this; } protected function _logTitle(string $sep_char, string $title, string $level) : self { - $this->getLogger()->log('\n'); + $this->getLogger()->log("\n"); $this->getLogger()->log(str_repeat($sep_char,50)); $this->getLogger()->log($title); $this->getLogger()->log(str_repeat($sep_char,50)); - $this->getLogger()->log(str_repeat('\n', $level)); + $this->getLogger()->log(str_repeat("\n", $level)); return $this; } protected function _logHash(array $hash, string $value_label) :self { - $this->_logTitle('-', sprintf('\t\t Statistiques %s', $value_label), 1); + $this->_logTitle('-', sprintf("\t\t Statistiques %s", $value_label), 1); foreach ($hash as $id_site => $count) - $this->getLogger()->log(sprintf(' site %s : %4d %s', $id_site,$count, $value_label)); + $this->getLogger()->log(sprintf(" site %s : %4d %s", $id_site,$count, $value_label)); return $this; } @@ -134,7 +139,7 @@ class Class_Cosmogramme_Integration_SplitBySite { $this->_items_by_site [$id_site] += count($zone995s); $new_record->update(); - $this->_siteFileAppend($id_site, $new_record->getFullRecord()); + $this->_siteFileAppend(trim($id_site), $new_record->getFullRecord()); return $this; } diff --git a/library/Class/Exemplaire.php b/library/Class/Exemplaire.php index c1533a34b67c2c250cde3510636defe1052903f7..6c94452096674c59df005151ebb2f9d61abfd422 100644 --- a/library/Class/Exemplaire.php +++ b/library/Class/Exemplaire.php @@ -20,17 +20,6 @@ */ class Class_ExemplaireLoader extends Storm_Model_Loader { - protected $_annexes_by_code = []; - - - public function getCachedCodifAnnexeByCode($code) { - // For cosmogramme integration performance. - if (!isset($this->_annexes_by_code[$code])) - $this->_annexes_by_code[$code] = Class_CodifAnnexe::findByCode($code); - return $this->_annexes_by_code[$code]; - } - - public function findFirstBySIGBOperation($user, $operation) { @@ -39,7 +28,7 @@ class Class_ExemplaireLoader extends Storm_Model_Loader { $params = $operation->getCodeBarre() ? ['code_barres' => $operation->getCodeBarre()] - : ['id_origine' => $operation->getNoNotice()]; + : ['id_origine' => $operation->getNoNotice()]; if (!array_filter($params)) return null; @@ -121,7 +110,7 @@ class Class_Exemplaire extends Storm_Model_Abstract { 'referenced_in' => 'id_origine'], 'int_bib' => [ 'model' => 'Class_IntBib', - 'referenced_in' => 'id_int_bib'], + 'referenced_in' => 'id_int_bib'], 'data_profile' => ['model' => 'Class_IntProfilDonnees', 'referenced_in' => 'id_data_profile'] @@ -148,8 +137,7 @@ class Class_Exemplaire extends Storm_Model_Abstract { 'shelf_key' => '', 'shelf_key_update_date' => '0000-00-00 00:00:00']; - protected - $_sigb_exemplaire; + protected $_sigb_exemplaire; public function incrementGroupCount() { @@ -213,7 +201,7 @@ class Class_Exemplaire extends Storm_Model_Abstract { $cote = $this->getCote(); if ( ! $ils_ws_item_cote = - $this->_withILSWsItemDo(fn($ils_ws_item) => $ils_ws_item->getCote())) + $this->_withILSWsItemDo(fn($ils_ws_item) => $ils_ws_item->getCote())) return $cote; return strlen($cote) > strlen($ils_ws_item_cote) @@ -222,10 +210,8 @@ class Class_Exemplaire extends Storm_Model_Abstract { } - public function getLibelleSite() { - if (null === ($site = Class_CodifAnnexe::findFirstBy(['code' => (string)$this->getAnnexe()]))) - return ''; - return $site->getLibelle(); + public function getLibelleSite() : string { + return Class_CodifAnnexe::getLibraryLabelFromItem($this); } @@ -395,7 +381,7 @@ class Class_Exemplaire extends Storm_Model_Abstract { public function updateAvailabilityAndLocationFromSIGBAndSaveIfNeeded() : self { if ( (! $sigb_exemplaire = $this->_withILSWsItemDo(fn($ils_ws_item) => $ils_ws_item)) - && $this->getIsAvailable()) { + && $this->getIsAvailable()) { $this->setIsAvailable(false)->save(); return $this; } @@ -406,14 +392,20 @@ class Class_Exemplaire extends Storm_Model_Abstract { $this->setUrlForCurrentUser($sigb_exemplaire->getUrlForCurrentUser()); $new_annexe = $this->getCodeAnnexe(); + $new_availability = $sigb_exemplaire->isDisponible(); if (($new_annexe == $this->getAnnexe()) && ($new_availability == $this->getIsAvailable())) return $this; + $annexe_id = ($annexe = Class_CodifAnnexe::findByCodeAndBib($new_annexe, $this->getIdBib())) + ? $annexe->getId() + : $new_annexe; + + $this - ->setAnnexe($new_annexe) + ->setAnnexe($annexe_id) ->setIsAvailable($new_availability) ->save(); @@ -448,16 +440,28 @@ class Class_Exemplaire extends Storm_Model_Abstract { } - public function getBibNumberFromIdOrigine() { - if ($this->getDataProfile() - && $this->getDataProfile()->isSerialFormatKoha() - && $this->getNotice()->isPeriodique() ) - return ($data = explode('-',$this->getIdOrigine())[0]) - ? $data - : null; + public function getBibNumberFromIdOrigine(): string + { + $id_origine = $this->getIdOrigine() ?? ''; + if ( ! $profile = $this->getDataProfile()) + return $id_origine; + + if ( ! $profile->isSerialFormatKoha()) + return $id_origine; - return $this->getIdOrigine(); + if ( ! $record = $this->getNotice()) + return $id_origine; + if ( ! $record->isPeriodique()) + return $id_origine; + + return $this->_getIdOrigineFirstPart(); + } + + + protected function _getIdOrigineFirstPart(): string + { + return explode('-', $this->getIdOrigine())[0] ?? ''; } @@ -488,8 +492,7 @@ class Class_Exemplaire extends Storm_Model_Abstract { public function getCodifAnnexe() { - return $this->getLoader() - ->getCachedCodifAnnexeByCode($this->getAnnexe()); + return Class_CodifAnnexe::find($this->getAnnexe()); } @@ -538,7 +541,7 @@ class Class_Exemplaire extends Storm_Model_Abstract { return null; if ( (null == ($ils_ws_item = $this->_getILSWsItemFromIntBibOrCache())) - || (! $ils_ws_item->isValid())) + || (! $ils_ws_item->isValid())) return null; return $callback($ils_ws_item); @@ -709,7 +712,7 @@ class Class_Exemplaire extends Storm_Model_Abstract { if ($emplacement = trim((string)$this->getEmplacement())) $facets []= Class_CodifEmplacement::CODE_FACETTE.$emplacement; - if ($annexe = trim((string)$this->getAnnexe())) + if ($annexe = trim((string) $this->getAnnexe())) $facets []= Class_CodifAnnexe::CODE_FACETTE.$annexe; if ($this->isDisponible(true)) @@ -724,7 +727,7 @@ class Class_Exemplaire extends Storm_Model_Abstract { if ($novelty = Class_CodifThesaurus::findForItemAnnexeNovelty($this)) $facets[] = $novelty; - return $facets; + return array_filter($facets); } @@ -741,7 +744,6 @@ class Class_Exemplaire extends Storm_Model_Abstract { public function requiresCalendarHold() : bool { - return (($intbib = $this->getIntBib()) && $intbib->isCommKoha() && (bool) $this->_withILSWsItemDo(fn($ils_ws_item) => $ils_ws_item->requiresCalendarHold())); @@ -761,6 +763,57 @@ class Class_Exemplaire extends Storm_Model_Abstract { } + protected function _isCentralizedCompatible(Class_Users $user): bool + { + if ( ! $central_library_id = Class_CosmoVar::get('centralized_hold_mode')) + return false; + + if ( ! $item_intbib = $this->getIdIntBib()) + return false; + + if ( ! $user_intbib = $user->getIntBib()) + return false; + + if ( $central_library_id != $item_intbib) + return false; + + return (bool) $user_intbib->getUseCardNumber(); + } + + + public function shouldUseCentralizedHold(Class_Users $user): bool + { + if ( ! $this->_isCentralizedCompatible($user)) + return false; + + return $this->getIntBib()->getUrlServer() != $user->getUrlServer(); + } + + + public function canBeHeldBy(Class_Users $user): bool + { + return ($server = $this->getUrlServer()) + && ($server == $user->getUrlServer()); + } + + + public function getUrlServer(): string + { + return ($int_bib = $this->getIntBib()) + ? $int_bib->getUrlServer() ?? '' + : ''; + } + + + public function canBeHeldFromCentralizedLibrary(): bool + { + if ( ! $central_library_id = Class_CosmoVar::get('centralized_hold_mode')) + return false; + + return $this->getIdIntBib() == $central_library_id; + } + + public function isFromKoha(): bool { return 1 === Class_IntBib::query() @@ -780,5 +833,14 @@ class Class_Exemplaire extends Storm_Model_Abstract { { $barcode = explode('-', $this->getCodeBarres()); return array_shift($barcode); + + } + + + public function annexeCode(): string + { + return ($annexe = Class_CodifAnnexe::find($this->getAnnexe())) + ? $annexe->getCode() + : ''; } } diff --git a/library/Class/Hold/Notify/User.php b/library/Class/Hold/Notify/User.php index 8144b6a0b066b036766e8cb326b31e9ff360f3a7..ba4f31f733db8142e9244c3ba2884e57a645a609 100644 --- a/library/Class/Hold/Notify/User.php +++ b/library/Class/Hold/Notify/User.php @@ -22,7 +22,7 @@ class Class_Hold_Notify_User extends Class_Hold_AbstractNotify { - protected string $_template_name = 'NOTIFICATION_TEMPLATE_NEW_RESERVATION_USER_LIBRARY'; + protected string $_template_name = 'NOTIFICATION_TEMPLATE_NEW_RESERVATION_USER'; public function __construct(Class_Users $user, Class_Exemplaire $item, string $annexe) diff --git a/library/Class/Hold/NotifyUser.php b/library/Class/Hold/NotifyUser.php index 5b8c5e46773351d9af211d7ace05842d9f66dc76..9a638d9d9d0259baec4ac1c2a3b7361bc5fd2851 100644 --- a/library/Class/Hold/NotifyUser.php +++ b/library/Class/Hold/NotifyUser.php @@ -24,7 +24,8 @@ class Class_Hold_NotifyUser extends Class_Hold_AbstractNotify { protected string $_template_name ='NOTIFICATION_TEMPLATE_NEW_RESERVATION'; public function getPickupLibraryData(string $annexe_code){ - return Class_CodifAnnexe::findFirstBy(['id_origine' => $annexe_code]); + return Class_CodifAnnexe::findByCodeAndBib($annexe_code, + $this->_item ? $this->_item->getIdBib() : ''); } diff --git a/library/Class/IntBib.php b/library/Class/IntBib.php index dcabea7f576223bbd514377670ebdeec6f2a8217..b3dad4afc8e59aa572a19fcb1b8a337e0f23690c 100644 --- a/library/Class/IntBib.php +++ b/library/Class/IntBib.php @@ -94,7 +94,9 @@ class IntBibLoader extends Storm_Model_Loader { public function findAllWithWebServices() { - return Class_IntBib::findAllBy(['comm_sigb' => Class_IntBib::allCommSigbCodes()]); + return Class_IntBib::query() + ->in('comm_sigb', Class_IntBib::allCommSigbCodes()) + ->fetchAll(); } @@ -136,8 +138,7 @@ class IntBibLoader extends Storm_Model_Loader { $combo = $this->_findAllWithPreRegistration(fn($int_bib) => $int_bib->isPreRegistrationNanookEnabled()) ->injectInto([], - function($combo, $library) - { + function($combo, $library) { $combo[$library->getId()] = $library->getLabel(); return $combo; }); @@ -658,9 +659,6 @@ class Class_IntBib extends Storm_Model_Abstract { public function getUseCardNumber() : string{ - if(!$this->isOrphee() ||!$this->isCommKoha()) - return ''; - $params = $this->getCommParamsAsArray(); return ($params['use_card_number'] ?? ''); } diff --git a/library/Class/IntBib/ForUrl.php b/library/Class/IntBib/ForUrl.php new file mode 100644 index 0000000000000000000000000000000000000000..1928399de47f6542ccc95b14ce4e24ab01735585 --- /dev/null +++ b/library/Class/IntBib/ForUrl.php @@ -0,0 +1,58 @@ +<?php +/** + * Copyright (c) 2012-2024, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Class_IntBib_ForUrl extends Class_IntBib_SingleSigb +{ + + public function intBibsForUrlServer(string $url_server): array + { + $rows = Class_IntBib::query() + ->select(['id_bib', 'sigb', 'comm_params']) + ->not_eq('sigb', Class_IntBib::SIGB_NONE) + ->fetchAll(); + $int_bibs = $this->_groupByAttributes($rows); + + $this->_unique_url = $this->_url(['url_serveur' => $url_server]); + + $ids = []; + foreach ($int_bibs as $id => $comm_params) + if ($id && $this->_isSameUrl($comm_params)) + $ids [] = $id; + + return $ids; + } + + + protected function _groupByAttributes(array $rows): array + { + $models = []; + + foreach ($rows as $row) { + $id = $row->getIdBib(); + + $models [$id] ??= []; + $models [$id][] = $row->getCommParams(); + } + + return $models; + } +} diff --git a/library/Class/IntBib/SingleSigb.php b/library/Class/IntBib/SingleSigb.php index f68e56d452ff2b5ded2880154aea35bfff632ec4..9f927d16f4a446739d52d2a5fe12485d1c781e56 100644 --- a/library/Class/IntBib/SingleSigb.php +++ b/library/Class/IntBib/SingleSigb.php @@ -29,7 +29,8 @@ class Class_IntBib_SingleSigb public function isSingle(): bool { $this->_unique_url = null; - $int_bibs = $this->_intBibs(); + $int_bibs = $this->_intBibs(Class_IntBib::query() + ->select(['sigb', 'comm_params'])); if ( ! $this->_isSizeValid($int_bibs)) return false; @@ -128,16 +129,22 @@ class Class_IntBib_SingleSigb } - protected function _intBibs(): array + protected function _intBibs(Storm_Query_Abstract $query): array { - $rows = Class_IntBib::query() - ->select(['sigb', 'comm_params']) + $rows = $query ->not_eq('sigb', Class_IntBib::SIGB_NONE) ->group('sigb') ->group('comm_params') ->fetchAll(); + return $this->_groupByAttributes($rows); + } + + + protected function _groupByAttributes(array $rows): array + { $models = []; + foreach ($rows as $row) { $sigb = $row->getSigb(); diff --git a/library/Class/IntProfilDonnees.php b/library/Class/IntProfilDonnees.php index d1d2f46f671af7768bbb5b000b6dd89c0cbe345e..819b61016312e392797d1709ac3bbf30eba76386 100644 --- a/library/Class/IntProfilDonnees.php +++ b/library/Class/IntProfilDonnees.php @@ -38,6 +38,13 @@ class IntProfilDonneesLoader extends Storm_Model_Loader { } + public function getLabel(?int $id_profile) : string { + return ($profile = $this->find($id_profile)) + ? $profile->getLibelle() + : ''; + } + + public function getItemFields() { return [Class_IntProfilDonnees::FIELD_ITEM_ZONE => '995', Class_IntProfilDonnees::FIELD_ITEM_BARCODE => '', @@ -1498,4 +1505,13 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract { return []; return $a; } + + + public function hasCodifRules(): bool + { + return (in_array($this->getFormat(), [Class_IntProfilDonnees::FORMAT_UNIMARC, + Class_IntProfilDonnees::FORMAT_UNIMARC_XML, + Class_IntProfilDonnees::FORMAT_MARC21]) + && $this->getTypeFichier() == Class_IntProfilDonnees::FT_RECORDS); + } } diff --git a/library/Class/Migration/BranchFromCodeToIdNotice.php b/library/Class/Migration/BranchFromCodeToIdNotice.php new file mode 100644 index 0000000000000000000000000000000000000000..c7657a5e8488dc43853da38a81bfa569eaaf5d20 --- /dev/null +++ b/library/Class/Migration/BranchFromCodeToIdNotice.php @@ -0,0 +1,180 @@ +<?php +/** + * Copyright (c) 2012-2024, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Class_Migration_BranchFromCodeToIdNotice +{ + use Trait_MemoryCleaner, Trait_Translator; + + const SEPCHAR = ';'; + + protected + $_items_done = [], + $_records_id_annexe = [], + $_adapter, + $_count = 0, + $_total = 0, + $_annexes = [], + $_elem_per_page = 1000, + $_field = '', + $_table = '', + $_separator = ''; + + + protected array $_annexes_cache = []; + + public function __construct() { + $this->_adapter = Zend_Db_Table::getDefaultAdapter(); + } + + + + public function run() + { + if ($this->_adapter->query("SELECT `clef` from `variables` WHERE `CLEF` = 'CODIFS_MIGRATED';")->fetchAll()) + return; + + $annexes = $this->_adapter->query("SELECT `id_annexe`, `code` from `codif_annexe`;")->fetchAll(); + + $this->_annexes = array_combine(array_map(fn($ann) => $ann['code'], + $annexes), + array_map(fn($ann) => $ann['id_annexe'], + $annexes)); + + Class_Notice::dropIndexMotsNotice(); + $this->_updateItemsAnnexes(); + $this->_emptyRecordsAnnexes(); + $this->_updateRecordsAnnexes(); + Class_Notice::createIndexMotsNotice(); + + $this->_table = 'catalogue'; + $this->_field = 'annexe'; + $this->_separator = ';'; + $this->_updateModelAnnexes(); + + $this->_table = 'album'; + $this->_field = 'annexes'; + $this->_separator = ' '; + $this->_updateModelAnnexes(); + + $this->_table = 'codif_type_doc'; + $this->_field = 'annexes'; + $this->_separator = ';'; + $this->_updateModelAnnexes(); + + $this->_table = 'bib_admin_profil'; + $this->_field = 'sel_annexe'; + $this->_separator = ';'; + $this->_updateModelAnnexes(); + + + $this->_adapter + ->query('insert into variables (`clef`, `valeur`) values ("CODIFS_MIGRATED", "1");'); + } + + + protected function _updateModelAnnexes(): void + { + $models = $this->_adapter->query(sprintf('SELECT DISTINCT(`%s`) FROM `%s`' + . ' WHERE `%s` > ""', + $this->_field, + $this->_table, + $this->_field)) + ->fetchAll(); + + foreach ($models as $model) + $this->_mapAnnexesCodeToID(trim($model[$this->_field])); + } + + + protected function _mapAnnexesCodeToID(string $annexes): void + { + if ( ! $annexes) + return; + + $new_annexes = []; + foreach (explode($this->_separator, $annexes) as $annexe) + $new_annexes[] = $this->_annexes[$annexe] ?? null; + + $this->_adapter->query(sprintf('UPDATE `%s` SET `%s` = "%s" WHERE `%s` = "%s"', + $this->_table, + $this->_field, + implode($this->_separator, array_filter($new_annexes)), + $this->_field, + $annexes)); + } + + + protected function _updateRecordsAnnexes(): void + { + foreach ($this->_records_id_annexe as $id_notice => $annexes_ids) + if ($annexes_ids = array_filter(array_unique($annexes_ids))) + $this->_adapter->query(sprintf("UPDATE notices set `facets` = CONCAT(`facets`, '%s'), `facettes` = CONCAT(`facettes`, '%s') WHERE id_notice = %d;", + ' F_' . implode(' F_', $annexes_ids), + ' ' . implode(' ', $annexes_ids), + $id_notice)); + } + + + protected function _updateItemsAnnexes(): void + { + foreach ($this->_annexes as $code => $id) + $this->_replaceFor($code, $id); + } + + + protected function _emptyRecordsAnnexes(): void + { + $this->_adapter->query("UPDATE notices set `facets` = CLEAN_SPACES(REGEXP_REPLACE(`facets`, '\\\\bF_Y[a-zA-Z0-9]*\\\\b', '')), `facettes` = CLEAN_SPACES(REGEXP_REPLACE(`facettes`, '\\\\bY[a-zA-Z0-9]*\\\\b', ''));"); + + } + + + protected function _replaceFor(string $code, int $id): void + { + if ( ! $code) + return; + + $not_in = $this->_items_done + ? ' AND id NOT IN (' . implode(',', $this->_items_done) . ')' + : ''; + + $items = $this->_adapter->query('SELECT id, id_notice FROM exemplaires WHERE `annexe` = \'' + . $code . '\'' . $not_in)->fetchAll(); + + $items_done = array_map(fn($item) => $item['id'], + $items); + $records_id = array_map(fn($item) => $item['id_notice'], + $items); + foreach ($records_id as $record_id) { + $this->_records_id_annexe [$record_id] ??= []; + $this->_records_id_annexe [$record_id] [] = 'Y' . $id; + } + + $sql = sprintf("UPDATE `exemplaires` SET `annexe` = '%s' WHERE `annexe` = '%s'%s;", + $id, + $code, + $not_in); + $this->_adapter->query($sql); + + $this->_items_done = array_merge($this->_items_done, $items_done); + } +} diff --git a/library/Class/MoteurRecherche/RecordRequest.php b/library/Class/MoteurRecherche/RecordRequest.php index 88067d8b88d46d69ba1d0fa24e8f59f827692de8..33e82ce839a53609a5c9b536a183d85782330af9 100644 --- a/library/Class/MoteurRecherche/RecordRequest.php +++ b/library/Class/MoteurRecherche/RecordRequest.php @@ -63,6 +63,8 @@ class Class_MoteurRecherche_RecordByIdSigbRequest protected $_id_sigb, $_id_site, + $_id_bib, + $_id_annexe, $_record_type, $_id_int_bib, $_error_message; @@ -72,6 +74,7 @@ class Class_MoteurRecherche_RecordByIdSigbRequest $this->_error_message = null; $this->_id_sigb = $request->getParam('id_sigb'); $this->_id_site = $request->getParam('id_site'); + $this->_id_bib = $request->getParam('id_bib'); $this->_id_int_bib = $request->getParam('id_int_bib'); $this->_record_type = $request->getParam('record_type'); @@ -81,11 +84,8 @@ class Class_MoteurRecherche_RecordByIdSigbRequest if (!$this->_id_sigb) $this->_error_message = $this->_('Paramètre id_sigb obligatoire'); - if (!$this->_id_site && !$this->_id_int_bib) - $this->_error_message = $this->_('Paramètre id_site obligatoire'); - - if ($this->_id_site && $this->_id_int_bib) - $this->_error_message = $this->_('Paramètre id_site et id_int_bib ne peuvent pas être renseignés en même temps'); + if (!$this->_id_site && !$this->_id_int_bib && !$this->_id_bib) + $this->_error_message = $this->_('Paramètre de site obligatoire'); return null !== $this->_error_message; } @@ -103,20 +103,30 @@ class Class_MoteurRecherche_RecordByIdSigbRequest protected function _findItem() : ?Class_Exemplaire { - $clauses = array_merge(($this->_id_int_bib - ? ['id_int_bib' => $this->_id_int_bib] - : ['id_int_bib not' => 0]), - ['id_origine' => $this->_id_sigb, - 'type' => $this->_record_type]); - - if (!$this->_id_site - || static::ALL_SITES === $this->_id_site) - return Class_Exemplaire::findFirstBy($clauses); - - return ($annex = Class_CodifAnnexe::findFirstBy(['id_origine' => $this->_id_site])) - ? Class_Exemplaire::findFirstBy(array_merge(['id_bib' => $annex->getIdBib()], - $clauses)) - : null; + $annex = null; + if ( $this->_id_site + && $this->_id_site != static::ALL_SITES + && (! $annex = Class_CodifAnnexe::find($this->_id_site))) + return null; + + $query = Class_Exemplaire::query() + ->eq('id_origine', $this->_id_sigb) + ->eq('type', $this->_record_type) + ->not_eq('id_int_bib', 0); + + if ( $annex ) + $query + ->eq('annexe', $annex->getId()); + + if ( $this->_id_bib ) + $query + ->eq('id_bib', $this->_id_bib); + + if ( $this->_id_int_bib ) + $query + ->eq('id_int_bib', $this->_id_int_bib); + + return $query->fetchFirst(); } } diff --git a/library/Class/Notice/Permalink.php b/library/Class/Notice/Permalink.php index ebbd28dc67d4ee0e64d560b59ff5cd7d1490e72e..7ff2e215f525f775702bd8fa5402bc4ac3d3be56 100644 --- a/library/Class/Notice/Permalink.php +++ b/library/Class/Notice/Permalink.php @@ -95,19 +95,23 @@ class Class_Notice_Permalink { return ''; if (!($id_sigb = $first_exemplaire->getIdOrigine()) - || !($id_int_bib = $first_exemplaire->getIdIntBib())) + || !($id_int_bib = $first_exemplaire->getIdIntBib()) + || !($id_annexe = $first_exemplaire->getAnnexe())) return ''; - $type = (Class_Notice::TYPE_BIBLIOGRAPHIC === $record->getType()) - ? [] - : ['type' => $record->getType()]; + $params = ['id_sigb' => $id_sigb]; + if ( $id_int_bib ) + $params['id_int_bib'] = $id_int_bib; + $params['id_site'] = $id_annexe ?:'*'; + + if (Class_Notice::TYPE_BIBLIOGRAPHIC === $record->getType()) + $params['record_type'] = $record->getType(); return Class_Url::relative(array_merge(['module' => 'opac', 'controller' => 'recherche', 'action' => 'viewnotice', - 'id_sigb' => $id_sigb, - 'id_int_bib' => $id_int_bib], - $type), null, true); + ], + $params), null, true); } diff --git a/library/Class/ProfilePrefs.php b/library/Class/ProfilePrefs.php index 1bfd60678b789faa9cc67030c794fa7adef8b093..5ff3f98faf72d046ec9056c5c0b568d9dd4ed10b 100644 --- a/library/Class/ProfilePrefs.php +++ b/library/Class/ProfilePrefs.php @@ -219,6 +219,24 @@ class Class_ProfilePrefs { } + public function getSections() : array { + return (new Class_ProfilePrefs_Codification_Section) + ->multiInputValuesFrom($this->_prefs); + } + + + public function getLocations() : array { + return (new Class_ProfilePrefs_Codification_Location) + ->multiInputValuesFrom($this->_prefs); + } + + + public function getSorts() : array { + return (new Class_ProfilePrefs_Codification_Sort) + ->multiInputValuesFrom($this->_prefs); + } + + public function addThumbsZoneField($zone, $field) { $this->_prefs = (new Class_ProfilePrefs_Thumbs) ->addZoneFieldInto($zone, $field, $this->_prefs); diff --git a/library/Class/ProfilePrefs/Codification.php b/library/Class/ProfilePrefs/Codification.php new file mode 100644 index 0000000000000000000000000000000000000000..8c6e8e743ce07df1b1f8f16b9e0ae96ea4215a10 --- /dev/null +++ b/library/Class/ProfilePrefs/Codification.php @@ -0,0 +1,71 @@ +<?php +/** + * Copyright (c) 2012-2023, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Class_ProfilePrefs_Codification { + use Trait_Translator; + + public function multiInputValuesFrom($prefs) { + return $this->extractFrom($prefs[static::PROFILE_NAME] ?? []); + } + + + public function multiInputFieldsDefinition() : array { + return [['name' => static::LABEL_KEY, + 'label' => $this->_('Libellé de la section')], + ['name' => static::ZONE_KEY, + 'label' => $this->_('Zone marc')], + ['name' => static::MODE_KEY, + 'label' => $this->_('Mode'), + 'type' => 'select', + 'options' => ['=' => $this->_('Égal'), + '/' => $this->_('Commence par'), + '*' => $this->_('Contient')]], + ['name' => static::VALUE_KEY, + 'label' => $this->_('Valeur(s), séparées par ;')], + ['name' => static::SPACE_KEY, + 'label' => $this->_('Avec espace'), + 'type' => 'checkbox']]; + } + + + public function extractFrom(array $datas) : array { + $labels = $datas[static::LABEL_KEY] ?? []; + $zones = $datas[static::ZONE_KEY] ?? []; + $modes = $datas[static::MODE_KEY] ?? []; + $values = $datas[static::VALUE_KEY] ?? []; + $spaces = $datas[static::SPACE_KEY] ?? []; + + $empties = []; + foreach ($labels as $k => $label) + if ('' === $label || '' === ($zones[$k] ?? '') || '' === ($values[$k] ?? '')) + $empties[] = $k; + + foreach($empties as $k) + unset($labels[$k], $zones[$k], $modes[$k], $values[$k], $spaces[$k]); + + return [static::LABEL_KEY => array_values($labels), + static::ZONE_KEY => array_values($zones), + static::MODE_KEY => array_values($modes), + static::VALUE_KEY => array_values($values), + static::SPACE_KEY => array_values($spaces)]; + } +} diff --git a/library/Class/ProfilePrefs/Codification/Location.php b/library/Class/ProfilePrefs/Codification/Location.php new file mode 100644 index 0000000000000000000000000000000000000000..167dd8f82ce0504ab06d29315155ec3e8732e7bb --- /dev/null +++ b/library/Class/ProfilePrefs/Codification/Location.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright (c) 2012-2023, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Class_ProfilePrefs_Codification_Location extends Class_ProfilePrefs_Codification { + + const + PROFILE_NAME = 'locations', + LABEL_KEY = 'locations_label', + ZONE_KEY = 'locations_zone', + MODE_KEY = 'locations_mode', + VALUE_KEY = 'locations_value', + SPACE_KEY = 'locations_whitespace'; +} diff --git a/library/Class/ProfilePrefs/Codification/Section.php b/library/Class/ProfilePrefs/Codification/Section.php new file mode 100644 index 0000000000000000000000000000000000000000..5c16795a3632c735db43468dba9945d0a6cee124 --- /dev/null +++ b/library/Class/ProfilePrefs/Codification/Section.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright (c) 2012-2023, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Class_ProfilePrefs_Codification_Section extends Class_ProfilePrefs_Codification { + + const + PROFILE_NAME = 'sections', + LABEL_KEY = 'sections_label', + ZONE_KEY = 'sections_zone', + MODE_KEY = 'sections_mode', + VALUE_KEY = 'sections_value', + SPACE_KEY = 'sections_whitespace', + SKIP_KEY = 'sections_skipitems'; +} diff --git a/library/Class/ProfilePrefs/Codification/Sort.php b/library/Class/ProfilePrefs/Codification/Sort.php new file mode 100644 index 0000000000000000000000000000000000000000..ca6a99aee9df1d8a00c2ee91d75c600b8666afa3 --- /dev/null +++ b/library/Class/ProfilePrefs/Codification/Sort.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright (c) 2012-2023, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Class_ProfilePrefs_Codification_Sort extends Class_ProfilePrefs_Codification { + + const + PROFILE_NAME = 'sorts', + LABEL_KEY = 'sorts_label', + ZONE_KEY = 'sorts_zone', + MODE_KEY = 'sorts_mode', + VALUE_KEY = 'sorts_value', + SPACE_KEY = 'sorts_whitespace'; +} diff --git a/library/Class/ProfileSerializer/UnimarcRecord.php b/library/Class/ProfileSerializer/UnimarcRecord.php index 97f63bdb39d990e9ed0ac167e00d463f0add0884..809be57193e48a19371502916d5c92393bf4fe4b 100644 --- a/library/Class/ProfileSerializer/UnimarcRecord.php +++ b/library/Class/ProfileSerializer/UnimarcRecord.php @@ -32,6 +32,9 @@ class Class_ProfileSerializer_UnimarcRecord extends Class_ProfileSerializer_Abst 6 => $this->_extractInterests(), 7 => $this->_extractFileIndexation(), 8 => $this->_extractThumbs(), + Class_ProfilePrefs_Codification_Section::PROFILE_NAME => $this->_extractSections(), + Class_ProfilePrefs_Codification_Location::PROFILE_NAME => $this->_extractLocations(), + Class_ProfilePrefs_Codification_Sort::PROFILE_NAME => $this->_extractSorts(), Class_IntProfilDonnees::PROFILE_RECORD_IDENTIFIERS => $this->_extractIdentifiers(), Class_IntProfilDonnees::PROFILE_RECORD_AUTHORITY_IDENTIFIERS => $this->_extractAuthorityIdentifiers(), ]; @@ -66,6 +69,9 @@ class Class_ProfileSerializer_UnimarcRecord extends Class_ProfileSerializer_Abst ->populateInterests() ->populateFileIndexation() ->populateThumbs() + ->populateSections() + ->populateLocations() + ->populateSorts() ->populateIdentifiers() ->populateAuthorityIdentifiers(); } @@ -177,4 +183,19 @@ class Class_ProfileSerializer_UnimarcRecord extends Class_ProfileSerializer_Abst return implode(';', $this->_datas['nouveaute_valeurs']); } + + + protected function _extractSections() { + return (new Class_ProfilePrefs_Codification_Section)->extractFrom($this->_datas); + } + + + protected function _extractLocations() { + return (new Class_ProfilePrefs_Codification_Location)->extractFrom($this->_datas); + } + + + protected function _extractSorts() { + return (new Class_ProfilePrefs_Codification_Sort)->extractFrom($this->_datas); + } } diff --git a/library/Class/Users.php b/library/Class/Users.php index bdc0fdc9d83b7151ac310a0b39547651532d4994..46a4cc9d3e2c1d73ee1c34aa8190b0fb4083e70e 100644 --- a/library/Class/Users.php +++ b/library/Class/Users.php @@ -1487,9 +1487,10 @@ class Class_Users extends Storm_Model_Abstract { } - public function shouldUseUniquePatron() :bool { + public function shouldUseUniquePatron(Class_Exemplaire $item) :bool { return (($central_library_id = Class_CosmoVar::get('centralized_hold_mode')) && ($this->getIdIntBib() != $central_library_id) + && ($item->getIdIntBib() == $central_library_id) && ($cardnumber = $this->getUseCardNumber())); } @@ -2261,4 +2262,12 @@ class Class_Users extends Storm_Model_Abstract { return $emprunteur->getExternalAjaxHistoryLoansHelperClassname(); } + + + public function getUrlServer(): string + { + return ($int_bib = $this->getIntBib()) + ? $int_bib->getUrlServer() + : ''; + } } diff --git a/library/Class/WebService/MappedSoapClient.php b/library/Class/WebService/MappedSoapClient.php index 5d17f5cd53ede119bebaca2edea4937c61d1699b..fcfa7824179135872efc64bf2b88dead02ec3426 100644 --- a/library/Class/WebService/MappedSoapClient.php +++ b/library/Class/WebService/MappedSoapClient.php @@ -154,7 +154,7 @@ class Class_WebService_MappedSoapClient extends SoapClient { { if (static::$_testing) return $this->getWebClient() - ->open_url($action, ['request' => $request, + ->postData($action, ['request' => $request, 'location' => $location, 'version' => $version]); diff --git a/library/Class/WebService/SIGB/AbstractExternalAjaxLoansHelper.php b/library/Class/WebService/SIGB/AbstractExternalAjaxLoansHelper.php index ced958600a7ea38367f1b49638fe7c91c25c427a..24018a7b71dd1f105b8b253a49f4f303c33a2536 100644 --- a/library/Class/WebService/SIGB/AbstractExternalAjaxLoansHelper.php +++ b/library/Class/WebService/SIGB/AbstractExternalAjaxLoansHelper.php @@ -45,7 +45,8 @@ abstract class Class_WebService_SIGB_AbstractExternalAjaxLoansHelper 'date_to' => $this->getDateTo(), 'date_from' => $this->getDateFrom(), 'page' => $page, - 'size' => $page_size])->getArrayCopy(); + 'size' => $page_size, + 'order' => $this->getOrder()])->getArrayCopy(); $collection = array_map(fn($loan) => new Intonation_Library_View_Wrapper_Loan($loan, $this->_view), $loans); @@ -162,6 +163,12 @@ abstract class Class_WebService_SIGB_AbstractExternalAjaxLoansHelper } + public function getOrder(): string + { + return $this->_order ?? ''; + } + + public function setDateTo(string $filter) :self { $this->_date_to = $filter; return $this; diff --git a/library/Class/WebService/SIGB/AbstractRESTService.php b/library/Class/WebService/SIGB/AbstractRESTService.php index d5bd41f0235d7c9ebd3dcb4a3dcc30248c774270..64a699d633b3623ae83eb8f5112f5d82a1cc9e15 100644 --- a/library/Class/WebService/SIGB/AbstractRESTService.php +++ b/library/Class/WebService/SIGB/AbstractRESTService.php @@ -28,6 +28,7 @@ abstract class Class_WebService_SIGB_AbstractRESTService protected $_server_root; protected $_web_client; protected $_has_network_error = false; + protected int $_id_int_bib = 0; /** * @param string $server_root @@ -48,6 +49,17 @@ abstract class Class_WebService_SIGB_AbstractRESTService } + public function setIdIntBib(int $id) : self { + $this->_id_int_bib = $id; + return $this; + } + + + public function getIdIntBib() : int { + return $this->_id_int_bib; + } + + /** * @param string $server_root * @return Class_WebService_SIGB_AbstractRESTService @@ -234,9 +246,11 @@ abstract class Class_WebService_SIGB_AbstractRESTService } - protected function _getTagData(?string $xml, string $tag) : string{ + protected function _getTagData(?string $xml, string $tag): string + { if ( ! $xml) return ''; + $matches = []; $string_to_search = sprintf('/%s>([^<]*)<\/%s/', $tag, $tag); if (preg_match($string_to_search, @@ -315,9 +329,11 @@ abstract class Class_WebService_SIGB_AbstractRESTService if ($this->_getTagData($xml, $error_tag)) return null; - return $reader - ->setEmprunteur(Class_WebService_SIGB_Emprunteur::nullInstance()) + $reader + ->setEmprunteur(Class_WebService_SIGB_Emprunteur::nullInstance()->setService($this)) ->parseXML($xml); + + return $reader; } diff --git a/library/Class/WebService/SIGB/AbstractService.php b/library/Class/WebService/SIGB/AbstractService.php index 4b09b4ab94c7646d47ad68a62fd7568f1f9e8ae2..18549ea6db58b4362727b939a13e0db1d086c2b2 100644 --- a/library/Class/WebService/SIGB/AbstractService.php +++ b/library/Class/WebService/SIGB/AbstractService.php @@ -144,7 +144,8 @@ abstract class Class_WebService_SIGB_AbstractService { } - public function providesPickupLocations() { + public function providesPickupLocations(): bool + { return false; } @@ -248,7 +249,8 @@ abstract class Class_WebService_SIGB_AbstractService { public function setDefaultLibraryToEmprunteur($emprunteur, int $library_id) : self{ - $emprunteur->setIdIntBib($library_id); + if ( ! $emprunteur->isNullInstance() && ! $emprunteur->getIdIntBib()) + $emprunteur->setIdIntBib($library_id); return $this; } @@ -389,4 +391,12 @@ abstract class Class_WebService_SIGB_AbstractService { abstract public function prolongerPret($user, $pret_id); abstract public function getNotice($id); + + + public function codifAnnexesForUrlServer(): array + { + $int_bibs = (new Class_IntBib_ForUrl)->intBibsForUrlServer($this->getServerRoot()); + + return Class_CodifAnnexe::findAllByIdBibs($int_bibs); + } } diff --git a/library/Class/WebService/SIGB/Decalog.php b/library/Class/WebService/SIGB/Decalog.php index 1a1c7e3af25f67d17b71a4ee346d511916be0f88..db32668e672fbd0c173ef495954dbc15fe95ee73 100644 --- a/library/Class/WebService/SIGB/Decalog.php +++ b/library/Class/WebService/SIGB/Decalog.php @@ -28,7 +28,8 @@ class Class_WebService_SIGB_Decalog extends Class_WebService_SIGB_Abstract { self::$service = Class_WebService_SIGB_Decalog_Service::getService($params['url_serveur'], $params['key'], $params['institution_code'], - $params['record_id_prefix']); + $params['record_id_prefix']) + ->initializeUseCardNumber($params); } return self::$service; diff --git a/library/Class/WebService/SIGB/Decalog/BookableResponseReader.php b/library/Class/WebService/SIGB/Decalog/BookableResponseReader.php index 40c92253514eedcca7982cee2fb4da3b585cac63..cf59fdb09350acfeadd67bd29ac15736342dddd0 100644 --- a/library/Class/WebService/SIGB/Decalog/BookableResponseReader.php +++ b/library/Class/WebService/SIGB/Decalog/BookableResponseReader.php @@ -39,7 +39,7 @@ class Class_WebService_SIGB_Decalog_BookableResponseReader protected function _isBookable() : bool { - return $this->_data['isBookable']; + return (bool) $this->_data['isBookable'] ?? false; } diff --git a/library/Class/WebService/SIGB/Emprunteur.php b/library/Class/WebService/SIGB/Emprunteur.php index 148ae30147ba543c3d1fc459031204dc846604ff..33910f277ee2ec67ca352bcfe585d739055c28b4 100644 --- a/library/Class/WebService/SIGB/Emprunteur.php +++ b/library/Class/WebService/SIGB/Emprunteur.php @@ -43,7 +43,7 @@ class Class_WebService_SIGB_Emprunteur protected string $_mobile = ''; protected string $_date_naissance = ''; protected string $_library_code = ''; - protected string $_id_int_bib = ''; + protected int $_id_int_bib = 0; protected string $_public_comment = ''; protected string $_favorite_sending_channel = ''; @@ -55,8 +55,8 @@ class Class_WebService_SIGB_Emprunteur protected array $_sending_channels = []; protected int $_nb_reservations; - protected int $_nb_emprunts; - protected int $_nb_retards; + protected ?int $_nb_emprunts; + protected ?int $_nb_retards; protected int $_multimedia_access = -1; protected int $_parental_authorization = -1; @@ -729,23 +729,47 @@ class Class_WebService_SIGB_Emprunteur } - public function setLibraryCode(string $library_code): self + public function getService() : ?Class_WebService_SIGB_AbstractService { + return ($this->_service instanceOf Class_Webservice_SIGB_AbstractService) + ? $this->_service + : null; + } + + + public function getIdIntBibByService() : int { + return $this->_service + ? $this->_service->getIdIntBib() + : 0; + } + + + public function setLibraryCode(string $library_code) : self { $this->_library_code = $library_code; return $this; } - public function getLibrary(): Class_CodifAnnexe - { - return ($library = Class_CodifAnnexe::findFirstBy(['id_origine' => $this->_library_code])) - ? $library + public function getLibrary() : Class_CodifAnnexe { + $url_service = ($service = $this->getService()) + ? $service->getServerRoot() + : ''; + return ($branch = Class_CodifAnnexe::findByCodeAndBib($this->_library_code, + $this->_id_int_bib, + $url_service)) + ? $branch : Class_CodifAnnexe::newInstance(); } - public function getLibraryCode() - { + public function getLibraryIntBibId() : int { + return ($library = $this->getLibrary()) + ? $library->getIntBibId() + : 0; + } + + + public function getLibraryCode() { return $this->_library_code; } @@ -908,8 +932,9 @@ class Class_WebService_SIGB_Emprunteur && ($bib = $annexe->getBib())) $user->setBib($bib); - if ($id_int_bib = $this->getIdIntBib()) - $user->setIntBib(Class_IntBib::find($id_int_bib)); + // Has to be processed after Bib + if ($int_bib = $this->_checkForIntBibId($user)) + $user->setIdIntBib($int_bib); if ( Class_Users::UNDEFINED_DATA !== $this->_multimedia_access ) $user->setMultimediaAccess($this->_multimedia_access); @@ -921,6 +946,17 @@ class Class_WebService_SIGB_Emprunteur } + protected function _checkForIntBibId(Class_Users $user): ?int + { + if (($id_bib = $user->getIdSite()) + && ($int_bib = Class_IntBib::find($id_bib)) + && $int_bib->getUrlServer()) + return $id_bib; + + return $this->getIdIntBib() ?: null; + } + + public function updateFromUser(Class_Users $user): self { $this @@ -938,7 +974,6 @@ class Class_WebService_SIGB_Emprunteur ->setIsContactSms($user->getIsContactSms() ?? false) ->setIsContactEmail($user->getIsContactMail() ?? false); - return $this; } diff --git a/library/Class/WebService/SIGB/Koha/CommunityService.php b/library/Class/WebService/SIGB/Koha/CommunityService.php index b3ee5f1fc6b249ff1623d10a13240c3ab318e43a..f94ed1d1a977f202eef58e48e0b10c43b818cf0b 100644 --- a/library/Class/WebService/SIGB/Koha/CommunityService.php +++ b/library/Class/WebService/SIGB/Koha/CommunityService.php @@ -273,7 +273,8 @@ class Class_WebService_SIGB_Koha_CommunityService } - public function providesPickupLocations() { + public function providesPickupLocations(): bool + { return true; } diff --git a/library/Class/WebService/SIGB/Koha/PatronInfoReader.php b/library/Class/WebService/SIGB/Koha/PatronInfoReader.php index 32fdd947a3b3ef09ee4436de4b2011861d0034d4..591549b5f543a59fe5a1fd92b2f6a1864e071541 100644 --- a/library/Class/WebService/SIGB/Koha/PatronInfoReader.php +++ b/library/Class/WebService/SIGB/Koha/PatronInfoReader.php @@ -98,6 +98,9 @@ class Class_WebService_SIGB_Koha_PatronInfoReader public function endHoldingbranch($data) { if ($this->_currentLoan) $this->updateBibliothequeWith($data); + + if ($this->_currentHold) + $this->updateBibliothequeWith($data); } @@ -168,23 +171,24 @@ class Class_WebService_SIGB_Koha_PatronInfoReader } - public function updateBibliothequeWith($data) { - if(!$site = $this->findSite($data)) - return; + public function updateBibliothequeWith(string $branch_code) : self { + if (! $branch = Class_CodifAnnexe::findByCodeAndBib(trim($branch_code), + $this->_getIdIntBib())) + return $this; - $this->_current_operation->getExemplaire()->setBibliotheque($site->getLibelle()); + $this->_current_operation + ->getExemplaire() + ->setBibliotheque($branch->getLibelle()); if ($this->_currentHold) - $this->_currentHold->setPickupLocationLabel($site->getLibelle()) - ->setLocationId($site->getLibraryId()); + $this->_currentHold->setPickupLocationLabel($branch->getLibelle()) + ->setLocationId($branch->getBibId()); + return $this; } - protected function findSite($code) { - $code = trim($code); - if (!$code || !($site = Class_CodifAnnexe::findFirstBy(['id_origine' => $code]))) - return null; - return $site; + protected function _getIdIntBib() : int { + return $this->_emprunteur ? $this->_emprunteur->getIdIntBibByService() : 0; } diff --git a/library/Class/WebService/SIGB/Koha/Service.php b/library/Class/WebService/SIGB/Koha/Service.php index 2cbbc4bed902a5592aaafb8053dc6f9326001d2f..c800dbc500d5e414962f5052751aebeb175b581e 100644 --- a/library/Class/WebService/SIGB/Koha/Service.php +++ b/library/Class/WebService/SIGB/Koha/Service.php @@ -39,6 +39,7 @@ class Class_WebService_SIGB_Koha_Service extends Class_WebService_SIGB_AbstractR public static function getService($params) { return static::newInstance() ->setServerRoot($params['url_serveur']) + ->setIdIntBib((int) ($params['id_bib'] ?? 0)) ->setInterdireResaDocDispo($params['Interdire_reservation_doc_dispo']==='1') ->setApiUser($params['api_user'] ?? '') ->setApiPass($params['api_pass'] ?? '') @@ -342,6 +343,7 @@ class Class_WebService_SIGB_Koha_Service extends Class_WebService_SIGB_AbstractR public function reserverExemplaire($user, $exemplaire, $code_annexe) { if ($exemplaire->requiresCalendarHold()) return $this->_error('La durée de réservation est requise'); + if (1 == Class_AdminVar::get('KOHA_MULTI_SITES')) return $this->holdItem($user, $exemplaire, $code_annexe); @@ -409,8 +411,9 @@ class Class_WebService_SIGB_Koha_Service extends Class_WebService_SIGB_AbstractR protected function _setPickupLocation($args, $code) { - if (trim($code) && $annexe = Class_CodifAnnexe::findByCode($code)) + if (trim($code) && $annexe = Class_CodifAnnexe::findByCodeAndBib($code, (int)$args['bib_id'] ?? 0)) $args['pickup_location'] = $annexe->getIdOrigine(); + return $args; } diff --git a/library/Class/WebService/SIGB/KohaLegacy/Service.php b/library/Class/WebService/SIGB/KohaLegacy/Service.php index af710d6d3fbb31650d7d5e9c40870d2048bdb8a0..4db3e2a80eb3adab6d7367daff59f9c0ccc44d89 100644 --- a/library/Class/WebService/SIGB/KohaLegacy/Service.php +++ b/library/Class/WebService/SIGB/KohaLegacy/Service.php @@ -38,6 +38,7 @@ class Class_WebService_SIGB_KohaLegacy_Service extends Class_WebService_SIGB_Koh public static function getService($params) { return static::newInstance() ->setServerRoot($params['url_serveur']) + ->setIdIntBib((int) ($params['id_bib'] ?? 0)) ->setInterdireResaDocDispo($params['Interdire_reservation_doc_dispo']==='1') ->setRestful($params['restful']==='1') ->setPreRegistration($params['pre-registration'] === '1') @@ -47,11 +48,6 @@ class Class_WebService_SIGB_KohaLegacy_Service extends Class_WebService_SIGB_Koh } - protected function _getPatronReader(){ - return Class_WebService_SIGB_Koha_PatronInfoReader::newInstance(); - } - - public function holdsForItem($item) { if (!$this->restful) { $response = $this->_error($this->_('Koha Restful désactivé')); @@ -102,6 +98,12 @@ class Class_WebService_SIGB_KohaLegacy_Service extends Class_WebService_SIGB_Koh } + public function providesItemInformationService() : bool + { + return false; + } + + public function suggestionsOf(Class_Users $user): array { if (!$this->providesSuggestions()) diff --git a/library/Class/WebService/SIGB/Nanook/PatronInfoReader.php b/library/Class/WebService/SIGB/Nanook/PatronInfoReader.php index 7a13820c2ae840be0988998ecfaaec6cdd21780a..4d3092fd3385cd07b9baddc875e36f41a5f1c5c6 100644 --- a/library/Class/WebService/SIGB/Nanook/PatronInfoReader.php +++ b/library/Class/WebService/SIGB/Nanook/PatronInfoReader.php @@ -332,8 +332,10 @@ class Class_WebService_SIGB_Nanook_PatronInfoReader public function endSite($data) { - $library = Class_Bib::find($data); - $this->_current_suggest->setLibrary($library ? $library->getLibelle() : $data); + $libelle = ($annexe = Class_CodifAnnexe::findByCodeAndCurrentUser($data)) + ? $annexe->getLibraryLabel() + : $data; + $this->_current_suggest->setLibrary($libelle); } diff --git a/library/Class/WebService/SIGB/Nanook/PreRegistration.php b/library/Class/WebService/SIGB/Nanook/PreRegistration.php index 22a21aec8446a9cccf3a4f1b576df56cd5be6ea6..099182bd10e70fa8475060e955a4c606992d44c6 100644 --- a/library/Class/WebService/SIGB/Nanook/PreRegistration.php +++ b/library/Class/WebService/SIGB/Nanook/PreRegistration.php @@ -40,14 +40,15 @@ class Class_WebService_SIGB_Nanook_Preregistration extends Class_WebService_SIGB return $this; } - $response = $int_bib->getSIGBComm()->preRegistration($data); + $response = $int_bib->getSIGBComm() + ->preRegistration($data->prepareForWebService()); if (!$response['statut']) { $this->getLogger()->log($response['erreur']); return $this; } - return $this->_updateUser($id, $response); + return $this->_updateUser($int_bib->getId(), $response); } diff --git a/library/Class/WebService/SIGB/Nanook/PreRegistration/Data.php b/library/Class/WebService/SIGB/Nanook/PreRegistration/Data.php index 5f047ec30247dc9d12d0dda96f8920570915fed7..fd9350b4a822539d8db651d0ec5ebacfc79a8788 100644 --- a/library/Class/WebService/SIGB/Nanook/PreRegistration/Data.php +++ b/library/Class/WebService/SIGB/Nanook/PreRegistration/Data.php @@ -21,6 +21,7 @@ class Class_WebService_SIGB_Nanook_Preregistration_Data extends Class_WebService_SIGB_PreRegistration_AbstractData { + protected ?Class_Bib $_library; protected static array $_fields_map = ['prenom' => 'firstName', @@ -31,6 +32,11 @@ class Class_WebService_SIGB_Nanook_Preregistration_Data extends Class_WebService 'code_postal' => 'zipcode', 'adresse' => 'address']; + public function __construct(array $data) { + parent::__construct($data); + $this->_library = Class_IntBib::find($this->_getBranchCode())?->getBib(); + } + protected function _getBranchCode() : string { return $this->_data_as_array['site'] ?? '0'; @@ -42,7 +48,22 @@ class Class_WebService_SIGB_Nanook_Preregistration_Data extends Class_WebService } + public function prepareForWebService(): self { + if (!$this->_library) + return $this; + + $this->_data_as_array['site'] = $this->_library->getIdOrigine() ?? 0; + + return $this; + } + + public function getEmail() : string { return $this->_data_as_array['mail'] ?? ''; } + + + public function getLibrary() : ?Class_Bib { + return $this->_library; + } } diff --git a/library/Class/WebService/SIGB/Nanook/Service.php b/library/Class/WebService/SIGB/Nanook/Service.php index 85e3bb346b911fe1248eb1ba79bff1dfe0d2e7bd..8dd45f7aac87cc38cc8abc33056f3059705192e8 100644 --- a/library/Class/WebService/SIGB/Nanook/Service.php +++ b/library/Class/WebService/SIGB/Nanook/Service.php @@ -196,6 +196,9 @@ class Class_Webservice_SIGB_Nanook_Service if ($user->getPassword()) $emprunteur->setPassword($user->getPassword()); + if ($emprunteur->getLibraryCode() && $id = $emprunteur->getLibraryIntBibId()) + $emprunteur->setIdIntBib($id); + return $emprunteur; } @@ -362,10 +365,9 @@ class Class_Webservice_SIGB_Nanook_Service */ public function reserverExemplaire($user, $exemplaire, $code_bib_or_annexe) { $code_annexe = $code_bib_or_annexe; - if ( - ($annexe = Class_CodifAnnexe::findFirstBy(['id_origine' => $code_bib_or_annexe])) - || - ($annexe = Class_CodifAnnexe::findFirstBy(['id_bib' => $code_bib_or_annexe]))) + if (($annexe = Class_CodifAnnexe::findByCodeAndBib($code_bib_or_annexe, + $exemplaire->getIdIntBib())) + || ($annexe = Class_CodifAnnexe::findFirstBy(['id_bib' => $code_bib_or_annexe]))) $code_annexe = $annexe->getIdOrigine(); return $this->ilsdiHoldTitle(['bibId' => $exemplaire->getIdOrigine(), diff --git a/library/Class/WebService/SIGB/Opsys/Service.php b/library/Class/WebService/SIGB/Opsys/Service.php index 40399cca913ed40649d2694b27cda7e73d195abb..98da4d4914027f64398a3b7e898d30e625759914 100644 --- a/library/Class/WebService/SIGB/Opsys/Service.php +++ b/library/Class/WebService/SIGB/Opsys/Service.php @@ -357,7 +357,9 @@ class Class_WebService_SIGB_Opsys_Service extends Class_WebService_SIGB_Abstract public function getServerRoot() { - return $this->search_client->getWsdlUrl(); + return $this->search_client + ? $this->search_client->getWsdlUrl() + : ''; } diff --git a/library/Class/WebService/SIGB/Orphee/Emprunteur.php b/library/Class/WebService/SIGB/Orphee/Emprunteur.php index aea2da22fcf2368f161fa8b77215db753b31b286..60e1cd6303870bfc9a67d7618a9a20fd3dd3165c 100644 --- a/library/Class/WebService/SIGB/Orphee/Emprunteur.php +++ b/library/Class/WebService/SIGB/Orphee/Emprunteur.php @@ -113,7 +113,7 @@ class Class_WebService_SIGB_Orphee_Emprunteur ]); return $this->_nb_retards; } - return count(array_filter( $this->getLoans(), fn( $loan) => $loan->enRetard())); + return 0; } @@ -137,6 +137,11 @@ class Class_WebService_SIGB_Orphee_Emprunteur } + public function nbRetards() :int { + return $this->_nb_retards ?? 0; + } + + public function ensureService(Class_Users $user) :Class_WebService_SIGB_Emprunteur { parent::ensureService($user); if ($this->_service) diff --git a/library/Class/WebService/SIGB/Orphee/GetInfoUserCarteResponseReader.php b/library/Class/WebService/SIGB/Orphee/GetInfoUserCarteResponseReader.php index ff14f836cee347246f89884338523a9518185251..017094e1389f45c8ffa12258b3b6ea6b0b899473 100644 --- a/library/Class/WebService/SIGB/Orphee/GetInfoUserCarteResponseReader.php +++ b/library/Class/WebService/SIGB/Orphee/GetInfoUserCarteResponseReader.php @@ -162,15 +162,6 @@ class Class_WebService_SIGB_Orphee_GetInfoUserCarteResponseReader { } - public function endAnx(string $data) : void { - $this->_emprunteur->setLibraryCode(trim($data)); - - if (!$annexe = Class_CodifAnnexe::findByCode(trim($data))) - return; - $this->_emprunteur->setIdIntBib($annexe->getIdBib()); - } - - public function endIsDepot(string $data) :void { $this->_emprunteur->setIsWarehouse((bool)trim($data)); } @@ -180,4 +171,9 @@ class Class_WebService_SIGB_Orphee_GetInfoUserCarteResponseReader { $this->_emprunteur->setWarehouseId(trim($data)); $this->_emprunteur->setIsWarehouse(true); } + + + public function endAnx(string $data) : void { + $this->_emprunteur->setLibraryCode(trim($data)); + } } diff --git a/library/Class/WebService/SIGB/Orphee/Service.php b/library/Class/WebService/SIGB/Orphee/Service.php index 60310ef514abcab7610b6d8f9b5b07ef14c447f7..0865355db41b4bfb9944262c55f19c07a386af67 100644 --- a/library/Class/WebService/SIGB/Orphee/Service.php +++ b/library/Class/WebService/SIGB/Orphee/Service.php @@ -228,15 +228,13 @@ class Class_WebService_SIGB_Orphee_Service extends Class_WebService_SIGB_Abstrac public function providesChangePasswordService() :bool { return $this->getSearchClient()->hasFunction('SetPwdAdh') - && Class_AdminVar::isLoginThroughSigbOnlyEnabled() && !$this->getUseCardNumber(); } public function providesAuthentication() :bool { return $this->_identification_provider - && $this->hasGetAdh() - && Class_AdminVar::isLoginThroughSigbOnlyEnabled(); + && $this->hasGetAdh(); } @@ -272,7 +270,8 @@ class Class_WebService_SIGB_Orphee_Service extends Class_WebService_SIGB_Abstrac } - public function getUniquePatron(string $cardnumber) : Class_WebService_SIGB_Emprunteur { + public function getUniquePatron(string $cardnumber): Class_WebService_SIGB_Emprunteur + { $result = $this->_search_client->GetAdh(GetAdh::WithNo($cardnumber)); if (!$emprunteur = Class_WebService_SIGB_Orphee_GetInfoUserCarteResponseReaderAsUniquePatron ::getInstanceWith($cardnumber) @@ -287,25 +286,29 @@ class Class_WebService_SIGB_Orphee_Service extends Class_WebService_SIGB_Abstrac } - public function setDefaultLibraryToEmprunteur($emprunteur, int $library_id) : self{ + public function setDefaultLibraryToEmprunteur($emprunteur, int $library_id): self + { if (!$emprunteur->getIdIntBib()) $emprunteur->setIdIntBib($library_id); return $this; } - public function getUserAnnexe($user) { + public function getUserAnnexe($user) + { return null; } - protected function hasGetAdh() { + protected function hasGetAdh() + { return $this->getSearchClient()->hasFunction('GetAdh'); } - public function newNullEmprunteur() { - return Class_WebService_SIGB_Emprunteur::newInstance(); + public function newNullEmprunteur() + { + return Class_WebService_SIGB_Emprunteur::nullInstance(); } @@ -346,7 +349,9 @@ class Class_WebService_SIGB_Orphee_Service extends Class_WebService_SIGB_Abstrac protected function _processOrderParams(array $params) :self{ - if (!isset($params['order']) ||(null === ($params['order'] ?? null))) + if (!isset($params['order']) + || (null === ($params['order'] ?? null)) + || ('' === $params['order'] ) ) $params['order'] = SetTri::SORT_ISSUE .'_'. SetTri::ORDER_DESC; if ($settri_params = $this->_setTriOptionsFromParams($params['order']) ) @@ -550,7 +555,9 @@ class Class_WebService_SIGB_Orphee_Service extends Class_WebService_SIGB_Abstrac $params['count'] = 1; $this->getEmpruntsOf($emprunteur, $params); - return $emprunteur->nbEmprunts(); + return ('late' === ($params['filter'] ?? '')) + ? $emprunteur->nbRetards() + : $emprunteur->nbEmprunts(); } @@ -581,7 +588,7 @@ class Class_WebService_SIGB_Orphee_Service extends Class_WebService_SIGB_Abstrac } catch (SoapFault $e) { $this->_logError($this->_wsdl, $e); return ['statut' => false, - 'erreur' => 'Le SIGB Orphée a retourné l\'erreur suivante: '.$e->getMessage()]; + 'erreur' => $this->_("Le SIGB Orphée a retourné l'erreur suivante: %s",$e->getMessage())]; } if ($message = $errorClosure($result)) { @@ -605,7 +612,7 @@ class Class_WebService_SIGB_Orphee_Service extends Class_WebService_SIGB_Abstrac $datas = simplexml_load_string($result->getXml()); return ($datas->msg->code == 1) ? false : (string)$datas->msg->libelle; }, - fn($user) => ($user->shouldUseUniquePatron()) + fn($user) => $user->shouldUseUniquePatron($exemplaire) ? $this->getUniquePatron($user->getUseCardNumber()) : $this->getEmprunteur($user) ); @@ -643,7 +650,10 @@ class Class_WebService_SIGB_Orphee_Service extends Class_WebService_SIGB_Abstrac $user, $notice_id, fn($id, $emprunteur) => $this->getSearchClient() ->DelRsv(DelRsv::withNoticeUserNo($id, $emprunteur->getId())), - fn($result) => ($result->DelRsvResult == 1) ? false : 'La suppression a échoué'); + fn($result) => ($result->DelRsvResult == 1) + ? false + : $this->_('La suppression a échoué') + ); } @@ -765,7 +775,8 @@ class Class_WebService_SIGB_Orphee_Service extends Class_WebService_SIGB_Abstrac return; $this->getSearchClient() - ->setTri(SetTri::withTypeTriAndOrdre($sort_type, $sort_order)); + ->SetTri(SetTri::withTypeTriAndOrdre((int) $sort_type, + (int) $sort_order)); }); } diff --git a/library/Class/WebService/SIGB/PreRegistration/AbstractData.php b/library/Class/WebService/SIGB/PreRegistration/AbstractData.php index 7b978d5c6ce7c0802603fdd2b8eda0913bdb25ac..d2ef2f9b893a4aa2b261cd5927063b926f1d52ea 100644 --- a/library/Class/WebService/SIGB/PreRegistration/AbstractData.php +++ b/library/Class/WebService/SIGB/PreRegistration/AbstractData.php @@ -85,9 +85,7 @@ abstract class Class_WebService_SIGB_PreRegistration_AbstractData { public function getLibraryId() : int { - return ($annexe = Class_CodifAnnexe::findFirstBy(['code' => $this->_getBranchCode()])) - ? $annexe->getIdBib() - : 0; + return ($library = $this->getLibrary()) ? $library->getId() : 0; } diff --git a/library/ZendAfi/Auth/Adapter/CommSigb.php b/library/ZendAfi/Auth/Adapter/CommSigb.php index 198b7b4ea9dd6b6282eedb1f146f39776740eefa..08197414b6424b47180956d387b10644227532ca 100644 --- a/library/ZendAfi/Auth/Adapter/CommSigb.php +++ b/library/ZendAfi/Auth/Adapter/CommSigb.php @@ -167,6 +167,7 @@ class ZendAfi_Auth_Adapter_CommSigb extends ZendAfi_Auth_Adapter_Abstract { if (!$loaner = $service->getEmprunteur($user)) return null; + $this->_called_services->append($service); if (!$loaner->isValid()) diff --git a/library/ZendAfi/Controller/Action/Helper/NotifyError.php b/library/ZendAfi/Controller/Action/Helper/NotifyError.php new file mode 100644 index 0000000000000000000000000000000000000000..fc65052cd2a283f0c62eea7404dfb3ae95566c39 --- /dev/null +++ b/library/ZendAfi/Controller/Action/Helper/NotifyError.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +class ZendAfi_Controller_Action_Helper_NotifyError extends ZendAfi_Controller_Action_Helper_Notify +{ + + + protected $_options = ['status' => 'error']; + + + public function notifyError($message, $options=[]) { + $this->_controller + ->getHelper('flashMessenger') + ->addNotification($message, array_merge($this->_options, $options)); + } +} diff --git a/library/ZendAfi/Controller/Plugin/ResourceDefinition/Emplacement.php b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Emplacement.php index 724cf40b073cf4c03c25d08d354312b285538ad5..2c99f750ff87c7e09647fc32576c752a69721c8f 100644 --- a/library/ZendAfi/Controller/Plugin/ResourceDefinition/Emplacement.php +++ b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Emplacement.php @@ -28,7 +28,8 @@ class ZendAfi_Controller_Plugin_ResourceDefinition_Emplacement ['model' => ['class' => 'Class_CodifEmplacement', 'name' => 'emplacement', 'order' => 'libelle', - 'model_id' => 'id_emplacement'], + 'model_id' => 'id_emplacement', + 'filter' => [Storm_Query_Clause::greater('regles', '')]], 'listViewMode' => ['helper_method' => 'ListViewMode_Codification_Flat', 'label' => $this->_('Emplacements'), diff --git a/library/ZendAfi/Controller/Plugin/ResourceDefinition/Genre.php b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Genre.php index 9c13c55a71c6f7083ace2e65196bdc040ccc7c0d..8e331bedbaf46f34a615b324c6c87f60615be3d3 100644 --- a/library/ZendAfi/Controller/Plugin/ResourceDefinition/Genre.php +++ b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Genre.php @@ -28,7 +28,8 @@ class ZendAfi_Controller_Plugin_ResourceDefinition_Genre ['model' => ['class' => 'Class_CodifGenre', 'name' => 'genre', 'order' => 'libelle', - 'model_id' => 'id_genre'], + 'model_id' => 'id_genre', + 'filter' => [Storm_Query_Clause::greater('regles', '')]], 'listViewMode' => ['helper_method' => 'ListViewMode_Codification_Flat', 'label' => $this->_('Genres'), diff --git a/library/ZendAfi/Controller/Plugin/ResourceDefinition/Section.php b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Section.php index 4077e4055a9a43e0704f211980ac87975dd80c4c..414964b81e52fdc894b298a9dcf26939630e97e5 100644 --- a/library/ZendAfi/Controller/Plugin/ResourceDefinition/Section.php +++ b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Section.php @@ -27,7 +27,8 @@ class ZendAfi_Controller_Plugin_ResourceDefinition_Section return ['model' => ['class' => 'Class_CodifSection', 'name' => 'section', 'order' => 'libelle', - 'model_id' => 'id_section'], + 'model_id' => 'id_section', + 'filter' => [Storm_Query_Clause::greater('regles', '')]], 'listViewMode' => ['helper_method' => 'ListViewMode_Codification_Flat', 'label' => $this->_('Sections'), diff --git a/library/ZendAfi/Form/Cosmo/CodifsImporter.php b/library/ZendAfi/Form/Cosmo/CodifsImporter.php new file mode 100644 index 0000000000000000000000000000000000000000..a7442e845bc0a10afcc0b3a9d22d1f70460e5944 --- /dev/null +++ b/library/ZendAfi/Form/Cosmo/CodifsImporter.php @@ -0,0 +1,78 @@ +<?php +/** + * Copyright (c) 2012-2023, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class ZendAfi_Form_Cosmo_CodifsImporter extends ZendAfi_Form { + + protected $_target; + + public function __construct(int $target) { + $this->_target = $target; + parent::__construct(); + } + + + public function init() { + parent::init(); + + Class_ScriptLoader::getInstance() + ->addAdminScripts(['global']) + ->addJqueryReady('formSelectToggleVisibilityForElement("#from", $("#profile").closest("tr"), ["2"]);'); + + $this->addElement('select', + 'from', + ['label' => $this->_('Depuis'), + 'multiOptions' => ['1' => $this->_('Les règles globales'), + '2' => $this->_('Un profil de données')]]); + + $this->addElement('select', 'profile', + ['label' => $this->_('Profil de données'), + 'multiOptions' => $this->_getProfilesCandidates()]); + + $this->addElement('multiCheckboxDropdown', + 'codif_types', + ['label' => $this->_('Les codifications suivantes'), + 'multiOptions' => ['sorts' => $this->_('Genre'), + 'sections' => $this->_('Section'), + 'locations' => $this->_('Emplacement')]]); + + $this->addUniqDisplayGroup('alone'); + } + + + protected function _getProfilesCandidates() : array { + $profiles = []; + + $profiles_in_db = Class_IntProfilDonnees::query() + ->select(['id_profil', 'libelle']) + ->not_eq('id_profil', $this->_target) + ->eq('type_fichier', Class_IntProfilDonnees::FT_RECORDS) + ->in('format', [Class_IntProfilDonnees::FORMAT_UNIMARC, + Class_IntProfilDonnees::FORMAT_UNIMARC_XML, + Class_IntProfilDonnees::FORMAT_MARC21]) + ->fetchAll(); + + foreach($profiles_in_db as $profile) + $profiles[$profile->getIdProfil()] = $profile->getLibelle(); + + return $profiles; + } +} diff --git a/library/ZendAfi/Form/Cosmo/DataProfile.php b/library/ZendAfi/Form/Cosmo/DataProfile.php index 8fd3f0ed04148ad78515e52b4158643d22caa761..25307828abf13c166e5639aefb9aa0b5f9eb6ac0 100644 --- a/library/ZendAfi/Form/Cosmo/DataProfile.php +++ b/library/ZendAfi/Form/Cosmo/DataProfile.php @@ -151,6 +151,9 @@ class ZendAfi_Form_Cosmo_DataProfile extends ZendAfi_Form { return $this ->_recordItemFields() ->addDocTypeGroup(['label' => $this->_('Label'), 'zone' => $this->_('Zone exemplaire')]) + ->_addSectionsGroup() + ->_addLocationsGroup() + ->_addSortsGroup() ->_recordNoveltyDate() ->_recordItemSerial() ->_recordIndexation() @@ -173,6 +176,48 @@ class ZendAfi_Form_Cosmo_DataProfile extends ZendAfi_Form { } + protected function _addSectionsGroup() { + $sections_prefs = new Class_ProfilePrefs_Codification_Section; + + $this->addElement('multiInput', 'sections_field', + ['label' => $this->_('Rechercher les sections dans'), + 'fields' => $sections_prefs->multiInputFieldsDefinition()]); + + return $this->addDisplayGroup(['sections_field'], + 'section_group', + ['legend' => $this->_('Sections')]); + + } + + + protected function _addLocationsGroup() { + $locations_prefs = new Class_ProfilePrefs_Codification_Location; + + $this->addElement('multiInput', 'locations_field', + ['label' => $this->_('Rechercher les emplacements dans'), + 'fields' => $locations_prefs->multiInputFieldsDefinition()]); + + return $this->addDisplayGroup(['locations_field'], + 'location_group', + ['legend' => $this->_('Emplacements')]); + + } + + + protected function _addSortsGroup() { + $sorts_prefs = new Class_ProfilePrefs_Codification_Sort; + + $this->addElement('multiInput', 'sorts_field', + ['label' => $this->_('Rechercher les genres dans'), + 'fields' => $sorts_prefs->multiInputFieldsDefinition()]); + + return $this->addDisplayGroup(['sorts_field'], + 'sort_group', + ['legend' => $this->_('Genres')]); + + } + + public function addOaiSetsGroup() : self { $sets = (new ZendAfi_Form_Admin_OaiSets)->getElement(); $this->addElement($sets); @@ -556,6 +601,39 @@ class ZendAfi_Form_Cosmo_DataProfile extends ZendAfi_Form { } + public function populateSections() : self { + if (!$this->_profile_prefs) + return $this; + + if ($this->sections_field) + $this->sections_field->setValues($this->_profile_prefs->getSections()); + + return $this; + } + + + public function populateLocations() : self { + if (!$this->_profile_prefs) + return $this; + + if ($this->locations_field) + $this->locations_field->setValues($this->_profile_prefs->getLocations()); + + return $this; + } + + + public function populateSorts() : self { + if (!$this->_profile_prefs) + return $this; + + if ($this->sorts_field) + $this->sorts_field->setValues($this->_profile_prefs->getSorts()); + + return $this; + } + + public function populateIdentifiers() : self { $this->getElement('identifiers')->setValues($this->_profile_prefs->getIdentifiers()); return $this; diff --git a/library/ZendAfi/View/Helper/BoutonIco.php b/library/ZendAfi/View/Helper/BoutonIco.php index 71a1ea221d1934182c01d12bca7ba26c6d6a38a3..de51d642781af739521a42c1d2ab99574a366f62 100644 --- a/library/ZendAfi/View/Helper/BoutonIco.php +++ b/library/ZendAfi/View/Helper/BoutonIco.php @@ -85,6 +85,7 @@ class ZendAfi_View_Helper_BoutonIco extends ZendAfi_View_Helper_BaseHelper 'VISIBLE' => ['hide', $this->_('Rendre visible')], 'INVISIBLE' => ['show', $this->_('Archiver')], 'DUPLICATE' => ['copy', $this->_('Dupliquer')], + 'COPY_CODIFS' => ['copy', $this->_('Importer les codifications')], ]; $type = strtoupper($type); diff --git a/library/ZendAfi/View/Helper/Cosmo/CodifsImporter.php b/library/ZendAfi/View/Helper/Cosmo/CodifsImporter.php new file mode 100644 index 0000000000000000000000000000000000000000..6392642bda985791f1a16ed7ca65e4723a910db8 --- /dev/null +++ b/library/ZendAfi/View/Helper/Cosmo/CodifsImporter.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright (c) 2012-2023, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class ZendAfi_View_Helper_Cosmo_CodifsImporter extends ZendAfi_View_Helper_BaseHelper { + + public function Cosmo_CodifsImporter() : string { + $html = $this->_tag('h1', $this->view->titre); + + $form = (new ZendAfi_Form_Cosmo_CodifsImporter($this->view->target_profile)) + ->setMethod('post') + ->setAction($this->view->url(['module' => 'cosmo', + 'controller' => 'data-profile', + 'action' => 'copy-codif-confirm', + 'id' => $this->view->target_profile], null, true)); + + return $html + . $this->view->renderForm($form); + } +} diff --git a/library/ZendAfi/View/Helper/TagListeCoches.php b/library/ZendAfi/View/Helper/TagListeCoches.php index a57bad66ccabe85f564f6b8a3ffe3f9f5936460f..c21819830bcc8ba84f39625552f7f95486ffa645 100644 --- a/library/ZendAfi/View/Helper/TagListeCoches.php +++ b/library/ZendAfi/View/Helper/TagListeCoches.php @@ -301,11 +301,6 @@ class ZendAfi_View_Helper_TagListeCochesSourceAnnexe extends ZendAfi_View_Helper public function __construct() { parent::__construct('Class_CodifAnnexe'); } - - - protected function getKey($instance) { - return $instance->getCode(); - } } diff --git a/library/digital_resources/Numel/tests/NumelTest.php b/library/digital_resources/Numel/tests/NumelTest.php index 76a35c1c44b24eac203b8f0f1fe67ea3ab033592..1b4c9a85a3862a66991091dea9dd490d5b8187ff 100644 --- a/library/digital_resources/Numel/tests/NumelTest.php +++ b/library/digital_resources/Numel/tests/NumelTest.php @@ -152,10 +152,14 @@ class NumelDashboardActivatedTest extends NumelActivatedTestCase "SELECT `codif_thesaurus`.* FROM `codif_thesaurus` WHERE (`codif_thesaurus`.`code` = 'Digital resources' AND `codif_thesaurus`.`id_thesaurus` LIKE 'DRDR0001%') ORDER BY `codif_thesaurus`.`id_thesaurus` DESC LIMIT 1", "SELECT `codif_thesaurus`.* FROM `codif_thesaurus` WHERE (`codif_thesaurus`.`code` = 'Digital resources' AND `codif_thesaurus`.`id_thesaurus` LIKE 'DRDR00010002%') ORDER BY `codif_thesaurus`.`id_thesaurus` DESC LIMIT 1", "SELECT `codif_tags`.* FROM `codif_tags` WHERE (`codif_tags`.`a_moderer` > '')", + "SELECT COUNT(*) AS `numberof` FROM `notices` WHERE (MATCH(`notices`.`titres`, `notices`.`auteurs`, `notices`.`editeur`, `notices`.`collection`, `notices`.`matieres`, `notices`.`dewey`, `notices`.`other_terms`, `notices`.`facets`) AGAINST('+F_B3' IN BOOLEAN MODE) AND `notices`.`type` = 1)", + "SELECT COUNT(*) AS `numberof` FROM `notices` WHERE (MATCH(`notices`.`titres`, `notices`.`auteurs`, `notices`.`editeur`, `notices`.`collection`, `notices`.`matieres`, `notices`.`dewey`, `notices`.`other_terms`, `notices`.`facets`) AGAINST('+F_T0 +F_B3' IN BOOLEAN MODE) AND `notices`.`type` = 1)", - "SELECT COUNT(*) AS `numberof` FROM `notices` WHERE (MATCH(`notices`.`titres`, `notices`.`auteurs`, `notices`.`editeur`, `notices`.`collection`, `notices`.`matieres`, `notices`.`dewey`, `notices`.`other_terms`, `notices`.`facets`) AGAINST('+F_HDRDR000100020001 +F_YArchivesdeMelun +F_B3' IN BOOLEAN MODE) AND `notices`.`type` = 1)", - "SELECT COUNT(*) AS `numberof` FROM `notices` WHERE (`notices`.`type` = 1 AND MATCH(`notices`.`titres`, `notices`.`auteurs`, `notices`.`editeur`, `notices`.`collection`, `notices`.`matieres`, `notices`.`dewey`, `notices`.`other_terms`, `notices`.`facets`) AGAINST('+F_HDRDR000100020001 -F_YArchivesdeMelun +F_B3' IN BOOLEAN MODE))"]); + + "SELECT COUNT(*) AS `numberof` FROM `notices` WHERE (MATCH(`notices`.`titres`, `notices`.`auteurs`, `notices`.`editeur`, `notices`.`collection`, `notices`.`matieres`, `notices`.`dewey`, `notices`.`other_terms`, `notices`.`facets`) AGAINST('+F_HDRDR000100020001 +F_Y233 +F_B3' IN BOOLEAN MODE) AND `notices`.`type` = 1)", + + "SELECT COUNT(*) AS `numberof` FROM `notices` WHERE (`notices`.`type` = 1 AND MATCH(`notices`.`titres`, `notices`.`auteurs`, `notices`.`editeur`, `notices`.`collection`, `notices`.`matieres`, `notices`.`dewey`, `notices`.`other_terms`, `notices`.`facets`) AGAINST('+F_HDRDR000100020001 -F_Y233 +F_B3' IN BOOLEAN MODE))"]); } diff --git a/tests/TearDown.php b/tests/TearDown.php index 0a4c2e88cce969ef0ed68511baec705204810292..ca8ffb8d7f857a476cf1079b5c92830381e156a1 100644 --- a/tests/TearDown.php +++ b/tests/TearDown.php @@ -45,6 +45,7 @@ class TearDown { Class_Album::setFileSystem(null); Class_Article_Loader::reset(); + Class_CodifAnnexe::reset(); Class_TypeDoc::reset(); Class_Codification::reset(); Class_Codification::resetInstance(); diff --git a/tests/application/modules/AbstractControllerTestCase.php b/tests/application/modules/AbstractControllerTestCase.php index 3e001864ab2fcb6cbfd98c82749c9c2c0c3313bd..f49d816d8f2048b89b3d93a15c3c96116234c57a 100644 --- a/tests/application/modules/AbstractControllerTestCase.php +++ b/tests/application/modules/AbstractControllerTestCase.php @@ -866,6 +866,12 @@ abstract class AbstractControllerTestCase extends Zend_Test_PHPUnit_ControllerTe } + public function assertXPathCountFromJson(string $path, int $count, string $message = ''): void + { + $this->_assertXPathFromJson('assertXpathCount', $path, $count, $message); + } + + public function assertNotXpathContentContainsFromJson(string $path, string $match, string $message = ''): void diff --git a/tests/application/modules/admin/controllers/CatalogueControllerTest.php b/tests/application/modules/admin/controllers/CatalogueControllerTest.php index a4222a2633d91389ff240562cb787ae89d350451..f3b51c4a87ad4d75a7e2b7cefc1ce5b91a2bfaf9 100644 --- a/tests/application/modules/admin/controllers/CatalogueControllerTest.php +++ b/tests/application/modules/admin/controllers/CatalogueControllerTest.php @@ -802,13 +802,13 @@ class CatalogueControllerEditCatalogueTest extends CatalogueControllerEditCatalo /** @test */ public function annexe12ChoiceShouldBePresent() { - $this->assertXPath('//div[@id="annexe_saisie"]//input[@type="checkbox"][@data-clef=12]'); + $this->assertXPath('//div[@id="annexe_saisie"]//input[@type="checkbox"][@data-clef=1]'); } /** @test */ public function annexe24ChoiceShouldBePresent() { - $this->assertXPath('//div[@id="annexe_saisie"]//input[@type="checkbox"][@data-clef=24]'); + $this->assertXPath('//div[@id="annexe_saisie"]//input[@type="checkbox"][@data-clef=2]'); } diff --git a/tests/application/modules/admin/controllers/TypeDocsControllerTest.php b/tests/application/modules/admin/controllers/TypeDocsControllerTest.php index 26167aa0a641b0dfc99c2abaa1782542eff21b46..5a5c80d2ddbbff57490b9c1480efd06d732c43e2 100644 --- a/tests/application/modules/admin/controllers/TypeDocsControllerTest.php +++ b/tests/application/modules/admin/controllers/TypeDocsControllerTest.php @@ -170,6 +170,7 @@ class TypeDocsControllerEditEPubTest extends AbstractTypeDocsControllerTestCase 'libelle' => 'News', 'invisible' => 0, 'id_origine' => 4]); + $this->fixture('Class_CodifAnnexe', ['id' => 93, 'libelle' => 'Bd', 'invisible' => 0, @@ -182,12 +183,13 @@ class TypeDocsControllerEditEPubTest extends AbstractTypeDocsControllerTestCase $this->fixture('Class_CodifTypeDoc', ['id' => 102, 'famille_id' => Class_CodifTypeDoc::LIVRE, 'bibliotheques' => '2;3', - 'annexes' => '4;8', + 'annexes' => '73;93', 'sections' => '9;10']); - $this->dispatch('/admin/type-docs/edit/id/102',true); + $this->dispatch('/admin/type-docs/edit/id/102'); } + /** @test */ public function titreShouldBeModificationDuTypeDocEPUB() { $this->assertXPathContentContains('//h1','Modification du type de document: E-Books'); @@ -214,7 +216,7 @@ class TypeDocsControllerEditEPubTest extends AbstractTypeDocsControllerTestCase /** @test */ public function annexeShouldBeDisplayedForEpub() { - $this->assertXPath('//form//input[@id="annexes"][@value="4;8"]'); + $this->assertXPath('//form//input[@id="annexes"][@value="73;93"]'); } diff --git a/tests/application/modules/opac/controllers/AbonneControllerSuggestionAchatNanookTest.php b/tests/application/modules/opac/controllers/AbonneControllerSuggestionAchatNanookTest.php index fadf79adbb4b04d7c487f3d3ce4e3f4f0ed876ee..a41ec65545a89d3bb82736a7ecff49b4418b23b5 100644 --- a/tests/application/modules/opac/controllers/AbonneControllerSuggestionAchatNanookTest.php +++ b/tests/application/modules/opac/controllers/AbonneControllerSuggestionAchatNanookTest.php @@ -49,9 +49,14 @@ abstract class AbstractAbonneControllerSuggestionAchatNanookTestCase extends Abs 'provide_suggest' => '1'], 'comm_sigb' => Class_IntBib::COM_NANOOK]); - $this->fixture('Class_Bib', ['id' => 12, - 'libelle' => 'Tatim bib', - 'int_bib' => $sigb_conf]); + $this->fixture(Class_CodifAnnexe::class, ['id' => 876, + 'code' => 12, + 'id_origine' => 12, + 'id_bib' => 12]); + + $tatim = $this->fixture(Class_Bib::class, ['id' => 12, + 'libelle' => 'Tatim bib', + 'int_bib' => $sigb_conf]); $sigb_conf->setIdBib(12); diff --git a/tests/application/modules/opac/controllers/AuthControllerPreRegistrationNanookDispatchTest.php b/tests/application/modules/opac/controllers/AuthControllerPreRegistrationNanookDispatchTest.php index c8da92eba50c7237f3d9310867d21cd024222e02..df729d7a0526f6ae3146c8ce356f9bdb78b230d2 100644 --- a/tests/application/modules/opac/controllers/AuthControllerPreRegistrationNanookDispatchTest.php +++ b/tests/application/modules/opac/controllers/AuthControllerPreRegistrationNanookDispatchTest.php @@ -25,6 +25,13 @@ class AuthControllerPreRegistrationNanookDispatchTest public function setUp(): void { parent::setUp(); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 99, + 'id_bib' => 1, + 'id_origine' => '1', + 'libelle' => 'Arcadia']); + $this->fixture(Class_Bib::class, ['id' => 1, 'libelle' => 'Arcadia']); diff --git a/tests/application/modules/opac/controllers/AuthControllerPreRegistrationTest.php b/tests/application/modules/opac/controllers/AuthControllerPreRegistrationTest.php index 1d11dcbf3d5f80688586ebebfa38a4fe9842eb3c..26e0c1739625e26152625a70d2514a5d46ac4360 100644 --- a/tests/application/modules/opac/controllers/AuthControllerPreRegistrationTest.php +++ b/tests/application/modules/opac/controllers/AuthControllerPreRegistrationTest.php @@ -346,21 +346,39 @@ abstract class AuthControllerPreRegistrationNanookTestCase parent::setUp(); $this->fixture(Class_CodifAnnexe::class, - ['id' => 1, + ['id' => 99, 'id_bib' => 1, - 'id_origine' => '1', + 'id_origine' => '8', 'libelle' => 'ARCADIA']); + $this->fixture(Class_CodifAnnexe::class, + ['id' => 100, + 'id_bib' => 2, + 'id_origine' => '2', + 'libelle' => 'Guiclan']); + $this->fixture(Class_Bib::class, - ['id' => 1, 'libelle' => 'Arcadia']); + ['id' => 1, + 'libelle' => 'Arcadia', + 'id_origine' => 8]); + + $this->fixture(Class_Bib::class, + ['id' => 2, 'libelle' => 'Guiclan']); $this->fixture(Class_IntBib::class, ['id' => 1, + 'id_bib' => 1, 'comm_params' => ['url_serveur' => 'http://super.nano.ok/ilsdi/arcadia', 'pre-registration' => 1], 'comm_sigb' => Class_IntBib::COM_NANOOK]); + $this->fixture(Class_IntBib::class, + ['id' => 2, + 'comm_params' => ['url_serveur' => 'http://super.nano2.ok/ilsdi/arcadia', + 'pre-registration' => 1], + 'comm_sigb' => Class_IntBib::COM_NANOOK]); + Class_IntBib::find(1)->getSIGBComm()->setWebClient($this->mock_web_client); } } @@ -407,6 +425,79 @@ class AuthControllerRegistrationWithConditionsTest extends AuthControllerPreRegi +class AuthControllerPreRegistrationNanookGetDispatchTest + extends AuthControllerPreRegistrationNanookTestCase { + + public function setUp(): void { + parent::setUp(); + $this->dispatch('/opac/auth/pre-registration', true); + } + + + /** @test */ + public function shouldNotRedirect() { + $this->assertNotRedirect(); + } + + + /** @test */ + public function siteListShouldContainArcadiaOption() + { + $this->assertXpath('//form//select[@name="site"]/option[@value="1"]'); + } + + + /** @test */ + public function siteListShouldContainGuiclanOption() + { + $this->assertXpath('//form//select[@name="site"]/option[@value="2"]'); + } + + + /** @test */ + public function formShouldContainsEmail() { + $this->assertXpath('//form//input[@name="mail"][@required="required"]'); + } + + + /** @test */ + public function inputForBirthDateShouldBeRequired() { + $this->assertXPath('//form//input[@name="birthDate"][@required="required"][@type="date"]'); + } + + + /** @test */ + public function formShouldContainsPassword() { + $this->assertXpath('//form//input[@name="password"]'); + } + + + /** @test */ + public function selectSiteShouldContainsOption99() { + $this->assertXPathContentContains('//form//select[@name="site"]//option[@value="1"]', 'Arcadia'); + } + + + /** @test */ + public function formShouldContainsCaptcha() { + $this->assertXPath('//input[@name="website"][@data-spambots="true"][@autocomplete="off"]'); + } + + + /** @test */ + public function birthdateShouldHaveMinAttribute() { + $this->assertXPath('//input[@name="birthDate"][@min="' . date('Y-m-d',strtotime('now -150 year')) . '"]'); + } + + + /** @test */ + public function birthdateShouldHaveMaxAttribute() { + $this->assertXPath('//input[@name="birthDate"][@max="' . date('Y-m-d',strtotime('now')) . '"]'); + } +} + + + class AuthControllerPreRegistrationNanookPostDispatchTest extends AuthControllerPreRegistrationNanookTestCase { @@ -420,7 +511,7 @@ class AuthControllerPreRegistrationNanookPostDispatchTest $this->mock_web_client ->whenCalled('postData') ->with('http://super.nano.ok/ilsdi/arcadia/service/pre-register', - ['site' => 1, + ['site' => 8, 'lastName' => 'Jiro', 'firstName' => 'Tom', 'mail' => 'test@test.fr', @@ -499,7 +590,7 @@ abstract class AuthControllerPreRegistrationNanookPostErrorTestCase $this->mock_web_client ->whenCalled('postData') ->with('http://super.nano.ok/ilsdi/arcadia/service/pre-register', - ['site' => 1, + ['site' => 8, 'lastName' => 'Jiro', 'firstName' => 'Tom', 'mail' => 'test@test.fr', @@ -614,7 +705,7 @@ class AuthControllerPreRegistrationNanookPostDispatchErrorPatronPasswordNotSecur $this->mock_web_client ->whenCalled('postData') ->with('http://super.nano.ok/ilsdi/arcadia/service/pre-register', - ['site' => 1, + ['site' => 8, 'lastName' => 'Jiro', 'firstName' => 'Tom', 'mail' => 'test@test.fr', @@ -733,6 +824,10 @@ class AuthControllerPreRegistrationWithNoPreRegistrationTest extends AuthControl parent::setUp(); Class_IntBib::find(1)->setCommParams(['url_serveur' => 'http://super.nano.ok/ilsdi/arcadia', 'pre-registration' => 0])->save(); + + Class_IntBib::find(2)->setCommParams(['url_serveur' => 'http://super.nano.ok/ilsdi/arcadia', + 'pre-registration' => 0])->save(); + $this->dispatch('/opac/auth/pre-registration'); } @@ -1136,7 +1231,7 @@ class AuthControllerPreRegistrationDefaultTemplateContentPostDispatchTest $this->mock_web_client ->whenCalled('postData') ->with('http://super.nano.ok/ilsdi/arcadia/service/pre-register', - ['site' => 1, + ['site' => 8, 'lastName' => 'Jiro', 'firstName' => 'Tom', 'mail' => 'test@test.fr', @@ -1166,7 +1261,7 @@ class AuthControllerPreRegistrationDefaultTemplateContentPostDispatchTest /** @test */ - public function responseShouldRedirectToPreRegistrationSuccessIdBibOne() { + public function responsePlopShouldRedirectToPreRegistrationSuccessIdBibOne() { $this->assertRedirectTo('/auth/pre-registration-success/id_bib/1'); } } diff --git a/tests/application/modules/opac/controllers/AuthControllerTest.php b/tests/application/modules/opac/controllers/AuthControllerTest.php index e0dbc93ac895a38445017e528b42a0a354e8b3cc..ed9d027606bc537869c03a01c8ddcd41b425b463 100644 --- a/tests/application/modules/opac/controllers/AuthControllerTest.php +++ b/tests/application/modules/opac/controllers/AuthControllerTest.php @@ -2834,43 +2834,37 @@ class AuthControllerPostWithSameIdSigbTest extends AbstractControllerTestCase { class AuthControllerPostLoginWithDifferentIdIntBibTest extends AbstractControllerTestCase { - protected $_storm_default_to_volatile = true; + public function setUp(): void { parent::setUp(); ZendAfi_Auth::getInstance()->clearIdentity(); - $pasc_library = $this->fixture(Class_Bib::class, - ['id' => 987, - 'libelle' => 'Pasc Library']); - - $this->fixture(Class_CodifAnnexe::class, - ['id' => 15, - 'libelle' => 'pasc', - 'id_origine' => 'PASC', - 'bib' => $pasc_library]); - - $emprunteur = Class_WebService_SIGB_Emprunteur::newInstance(789, 'koha'); - $emprunteur->setPassword('bar') - ->setLibraryCode('PASC'); - $emprunteur->beValid(); + $user = + $this->fixture(Class_Users::class, + ['id' => 5, + 'login' => 'foo', + 'password' => 'bar', + 'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB, + 'idabon' => 'foo', + 'id_site' => 56, + 'id_int_bib' => 56, + 'id_sigb' => null]); - $service = (new Class_Testing_WebService_SIGB_KohaLegacy_Service()) - ->whenCalled('getEmprunteur') - ->answers($emprunteur) - ->whenCalled('isConnected') - ->answers(true) - ->whenCalled('providesAuthentication') - ->answers(true); + Class_HttpClientFactory::forTest() + ->addPostRequestWithResponse('http://mon-koha-de-test.org:80', + ['service' => 'AuthenticatePatron', + 'username' => 'foo', + 'password' => 'bar'], + KohaFixtures::xmlAuthenticatePatronJameBondOk()) + ->addRequestWithResponse('http://mon-koha-de-test.org:80?service=GetPatronInfo&patron_id=007&show_contact=1&show_loans=0&show_holds=1', + KohaFixtures::xmlGetPatronInfoJamesBond()); $params = ['url_serveur' => 'http://mon-koha-de-test.org', 'id_bib' => 56, 'type' => Class_IntBib::COM_KOHA_LEGACY]; - Class_WebService_SIGB_KohaLegacy::setService($params, - $service); - $this->fixture(Class_Bib::class, ['id' => 56, 'libelle' => 'Library']); @@ -2885,31 +2879,39 @@ class AuthControllerPostLoginWithDifferentIdIntBibTest ['id' => 987, 'id_bib' => 987, 'comm_sigb' => Class_IntBib::COM_KOHA_LEGACY, - 'comm_params' => serialize($params)]); + 'comm_params' => serialize(array_merge($params, ['id_bib' => 987]))]); - $this->fixture(Class_Users::class, - ['id' => 5, - 'login' => 'foo', - 'password' => 'bar', - 'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB, - 'idabon' => 'foo', - 'id_site' => 56, - 'id_int_bib' => 56, - 'id_sigb' => null]); + $this->fixture(Class_Bib::class, + ['id' => 987, + 'libelle' => 'VS Library', + 'visibilite' => Class_Bib::V_DATA]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 15, + 'libelle' => 'VS', + 'id_origine' => 'VS', + 'id_bib' => 987]); $this->postDispatch('/opac/auth/login', ['username' => 'foo', 'password' => 'bar']); } - /** @test */ - public function userFooShouldBeLoggedAndCreated() { + public function fooData() : array { + return [[667, fn($user) => $user->getId()], + ['foo', fn($user) => $user->getLogin()], + ['VS Library', fn($user) => $user->getLibelleBib()], + [987, fn($user) => $user->getIdIntBib()]]; + } + + + /** + * @test + * @dataProvider fooData + */ + public function newUserFooShouldBeSavedWithExpectedData($expected, $foo_data) { $user = Class_Users::getIdentity(); - $this->assertNotNull($user); - $this->assertEquals('foo', $user->getLogin()); - $this->assertNotEquals(5, $user->getId()); - $this->assertEquals('Pasc Library', $user->getLibelleBib()); - $this->assertEquals(56, $user->getIdIntBib()); + $this->assertEquals($expected, $foo_data($user)); } } @@ -2929,7 +2931,7 @@ class AuthControllerPostLoginOpsysWithExceptionTest extends AbstractControllerTe $this->fixture(Class_IntBib::class, ['id' => 44 , 'comm_sigb' => Class_IntBib::COM_OPSYS, - 'comm_params' => serialize(['url_serveur' => ''])]); + 'comm_params' => serialize(['url_serveur' => 'http://astrolabe.com/opsys.wsdl'])]); $service = (new Class_Testing_WebService_SIGB_Opsys_Service(null)) ->whenCalled('getEmprunteur') ->answers(Class_WebService_SIGB_Emprunteur::newInstance(2233, 'harlock')->beValid()) @@ -2944,7 +2946,9 @@ class AuthControllerPostLoginOpsysWithExceptionTest extends AbstractControllerTe ->whenCalled('providesAuthentication') ->answers(true); - Class_WebService_SIGB_Opsys::setService(['url_serveur' => '','id_bib' => 44,'type' => 2], + Class_WebService_SIGB_Opsys::setService(['url_serveur' => 'http://astrolabe.com/opsys.wsdl', + 'id_bib' => 44, + 'type' => 2], $service); $this->postDispatch('/opac/auth/login', @@ -3116,3 +3120,95 @@ class AuthControllerOrpheeTest Class_Users::findFirstBy([ 'login' => '0010900000753'])->getIdIntBib()); } } + + + + +class AuthControllerLoggedActivateWithKohaCodifAnnexeWithEmptyComParamSuccessTest extends AuthControllerNobodyLoggedTestCase { + public function setUp() : void + { + parent::setUp(); + + $this->fixture(Class_Bib::class, + ['id' => 10, + 'libelle'=>'Myriam', + ]); + + $params = ['url_serveur' => 'http://mon-koha-de-test.org', + 'api_user' => 'bokeh.ap', + 'api_pass' => 'scrt', + 'loans_per_page' => 20]; + + $int_bib = $this->fixture(Class_IntBib::class, + ['id' => 10, + 'id_bib' => 10, + 'sigb' => Class_IntBib::SIGB_KOHA, + 'nom_court' => 'Myriam', + 'comm_sigb' => Class_IntBib::COM_KOHA, + 'comm_params' => $params + ]); + $int_bib->assertSave(); + + $this->fixture(Class_Bib::class, + ['id' => 14, + 'libelle'=>'Joinville-le-point', + ]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 123, + 'code' => 'BDM', + 'libelle'=> 'Blog du Modérateur', + 'id_origine' => 'BDM', + 'id_bib' => 14, + ]); + + $empty_bib = $this->fixture(Class_IntBib::class, + ['id' => 14, + 'id_bib'=> 14, + 'nom_court' => 'JoinVille', + 'comm_sigb' => Class_IntBib::SIGB_NONE, + 'sigb' => Class_IntBib::SIGB_NONE, + ]); + Class_HttpClientFactory::forTest() + ->addPostRequestWithResponse('http://mon-koha-de-test.org:80', + ['service' => 'AuthenticatePatron', + 'username' => 'JohnDoe', + 'password' => 's3cr3t'], + KohaFixtures::xmlAuthenticatePatronOk() + ) + ->addRequestWithResponse('http://mon-koha-de-test.org:80?service=GetPatronInfo&patron_id=96138&show_contact=1&show_loans=0&show_holds=1', + kohaFixtures::xmlGetPatronInfoLaure() + ) + ->addRequestWithResponse('http://mon-koha-de-test.org:80?service=GetPatronInfo&patron_id=572&show_contact=1&show_loans=0&show_holds=1', + kohaFixtures::xmlGetPatronInfoLaure()) + ->addRequestWithResponse('http://mon-koha-de-test.org:80?service=GetPatronInfo&patron_id=572&show_contact=0&show_loans=1&show_holds=0&loans_per_page=20&loans_page=1', + kohaFixtures::xmlGetPatronInfoLaure() + ); + Class_CommSigb::shouldThrowError(true); + Class_Webservice_Sigb_AbstractRESTService::shouldThrowError(true); + + $this->postDispatch('/opac/auth/boite-login', + [ + 'username'=>'JohnDoe', + 'password' => 's3cr3t']); + + Class_Users::clearCache(); + } + + + /** @test */ + public function userCreatedShouldBeLinkedToIntBib10() { + $user = Class_Users::findFirstBy(['login' => 'JohnDoe']); + $this->assertEquals(10, $user->getIdIntBib()); + return $user; + } + + + /** + * @depends userCreatedShouldBeLinkedToIntBib10 + * @test + */ + public function userCreatedShouldBeLinkedToBib14($user) { + $this->assertEquals(14, $user->getIdSite()); + } +} diff --git a/tests/application/modules/opac/controllers/AuthControllerWithNanookTest.php b/tests/application/modules/opac/controllers/AuthControllerWithNanookTest.php index 7f540cdb7bd6356bbfd885ed61843d30fb5dae90..a478a4c413581313bcb354d35813055faf365e48 100644 --- a/tests/application/modules/opac/controllers/AuthControllerWithNanookTest.php +++ b/tests/application/modules/opac/controllers/AuthControllerWithNanookTest.php @@ -233,13 +233,14 @@ class AuthControllerWithNanookPostSecurePasswordWithMailAndUnsecurePassword , '<?xml version="1.0" encoding="utf-8"?><GetPatronInfo><patronId>9876</patronId><mail>name@server.tld</mail><barcode>03456</barcode></GetPatronInfo>'); - $this->postDispatch('/opac/auth/do-secure-password', ['card' => 'ZBTIC1234', - 'current_password' => '1987', - 'secure_password' => 'rox@r#1', - 'confirm_password' => 'rox@r#1', - 'pattern' => '/^(?=.*[^0-9])(?=.*\d).{6,}$/', - 'password_hint' => 'doit faire au moins 6', - ]); + $this->postDispatch('/opac/auth/do-secure-password', + ['card' => 'ZBTIC1234', + 'current_password' => '1987', + 'secure_password' => 'rox@r#1', + 'confirm_password' => 'rox@r#1', + 'pattern' => '/^(?=.*[^0-9])(?=.*[0-9]).{6,}$/', + 'password_hint' => 'doit faire au moins 6', + ]); } @@ -289,13 +290,14 @@ class AuthControllerWithNanookPostDoSecurePasswordWithWrongCard ->addRequestWithResponse($this->nanook_service_url.'service/AuthenticatePatron/username/ZBTIC1234/password/1987', '<?xml version="1.0" encoding="UTF-8"?><AuthenticatePatron><error>PatronNotFound</error></AuthenticatePatron>'); - $this->postDispatch('/opac/auth/do-secure-password', ['card' => 'ZBTIC1234', - 'current_password' => '1987', - 'secure_password' => 'rox@r#1', - 'confirm_password' => 'rox@r#1', - 'pattern' => '/^(?=.*[^0-9])(?=.*\d).{6,}$/', - 'password_hint' => 'doit faire au moins 6', - ]); + $this->postDispatch('/opac/auth/do-secure-password', + ['card' => 'ZBTIC1234', + 'current_password' => '1987', + 'secure_password' => 'rox@r#1', + 'confirm_password' => 'rox@r#1', + 'pattern' => '/^(?=.*[^0-9])(?=.*[0-9]).{6,}$/', + 'password_hint' => 'doit faire au moins 6', + ]); } @@ -337,26 +339,28 @@ class AuthControllerWithNanookPostDoSecurePasswordWithErrorsTest /** @test */ public function formShouldDisplayErrorPasswordDoesNotMatch() { - $this->postDispatch('/opac/auth/do-secure-password', ['card' => 'ZBTIC1234', - 'current_password' => '1987', - 'secure_password' => 'rox@r#1', - 'confirm_password' => 'rouk1', - 'pattern' => '/^(?=.*[^0-9])(?=.*\d).{6,}$/', - 'password_hint' => 'doit faire au moins 6', - ]); + $this->postDispatch('/opac/auth/do-secure-password', + ['card' => 'ZBTIC1234', + 'current_password' => '1987', + 'secure_password' => 'rox@r#1', + 'confirm_password' => 'rouk1', + 'pattern' => '/^(?=.*[^0-9])(?=.*[0-9]).{6,}$/', + 'password_hint' => 'doit faire au moins 6', + ]); $this->assertXPathContentContains('//li', 'Les champs \'Mot de passe\' sont différents'); } /** @test */ public function formShouldDisplayErrorPasswordDoesNotFollowPattern() { - $this->postDispatch('/opac/auth/do-secure-password', ['card' => 'ZBTIC1234', - 'current_password' => '1987', - 'secure_password' => 'pouet', - 'confirm_password' => 'pouet', - 'pattern' => '/^(?=.*[^0-9])(?=.*\d).{6,}$/', - 'password_hint' => 'doit faire au moins 6', - ]); + $this->postDispatch('/opac/auth/do-secure-password', + ['card' => 'ZBTIC1234', + 'current_password' => '1987', + 'secure_password' => 'pouet', + 'confirm_password' => 'pouet', + 'pattern' => '/^(?=.*[^0-9])(?=.*[0-9]).{6,}$/', + 'password_hint' => 'doit faire au moins 6', + ]); $this->assertXPathContentContains('//li', 'doit faire au moins 6'); } } @@ -503,7 +507,6 @@ class AuthControllerWithNanookPostAxelLoginNoMemberships class AuthControllerWithNanookPostAxelLoginWithExistingMemberships extends AuthControllerWithNanookPostAxelLoginTestCase { - protected function _prepareMemberships(){ parent::_prepareMemberships(); $this->fixture(Class_Membership::class, @@ -662,3 +665,144 @@ class AuthControllerWithNanookPostAxelLoginWithRoleLevelModoBibWithoutLabelButEx $this->assertEquals(0, Class_User_Membership::count()); } } + + + + +abstract class AuthControllerWithNanookPostAxelLoginWithCodifAnnexeTestCase + extends AuthControllerNanookTestCase { + public function setUp() :void + { + parent::setUp(); + Class_WebService_SIGB_AbstractRESTService::shouldThrowError(true); + + $params = ['url_serveur' => 'http://localhost:8080/afi_Nanook/ilsdi/', + 'id_bib' => 6, + 'type' => Class_IntBib::COM_NANOOK]; + + ZendAfi_Auth::getInstance()->clearIdentity(); + + $this->fixture(Class_Bib::class, + ['id' => 6, + 'libelle' => 'Cran']); + + $this->fixture(Class_IntBib::class, + ['id' => 6, + 'sigb' => Class_IntBib::SIGB_NANOOK, + 'comm_sigb' => Class_IntBib::COM_NANOOK, + 'comm_params' => serialize($params)]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 7, + 'code' => 1, + 'id_origine' => 1, + 'id_bib' => 6, + 'libelle' => 'Cran']); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 5, + 'code' => 2, + 'id_origine' => 2, + 'id_bib' => 5, + 'libelle' => 'Seynod']); + + Class_WebService_SIGB_Nanook::reset(); + + $this->_web_client = $this->mock() + ->whenCalled('open_url') + ->with('http://localhost:8080/afi_Nanook/ilsdi/service/AuthenticatePatron/username/Axel/password/2022') + ->answers(NanookFixtures::axelAuthenticatePatron()) + + ->whenCalled('open_url') + ->with('http://localhost:8080/afi_Nanook/ilsdi/service/GetPatronInfo/patronId/8') + ->answers(NanookFixtures::axelPatronInfo()) + + ->whenCalled('hasErrors') + ->answers(false) + + ->beStrict(); + + + $this->_service = Class_WebService_SIGB_Nanook_Service::newInstance() + ->setServerRoot('http://localhost:8080/afi_Nanook/ilsdi/') + ->setWebClient($this->_web_client); + + $params = ['url_serveur' => 'http://localhost:8080/afi_Nanook/ilsdi/', + 'id_bib' => 5, + 'type' => Class_IntBib::COM_NANOOK]; + + Class_WebService_SIGB_Nanook::setService($params, $this->_service); + + $params = ['url_serveur' => 'http://localhost:8080/afi_Nanook/ilsdi/', + 'id_bib' => 6, + 'type' => Class_IntBib::COM_NANOOK]; + + Class_WebService_SIGB_Nanook::setService($params, $this->_service); + + $this->postDispatch('/opac/auth/login', + ['username' => 'Axel', + 'password' => '2022']); + } +} + + + + +class AuthControllerWithNanookPostAxelLoginWithTwoPossibleIdIntBibTest + extends AuthControllerWithNanookPostAxelLoginWithCodifAnnexeTestCase { + public function setUp() : void + { + parent::setUp(); + + $this->postDispatch('/opac/auth/login', + ['username' => 'Axel', + 'password' => '2022']); + } + + + /** @test */ + public function oneUserShouldBeCreatedWithIdIntBib6() { + $this->assertEquals(Class_Users::findFirstBy(['login' => 'Axel'])->getIdIntBib(), 6); + } +} + + + +class AuthControllerWithNanookPostAxelLoginWithTwoDifferentNanokNetworkTest + extends AuthControllerWithNanookPostAxelLoginWithCodifAnnexeTestCase { + public function setUp() :void + { + parent::setUp(); + + $params = ['url_serveur' => 'http://Myotherhost:8080/afi_Nanook/ilsdi/', + 'id_bib' => 7, + 'type' => Class_IntBib::COM_NANOOK]; + + $this->fixture(Class_IntBib::class, + ['id' => 7, + 'sigb' => Class_IntBib::SIGB_NANOOK, + 'comm_sigb' => Class_IntBib::COM_NANOOK, + 'comm_params' => serialize($params)]); + + $this->fixture(Class_Bib::class, + ['id' => 7, + 'libelle' => 'Barberaz']); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 1, + 'code' => 1, + 'id_origine' => 1, + 'id_bib' => 7, + 'libelle' => 'Barberaz']); + + $this->postDispatch('/opac/auth/login', + ['username' => 'Axel', + 'password' => '2022']); + } + + + /** @test */ + public function oneUserShouldBeCreatedWith() { + $this->assertEquals(Class_Users::findFirstBy(['login' => 'Axel'])->getIdIntBib(), 6); + } +} diff --git a/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php b/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php index ae390fe0959793eb58049b6fe262c8251c701fca..1ee619935bdcdffc964db1d91b9f62ae7317cc74 100644 --- a/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php +++ b/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php @@ -901,7 +901,7 @@ class NoticeAjaxControllerExemplairesWithOtherAnnexTest 'id_int_bib' => 6, 'id_notice' => 123, 'id_origine' => '369667', - 'annexe' => 'MOUL', + 'annexe' => 86, 'section' => 'A9', 'emplacement' => '42', 'cote' => 'VOD-T-DLJ', @@ -921,16 +921,21 @@ class NoticeAjaxControllerExemplairesWithOtherAnnexTest 'id_notice' => 125, 'cote' => 'VOD', 'dispo' => 'Disponible'])]]); + + $this->fixture(Class_CodifAnnexe::class, ['id' => 86, + 'id_bib' => 6, + 'id_origine' => 21, + 'code' => 21]); } /** @test */ - public function facetsShouldBeUpdatedWithAnnex21() { + public function facetsShouldBeUpdatedWithAnnex86() { $this->dispatch('noticeajax/exemplaires/id/123'); Class_Notice::clearCache(); - $this->assertEquals('D78092 A3029 A9751 A117014 A117015 M37414 G464 HNNNN0002 HNANA0002 T0 B6 SA9 E42 Y21 V6 HNRNR0001', + $this->assertEquals('D78092 A3029 A9751 A117014 A117015 M37414 G464 HNNNN0002 HNANA0002 T0 B6 SA9 E42 Y86 V6 HNRNR0001', Class_notice::find(123)->getFacettes()); - $this->assertEquals('F_D78092 F_A3029 F_A9751 F_A117014 F_A117015 F_M37414 F_G464 F_HNNNN0002 F_HNANA0002 F_T0 F_B6 F_SA9 F_E42 F_Y21 F_V6 F_HNRNR0001', + $this->assertEquals('F_D78092 F_A3029 F_A9751 F_A117014 F_A117015 F_M37414 F_G464 F_HNNNN0002 F_HNANA0002 F_T0 F_B6 F_SA9 F_E42 F_Y86 F_V6 F_HNRNR0001', Class_notice::find(123)->getFacets()); } } diff --git a/tests/application/modules/opac/controllers/RechercheControllerIdentifiersTest.php b/tests/application/modules/opac/controllers/RechercheControllerIdentifiersTest.php index 4dc0baf93100c162d018e9742816484e2127c6d6..7e9a2b91cd8e1abb9ba7c5070d414cfc2b54315c 100644 --- a/tests/application/modules/opac/controllers/RechercheControllerIdentifiersTest.php +++ b/tests/application/modules/opac/controllers/RechercheControllerIdentifiersTest.php @@ -26,15 +26,26 @@ class RechercheControllerIdentifiersIdSigbTest parent::setUp(); $this->fixture(Class_CodifAnnexe::class, - ['id' => 1, - 'id_bib' => 456, + ['id' => 3, + 'id_bib' => 4, + 'code' => 2, 'id_origine' => 2]); $this->fixture(Class_Exemplaire::class, ['id' => 34, 'id_bib' => 456, + 'id_int_bib' => 456, 'id_notice' => 345, + 'id_origine' => 12, + 'code_barres' => '12256663233656', + ]); + + $this->fixture(Class_Exemplaire::class, + ['id' => 348989, + 'id_bib' => 4, 'id_int_bib' => 1, + 'annexe' => 3, + 'id_notice' => 345, 'id_origine' => 12, 'code_barres' => '12256663233656', ]); @@ -54,7 +65,7 @@ class RechercheControllerIdentifiersIdSigbTest /** @test */ public function withRightIdsResponseShouldRedirectToViewNoticeId345() { - $this->dispatch('/recherche/viewnotice/id_sigb/12/id_site/2'); + $this->dispatch('/recherche/viewnotice/id_sigb/12/id_site/3'); $this->assertRedirectTo('/recherche/viewnotice/id/345'); } @@ -68,7 +79,7 @@ class RechercheControllerIdentifiersIdSigbTest /** @test */ public function withIdSIB12AndRecordTypeAuthorityShouldRedirectToViewNoticeId678() { - $this->dispatch('/recherche/viewnotice/id_sigb/12/id_site/2/record_type/2'); + $this->dispatch('/recherche/viewnotice/id_sigb/12/id_bib/456/record_type/2'); $this->assertRedirectTo('/recherche/viewnotice/id/678'); } @@ -95,9 +106,9 @@ class RechercheControllerIdentifiersIdSigbTest /** @test */ - public function withUnknownIdSiteShouldThrowError() { + public function withUndefinedIdSiteShouldThrowError() { try { - $this->dispatch('/recherche/viewnotice/id_sigb/12/id_site/3'); + $this->dispatch('/recherche/viewnotice/id_sigb/12/id_site/45'); } catch (Zend_Controller_Action_Exception $e){ $this->assertTrue(true); } @@ -126,14 +137,6 @@ class RechercheControllerIdentifiersIdSigbTest $this->dispatch('/recherche/viewnotice/id_sigb/12', false); $this->assertResponseCode(400); } - - - /** @test */ - public function withIdIntBib1AndIdSite2ShouldThrow400() { - $this->dispatch('/recherche/viewnotice/id_sigb/12/id_site/2/id_int_bib/1', - false); - $this->assertResponseCode(400); - } } @@ -148,12 +151,14 @@ class RechercheControllerIdentifiersIdSigbFilteredTest $this->fixture(Class_CodifAnnexe::class, ['id' => 1, 'id_bib' => 456, + 'code' => 2, 'id_origine' => 2]); $this->fixture(Class_Exemplaire::class, ['id' => 5, 'id_notice' => 883, 'id_bib' => 456, + 'annexe' => 1, 'id_int_bib' => 0, 'id_origine' => 12, 'code_barres' => null, @@ -163,8 +168,9 @@ class RechercheControllerIdentifiersIdSigbFilteredTest ['id' => 34, 'id_bib' => 456, 'id_notice' => 345, - 'id_int_bib' => 1, + 'id_int_bib' => 456, 'id_origine' => 12, + 'annexe' => 1, 'code_barres' => '12256663233656', ]); } @@ -178,8 +184,8 @@ class RechercheControllerIdentifiersIdSigbFilteredTest /** @test */ - public function withIdSigbAndIdSite2ShouldRedirectToViewNoticeId345() { - $this->dispatch('/recherche/viewnotice/id_sigb/12/id_site/2'); + public function withIdSigb12AndIdSite2ShouldRedirectToViewNoticeId345() { + $this->dispatch('/recherche/viewnotice/id_sigb/12/id_site/1'); $this->assertRedirectTo('/recherche/viewnotice/id/345'); } } diff --git a/tests/application/modules/opac/controllers/RechercheControllerReservationPergameTest.php b/tests/application/modules/opac/controllers/RechercheControllerReservationPergameTest.php index 02d1c90b2f737c0d9cbb49b02e8981c85cfbb79f..04fbce972bb42b562c25b7dcc4d04e20441d7d7e 100644 --- a/tests/application/modules/opac/controllers/RechercheControllerReservationPergameTest.php +++ b/tests/application/modules/opac/controllers/RechercheControllerReservationPergameTest.php @@ -26,47 +26,62 @@ abstract class RechercheControllerReservationPergameTestCase extends AbstractCon public function setUp(): void { parent::setUp(); - $this->fixture('Class_Bib', + $bib_toulon = $this->fixture(Class_Bib::class, ['id' => 1]); - $int_bib_toulon = $this->fixture('Class_IntBib', ['id' => 1, - 'comm_sigb' => Class_IntBib::COM_PERGAME, - 'comm_params' => ['url_serveur' => 'bib-toulon.sud', - 'Autoriser_docs_disponibles' => 1], - 'id_bib' => 1]); + $int_bib_toulon = $this->fixture(Class_IntBib::class, + ['id' => 1, + 'comm_sigb' => Class_IntBib::COM_PERGAME, + 'comm_params' => ['url_serveur' => 'bib-toulon.sud', + 'Autoriser_docs_disponibles' => 1], + 'id_bib' => 1]); - $this->fixture('Class_Bib', + $bib_can = $this->fixture(Class_Bib::class, ['id' => 2]); - $this->fixture('Class_IntBib', ['id' => 2, - 'comm_sigb' => Class_IntBib::COM_PERGAME, - 'comm_params' => ['url_serveur' => 'bib-canne.sud', - 'Autoriser_docs_disponibles' => 1], - 'id_bib' => 2]); + $int_bib_canne = $this->fixture(Class_IntBib::class, + ['id' => 2, + 'comm_sigb' => Class_IntBib::COM_PERGAME, + 'comm_params' => ['url_serveur' => 'bib-canne.sud', + 'Autoriser_docs_disponibles' => 1], + 'id_bib' => 2]); - $bib_mars = $this->fixture('Class_Bib', ['id' => 3]); + $this->fixture(Class_CodifAnnexe::class, + ['id' => 2, + 'libelle' => 'Canne', + 'id_bib' => 2, + 'id_origine' => 2]); - $jacques = $this->fixture('Class_Users', ['id' => 1, - 'login' => 'jacques', - 'password' => 'secret', - 'idabon' => '1414', - 'ordreabon' => '1', - 'bib' => $bib_mars, - 'int_bib' => $int_bib_toulon]); + $bib_mars = $this->fixture(Class_Bib::class, ['id' => 3]); + $jacques = $this->fixture(Class_Users::class, + ['id' => 1, + 'login' => 'jacques', + 'password' => 'secret', + 'idabon' => '1414', + 'ordreabon' => '1', + 'bib' => $bib_mars, + 'int_bib' => $int_bib_toulon]); - ZendAfi_Auth::getInstance()->logUser($jacques); - $this->fixture('Class_Notice', ['id' => 31084, - 'titres' => 'TITEUF TITEF FILLES FIL C00 EST NUL']); + ZendAfi_Auth::getInstance()->logUser($jacques); - $this->fixture('Class_Exemplaire', ['id' => 1142445, - 'id_notice' => 31084, - 'code_barres' => '0229923321', - 'id_origine' => '00021243', - 'id_int_bib' => 2, - 'id_bib' => 2, - 'annexe' => 2]); + $this->fixture(Class_Notice::class, + ['id' => 31084, + 'titres' => 'TITEUF TITEF FILLES FIL C00 EST NUL']); + + $this->fixture(Class_CodifAnnexe::class, ['id' => 2, + 'code' => 'Deux', + 'id_origine' => 'Deux']); + + $this->fixture(Class_Exemplaire::class, + ['id' => 1142445, + 'id_notice' => 31084, + 'code_barres' => '0229923321', + 'id_origine' => '00021243', + 'id_int_bib' => 2, + 'id_bib' => 2, + 'annexe' => 2]); } } @@ -78,10 +93,9 @@ class RechercheControllerReservationPergameWithPickupToItemLibrary public function setUp(): void { parent::setUp(); - $this->fixture('Class_CosmoVar', ['id' => 'site_retrait_resa', - 'valeur' => 0]); + Class_CosmoVar::setValueOf('site_retrait_resa', Class_CosmoVar::PICKUP_LOCATION_ITEM); - $this->dispatch('recherche/reservationajax/id_bib/2/copy_id/1142445/code_annexe/2',true); + $this->dispatch('recherche/reservationajax/id_bib/2/copy_id/1142445/code_annexe/2'); } @@ -89,7 +103,7 @@ class RechercheControllerReservationPergameWithPickupToItemLibrary public function holdShouldHaveBeenCreatedWithCanneLibrary() { $reservation = Class_Reservation::findFirstBy(['id_notice_origine' => '00021243', 'idabon' => 1414]); - $this->assertEquals(2, $reservation->getIdSite()); + $this->assertEquals('Deux', $reservation->getIdSite()); } } @@ -101,10 +115,9 @@ class RechercheControllerReservationPergameWithPickupToPatronLibrary public function setUp(): void { parent::setUp(); - $this->fixture('Class_CosmoVar', ['id' => 'site_retrait_resa', - 'valeur' => 2]); + Class_CosmoVar::setValueOf('site_retrait_resa', Class_CosmoVar::PICKUP_LOCATION_PATRON); - $this->dispatch('recherche/reservationajax/id_bib/8/copy_id/1142445/code_annexe/18',true); + $this->dispatch('recherche/reservationajax/id_bib/8/copy_id/1142445/code_annexe/18'); } diff --git a/tests/application/modules/opac/controllers/RechercheControllerReservationTest.php b/tests/application/modules/opac/controllers/RechercheControllerReservationTest.php index 5d1c2bd5e4a9ecb7af5e59dca07f4f9313627e31..10690fcb73fb44ed5d5b7745ac0ddbac3e4383c5 100644 --- a/tests/application/modules/opac/controllers/RechercheControllerReservationTest.php +++ b/tests/application/modules/opac/controllers/RechercheControllerReservationTest.php @@ -20,6 +20,10 @@ */ +require_once 'tests/fixtures/NanookFixtures.php'; +require_once 'tests/fixtures/KohaFixtures.php'; + + abstract class RechercheControllerReservationTestCase extends AbstractControllerTestCase { @@ -28,8 +32,20 @@ abstract class RechercheControllerReservationTestCase public function setUp(): void { parent::setUp(); - Class_CosmoVar::setValueOf('site_retrait_resa', - 1); + Class_CosmoVar::setValueOf('site_retrait_resa', Class_CosmoVar::PICKUP_LOCATION_CHOICE); + + $pierre = + $this->fixture(Class_Users::class, + ['id' => 789789, + 'login' => 'Pierre', + 'password' => 'secret!@', + 'idabon' => 789789, + 'id_sigb' => 8798, + 'id_site' => 12, + 'id_int_bib' => 12, + 'role_level' => 2]); + + ZendAfi_Auth::getInstance()->logUser($pierre); $this->fixture(Class_CodifAnnexe::class, ['id' => 2, @@ -43,13 +59,46 @@ abstract class RechercheControllerReservationTestCase 'id_origine' => '37', 'libelle' => 'Cran']); + $this->fixture(Class_Notice::class, + ['id' => 124, + 'titre' => 'Aimer' + ]); + + $this->fixture(Class_IntBib::class, + ['id' => 12, + 'comm_sigb' => Class_IntBib::COM_NANOOK, + 'comm_params' => ['url_serveur' => 'http://valensol.net', + 'provides_pickup_locations' => '1']]); + + $this->fixture(Class_Exemplaire::class, + ['id' => 13425, + 'id_origine' => 12, + 'id_int_bib' => 12, + 'notice_id' => 124, + 'code_barres' => '1242', + 'annexe' => 2 + ]); + + Class_HttpClientFactory::forTest(); + $this->_xpath = new Storm_Test_XPath; } + + + /** @test @see http://forge.afi-sa.fr/issues/90710 */ + public function nanookShouldHaveBeenCalled() { + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->checkCalls( $this); + } } + + + abstract class RechercheControllerReservationWithPickupChoiceTestCase extends RechercheControllerReservationTestCase { @@ -65,13 +114,21 @@ abstract class RechercheControllerReservationWithPickupChoiceTestCase class RechercheControllerReservationPickupAjaxActionWithChosenPickupTest - extends RechercheControllerReservationWithPickupChoiceTestCase { + extends RechercheControllerReservationTestCase { public function setUp(): void { parent::setUp(); - $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=36'); - + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::axelPatronInfo()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/0/patronId/0/siteId/0', + NanookFixtures::pickupLocationsOkAnswersAnnecyAndCran()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/12/patronId/8798/siteId/36', + NanookFixtures::pickupLocationsOkAnswersAnnecyAndCran()); + + $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=36©_id=13425'); $this->_json = json_decode($this->_response->getBody()); } @@ -101,14 +158,26 @@ class RechercheControllerReservationPickupAjaxActionWithChosenPickupTest class RechercheControllerReservationPickupAjaxActionPostTest - extends RechercheControllerReservationWithPickupChoiceTestCase { + extends RechercheControllerReservationTestCase { + + protected $_response; /** @test */ public function responseShouldRedirectToReservationajaxAction() { + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::axelPatronInfo()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/0/patronId/0/siteId/0', + NanookFixtures::pickupLocationsOkAnswersAnnecyAndCran()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/12/patronId/8798/siteId/36', + NanookFixtures::pickupLocationsOkAnswersAnnecyAndCran()); + $this->postDispatch('recherche/reservation-pickup-ajax', ['id_bib' => 2, 'id_origine' => 12, + 'copy_id' => 13425, 'code_annexe' => '36']); $this->assertRedirectTo('/recherche/reservationajax/code_annexe/36'); @@ -117,10 +186,20 @@ class RechercheControllerReservationPickupAjaxActionPostTest /** @test */ public function withoutAvailablePickupLocationPostResponseShouldAnswerError() { + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::axelPatronInfo()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/0/patronId/0/siteId/0', + NanookFixtures::pickupLocationsOkAnswersAnnecyAndCran()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/12/patronId/8798/siteId/36', + NanookFixtures::pickupLocationsOkAnswersAnnecyAndCran()); + Class_CodifAnnexe::deleteBy([]); $this->postDispatch('recherche/reservation-pickup-ajax', ['id_bib' => 2, 'id_origine' => 12, + 'copy_id' => 13425, 'code_annexe' => '36']); $json = json_decode($this->_response->getBody(), true); $this->assertContains('Aucun site de retrait disponible', $json['content']); @@ -129,8 +208,17 @@ class RechercheControllerReservationPickupAjaxActionPostTest /** @test */ public function withoutAvailablePickupLocationGETResponseShouldAnswerError() { + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::axelPatronInfo()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/0/patronId/0/siteId/0', + NanookFixtures::pickupLocationsOkAnswersAnnecyAndCran()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/12/patronId/8798/siteId/36', + NanookFixtures::pickupLocationsOkAnswersAnnecyAndCran()); + Class_CodifAnnexe::deleteBy([]); - $this->dispatch('recherche/reservation-pickup-ajax/id_bib/2/id_origine/12'); + $this->dispatch('recherche/reservation-pickup-ajax/id_bib/2/id_origine/12/copy_id/13425'); $json = json_decode($this->_response->getBody(), true); $this->assertContains('Aucun site de retrait disponible', $json['content']); } @@ -138,11 +226,19 @@ class RechercheControllerReservationPickupAjaxActionPostTest /** @test */ public function withPopupAndInspectorGadgetResponseShouldStillSendJSON() { - Zend_Registry::get('session')->inspectorCalls = [serialize(new Class_InspectorGadget_ServiceCall('I', 'love', 'milk', 'coffee', '418'))]; + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::axelPatronInfo()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/0/patronId/0/siteId/0', + NanookFixtures::pickupLocationsOkAnswersAnnecyAndCran()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/12/patronId/8798/siteId/36', + NanookFixtures::pickupLocationsOkAnswersAnnecyAndCran()); $this->postDispatch('recherche/reservation-pickup-ajax/render/popup/inspector_gadget/1', ['id_bib' => 2, 'id_origine' => 12, + 'copy_id' => 13425, 'code_annexe' => '36']); $this->assertNotNull($json = json_decode($this->_response->getBody(), true)); $this->assertContains('<script>location.reload();</script>', $json['content']); @@ -151,9 +247,19 @@ class RechercheControllerReservationPickupAjaxActionPostTest /** @test */ public function responseShouldContainsJsonRedirectToReservationajaxAction() { + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::axelPatronInfo()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/0/patronId/0/siteId/0', + NanookFixtures::pickupLocationsOkAnswersAnnecyAndCran()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/12/patronId/8798/siteId/36', + NanookFixtures::pickupLocationsOkAnswersAnnecyAndCran()); + $this->postDispatch('recherche/reservation-pickup-ajax/render/popup', ['id_bib' => 2, 'id_origine' => 12, + 'copy_id' => 13425, 'code_annexe' => '36']); $json = json_decode($this->_response->getBody(), true); $this->assertContains('<script>location.reload();</script>', $json['content']); @@ -164,7 +270,7 @@ class RechercheControllerReservationPickupAjaxActionPostTest class RechercheControllerReservationPickupAjaxActionTestWithChosenPickupDispatch - extends RechercheControllerReservationWithPickupChoiceTestCase { + extends RechercheControllerReservationTestCase { public $jajm; public $nanook; @@ -173,47 +279,27 @@ class RechercheControllerReservationPickupAjaxActionTestWithChosenPickupDispatch public function setUp(): void { parent::setUp(); - $bib = $this - ->fixture(Class_IntBib::class, - ['id' => 1, - 'comm_sigb' => Class_IntBib::COM_NANOOK, - 'comm_params' => ['url_serveur' => 'http://bib.valensol.net']]); - - $this->jajm = $this - ->fixture(Class_Users::class, - ['id' => 1, - 'login' => 'jajm', - 'password' => 'secret', - 'idabon' => '0000007', - 'int_bib' => $bib, - ]); - - $this->nanook = (new Class_Testing_WebService_SIGB_Nanook_Service()) - ->whenCalled('reserverExemplaire')->answers(['erreur' => '', 'statut' => true]) - ->whenCalled('isConnected')->answers(true); - - Class_WebService_SIGB_Nanook::setService(['url_serveur' => 'http://bib.valensol.net', - 'id_bib' => 1, - 'type' => Class_IntBib::COM_NANOOK,], - $this->nanook); - - ZendAfi_Auth::getInstance()->logUser($this->jajm); - - $this->fixture('Class_Exemplaire', ['id' => 12]); - $mock_transport = new MockMailTransport(); Zend_Mail::setDefaultTransport($mock_transport); - $this->dispatch('recherche/reservationajax/id/11760/id_int_bib/23/id_bib/23/id_origine/594105/code_annexe/23/render/popup/copy_id/12'); + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::axelPatronInfo()) + ->addRequestWithResponse('http://valensol.net:80/service/HoldTitle/bibId/12/patronId/8798/pickupLocation/36', + NanookFixtures::xmlHoldTitleSuccess()); + + $this->dispatch('recherche/reservationajax/id/11760/id_int_bib/12/id_bib/12/id_origine/12/code_annexe/36/render/popup/copy_id/13425'); + $this->_json = json_decode($this->_response->getBody()); $this->_sent_mails = $mock_transport->getSentMails(); } /** @test */ - public function parameterCodeAnnexeShouldBeUsedForReservation() { - $this->assertEquals('23', - $this->nanook->getAttributesForLastCallOn('reserverExemplaire')[2]); + public function responseShouldContaisSuccessHeldMessage() { + $this->assertEquals('Votre réservation est enregistrée.<br>Nous vous informerons quand le document sera disponible', + $this->_json->content); } @@ -235,46 +321,25 @@ class RechercheControllerReservationPickupAjaxActionTestWithPatronLibraryPickup public function setUp(): void { parent::setUp(); - - $bib = $this - ->fixture(Class_IntBib::class, - ['id' => 12, - 'comm_sigb' => Class_IntBib::COM_NANOOK, - 'comm_params' => ['url_serveur' => 'http://bib.valensol.net']]); - - $this->jajm = $this->fixture(Class_Users::class, - ['id' => 1, - 'login' => 'jajm', - 'password' => 'secret', - 'idabon' => '0000007', - 'int_bib' => $bib]); - - $this->nanook = (new Class_Testing_WebService_SIGB_Nanook_Service) - ->whenCalled('isConnected')->answers(true) - ->whenCalled('providesPickupLocations')->answers(false) - ->whenCalled('getUserAnnexe')->answers('12'); - - Class_WebService_SIGB_Nanook::setService(['url_serveur' => 'http://bib.valensol.net', - 'id_bib' => 12, - 'type' => Class_IntBib::COM_NANOOK,], - $this->nanook); - - ZendAfi_Auth::getInstance()->logUser($this->jajm); - Class_CosmoVar::setValueOf('site_retrait_resa', Class_CosmoVar::PICKUP_LOCATION_PATRON); - $this->fixture(Class_Exemplaire::class, - ['id' => 12]); + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::axelPatronInfo()) + ->addRequestWithResponse('http://valensol.net:80/service/HoldTitle/bibId/12/patronId/8798/pickupLocation/12', + NanookFixtures::xmlHoldTitleSuccess()); - $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=36©_id=12'); + $this->dispatch('recherche/reservation-pickup-ajax?id_bib=12&id_origine=12&code_annexe=36©_id=13425'); + $this->_json = json_decode($this->_response->getBody()); } /** @test */ - public function getUserAnnexeResultShouldBeUsedForReservation() { - $this->assertEquals('12', - $this->nanook->getAttributesForLastCallOn('reserverExemplaire')[2]); + public function responseShouldContaisSuccessHeldMessage() { + $this->assertEquals('Votre réservation est enregistrée.<br>Nous vous informerons quand le document sera disponible', + $this->_json->content); } } @@ -290,46 +355,34 @@ class RechercheControllerReservationPickupAjaxActionTestWithItemLibraryPickup public function setUp(): void { parent::setUp(); - $bib = $this->fixture(Class_IntBib::class, - ['id' => 1, - 'comm_sigb' => Class_IntBib::COM_NANOOK, - 'comm_params' => ['url_serveur' => 'http://bib.valensol.net']]); - - $this->jajm = $this->fixture(Class_Users::class, - ['id' => 1, - 'login' => 'jajm', - 'password' => 'secret', - 'idabon' => '0000007', - 'int_bib' => $bib - ]); - - $this->nanook = (new Class_Testing_WebService_SIGB_Nanook_Service()) - ->whenCalled('isConnected')->answers(true) - ->whenCalled('providesPickupLocations')->answers(false) - ->whenCalled('reserverExemplaire')->answers(['statut' => true, 'erreur' => '']); - - Class_WebService_SIGB_Nanook::setService(['url_serveur' => 'http://bib.valensol.net', - 'id_bib' => 1, - 'type' => Class_IntBib::COM_NANOOK,], - $this->nanook); - - ZendAfi_Auth::getInstance()->logUser($this->jajm); - Class_CosmoVar::setValueOf('site_retrait_resa', Class_CosmoVar::PICKUP_LOCATION_ITEM); + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::axelPatronInfo()) + ->addRequestWithResponse('http://valensol.net:80/service/HoldTitle/bibId/12/patronId/8798/pickupLocation/36', + NanookFixtures::xmlHoldTitleSuccess()); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 36, + 'code' => '36', + 'id_origine' => '36']); + $this->fixture(Class_Exemplaire::class, ['id' => 12, 'annexe' => 36]); - $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=36©_id=12'); + $this->dispatch('recherche/reservation-pickup-ajax?id_bib=12&id_origine=12&code_annexe=36©_id=13425'); + $this->_json = json_decode($this->_response->getBody()); } /** @test */ - public function itemAnnexeShouldBeUsedForReservation() { - $this->assertEquals('36', - $this->nanook->getAttributesForLastCallOn('reserverExemplaire')[2]); + public function responseShouldContaisSuccessHeldMessage() { + $this->assertEquals('Votre réservation est enregistrée.<br>Nous vous informerons quand le document sera disponible', + $this->_json->content); } } @@ -442,173 +495,166 @@ class RechercheControllerReservationWithWebServiceKohaTest { parent::setUp(); - $webservice = 'http://bib.valensol.net'; - $bib = $this->fixture(Class_IntBib::class, - ['id' => 1, - 'comm_sigb' => Class_IntBib::COM_KOHA_LEGACY, - 'comm_params' => ['url_serveur' => $webservice]]); + $this->fixture(Class_IntBib::class, + ['id' => 1, + 'comm_sigb' => Class_IntBib::COM_KOHA_LEGACY, + 'comm_params' => ['url_serveur' => 'http://bib.valensol.net']]); + + $jajm = + $this->fixture(Class_Users::class, + ['id' => 1, + 'login' => 'jajm', + 'password' => 'secret', + 'id_int_bib' => 1, + 'id_site' => 1, + 'role_level' => 2, + 'idabon' => 12890, + 'id_sigb' => 7891738 + ]); + + ZendAfi_Auth::getInstance()->logUser($jajm); - $this->jajm = $this->fixture(Class_Users::class, - ['id' => 1, - 'login' => 'jajm', - 'password' => 'secret', - 'int_bib' => $bib, - ]); + $this->fixture(Class_CodifAnnexe::class, + ['id' => 123, + 'code' => 'VS', + 'libelle' => 'Valensole', + 'id_int_bib' => 1, + 'id_origine' => 'VS']); - ZendAfi_Auth::getInstance()->logUser($this->jajm); - $this->koha = new Class_Testing_WebService_SIGB_KohaLegacy_Service(); - $this->koha->setServerRoot( $webservice); + $koha_profile = Class_IntProfilDonnees::forKoha(); + $koha_profile->save(); - Class_WebService_SIGB_KohaLegacy::setService(['url_serveur' => $webservice, - 'id_bib' => 1, - 'type' => Class_IntBib::COM_KOHA_LEGACY], - $this->koha); - } + $this->fixture(Class_Notice::class, + ['id' => 54, + 'type_doc' => Class_Typedoc::LIVRE, + 'titre_principal' => 'Robinson Crusoe', + 'auteur_principal' => 'Daniel Dafoe']); + $this->fixture(Class_Exemplaire::class, + ['id' => 456, + 'code_barres' => 'MALLE00010', + 'id_origine' => 789, + 'id_notice' => 54, + 'id_origine' => 32468, + 'id_int_bib' => 1, + 'id_data_profile' => $koha_profile->getId(), + 'annexe' => 123]) + ->setZone995(serialize([['code' => '9', + 'valeur' => '446297']])); - protected function dispatchAndCheckContentEquals($expected) { - $this->dispatch('/recherche/reservationajax/id_bib/1/copy_id/456/code_annexe/VS'); - $this->json = json_decode($this->_response->getBody()); - $this->assertEquals($expected, $this->json->content); + Class_HttpClientFactory::forTest(); } /** @test */ - public function reservationAjaxWithItemRequiringCalendarHoldShouldRedirectToReservationCalendarAjax() { - $item = $this->fixture(Class_Exemplaire::class, - ['id' => 456, - 'code_barres' => 123, - 'id_int_bib' => 1, - 'annexe' => 'VS', - 'notice' => $this->fixture(Class_Notice::class, - ['id' => 8890, - 'titre_principal' => 'Elementaire mon cher polar', - 'auteur_principal' => 'Conan Doyle'])]); - - $item->setSigbExemplaire((Class_WebService_SIGB_Koha_Exemplaire::newInstance()) - ->doRequiresCalendarHold() - ->setId(2) - ->beReservable())->save(); - - $this->jajm->setIdabon(395749); + public function reservationAjaxWithItemRequiringCalendarHoldShouldRedirectToReservationCalendarAjax() + { + Class_IntBib::find(1) + ->setCommParams(['url_serveur' => 'http://bib.valensol.net', + 'grouped_holds_itypes' => 'pretnormal']) + ->assertSave(); - $this->koha - ->whenCalledDo('reserverExemplaire', [], fn() => $this->_error('error')); + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://bib.valensol.net:80?service=HoldTitle&patron_id=7891738&bib_id=32468&request_location=127.0.0.1&pickup_location=VS', + KohaFixtures::holdTitleResponseWithItemHoldsItypeOut()) + ->addRequestWithResponse('http://bib.valensol.net:80?service=GetPatronInfo&patron_id=7891738&show_contact=1&show_loans=0&show_holds=1', + kohaFixtures::xmlGetPatronInfoJamesBond()) + ->addRequestWithResponse('http://bib.valensol.net:80?service=GetRecords&id=32468', + KohaFixtures::xmlGetRecordLeChatLePlusMignonDuMonde()); $this->dispatch('/recherche/reservationajax/id_bib/1/copy_id/456/code_annexe/VS'); - $this->assertRedirectTo('/recherche/reservation-calendar-ajax/id_bib/1/copy_id/456/code_annexe/VS'); } /** @test */ public function withMatchingHoldMessageShouldContainsPickupLocation() { - $item = $this->fixture(Class_Exemplaire::class, - ['id' => 456, - 'code_barres' => 123, - 'id_int_bib' => 1]); - - $response = $this->_prepareEmprunteurHolding($item, 'Valensole'); - $expected_message = 'Votre réservation est enregistrée.<br>Nous vous informerons quand le document sera disponible pour être retiré à : Valensole'; - $this->_dispatchWithEmprunteurAndAssertContentEquals($response, - $expected_message); - } - + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://bib.valensol.net:80?service=GetRecords&id=32468', + KohaFixtures::xmlGetRecordLeChatLePlusMignonDuMonde()) + ->addRequestWithResponse('http://bib.valensol.net:80?service=HoldTitle&patron_id=7891738&bib_id=32468&request_location=127.0.0.1', + KohaFixtures::holdTitleResponseWithItemHoldsItypeOut()) + ->addRequestWithResponse('http://bib.valensol.net:80?service=HoldTitle&patron_id=7891738&bib_id=32468&request_location=127.0.0.1&pickup_location=VS', + KohaFixtures::holdTitleResponseWithItemHoldsItypeOut()) + ->addRequestWithResponse('http://bib.valensol.net:80?service=GetPatronInfo&patron_id=7891738&show_contact=1&show_loans=0&show_holds=1', + kohaFixtures::xmlGetPatronInfoJamesBond()); - /** @test */ - public function withMatchingHoldAndRecordWithBRInTitleMessageShouldContainsPickupLocationAndRecordTitleAuthor() { - $exemplaire = $this->fixture(Class_Exemplaire::class, - ['id' => 456, - 'code_barres' => 123, - 'id_int_bib' => 1, - 'notice' => $this->fixture(Class_Notice::class, - ['id' => 8890, - 'titre_principal' => 'Albator <br /> Arcadia', - 'auteur_principal' => 'Matsumoto'])]); - $this->_dispatchWithEmprunteurAndAssertContentEquals( - $this->_prepareEmprunteurHolding($exemplaire, 'Valensole'), - 'Votre réservation est enregistrée.<br>Nous vous informerons quand le document \'Albator Arcadia / Matsumoto\' sera disponible pour être retiré à : Valensole'); + $this->dispatch('/recherche/reservationajax/id_bib/1/copy_id/456/code_annexe/VS'); + $this->json = json_decode($this->_response->getBody()); + $this->assertEquals('Votre réservation est enregistrée.<br>Nous vous informerons quand le document \'Robinson Crusoe / Daniel Dafoe\' sera disponible pour être retiré à : Valensole', + $this->json->content); } /** @test */ public function withMatchingHoldAndRecordWithoutAuthorMessageShouldContainsPickupLocationAndRecordTitleOnly() { - $exemplaire = $this->fixture(Class_Exemplaire::class, - ['id' => 456, - 'code_barres' => 123, - 'id_int_bib' => 1, - 'notice' => $this->fixture(Class_Notice::class, - ['id' => 8890, - 'titre_principal' => 'Arcadia'])]); - $this->_dispatchWithEmprunteurAndAssertContentEquals( - $this->_prepareEmprunteurHolding($exemplaire, 'Valensole'), - 'Votre réservation est enregistrée.<br>Nous vous informerons quand le document \'Arcadia\' sera disponible pour être retiré à : Valensole'); - } + Class_Notice::find(54)->setAuteurPrincipal(''); + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://bib.valensol.net:80?service=GetRecords&id=32468', + KohaFixtures::xmlGetRecordLeChatLePlusMignonDuMonde()) + ->addRequestWithResponse('http://bib.valensol.net:80?service=HoldTitle&patron_id=7891738&bib_id=32468&request_location=127.0.0.1&pickup_location=VS', + KohaFixtures::holdTitleResponseWithItemHoldsItypeOut()) + ->addRequestWithResponse('http://bib.valensol.net:80?service=HoldTitle&patron_id=7891738&bib_id=32468&request_location=127.0.0.1', + KohaFixtures::holdTitleResponseWithItemHoldsItypeOut()) + ->addRequestWithResponse('http://bib.valensol.net:80?service=GetPatronInfo&patron_id=7891738&show_contact=1&show_loans=0&show_holds=1', + kohaFixtures::xmlGetPatronInfoJamesBond()); + $this->dispatch('/recherche/reservationajax/id_bib/1/copy_id/456/code_annexe/VS'); - /** @test */ - public function withoutMatchingHoldMessageShouldContainsDocumentNotFound() { - $this->_dispatchWithEmprunteurAndAssertContentEquals( - $this->_prepareEmprunteurHolding(null, 'Valensole'), - 'Document introuvable'); + $this->json = json_decode($this->_response->getBody()); + $this->assertEquals('Votre réservation est enregistrée.<br>Nous vous informerons quand le document \'Robinson Crusoe\' sera disponible pour être retiré à : Valensole', + $this->json->content); } /** @test */ - public function withMatchingHoldAndNoPickupLocationShouldNotContainsPickupLocation() { - $this->_dispatchWithEmprunteurAndAssertContentEquals($this->_prepareEmprunteurHolding($this->fixture(Class_Exemplaire::class, - ['id' => 456]), - null), - 'Votre réservation est enregistrée.<br>Nous vous informerons quand le document sera disponible'); - } - - - protected function _prepareEmprunteurHolding($item, $pickup_label) { - $this->jajm->setIdabon(395749); - - $exemplaire = (new Class_WebService_SIGB_Exemplaire(2)) - ->setExemplaireOPAC($item); - $hold = new Class_WebService_SIGB_Reservation(2, $exemplaire); - $hold->setPickupLocationLabel($pickup_label) - ->setCodeBarre(123); - - $emprunteur_jajm = Class_WebService_SIGB_Emprunteur::newInstance(2, 'jajm'); - $emprunteur_jajm->reservationsAdd($hold); - return $emprunteur_jajm; - } - + public function withoutMatchingHoldMessageShouldContainsDocumentNotFound() { + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://bib.valensol.net:80?service=GetRecords&id=32468', + KohaFixtures::xmlGetRecordLeChatLePlusMignonDuMonde()) + ->addRequestWithResponse('http://bib.valensol.net:80?service=HoldTitle&patron_id=7891738&bib_id=32468&request_location=127.0.0.1', + KohaFixtures::holdTitleResponseError()) + ->addRequestWithResponse('http://bib.valensol.net:80?service=HoldTitle&patron_id=7891738&bib_id=32468&request_location=127.0.0.1&pickup_location=VS', + KohaFixtures::holdTitleResponseError()); - protected function _dispatchWithEmprunteurAndAssertContentEquals($emprunteur, $content) { - $this->koha - ->whenCalledDefaultAnswers('reserverExemplaire', ['statut' => true, - 'erreur' => '', - 'popup' => false]) - ->whenCalledDefaultAnswers('getEmprunteur',$emprunteur); + $this->dispatch('/recherche/reservationajax/id_bib/1/copy_id/456/code_annexe/VS'); + $this->json = json_decode($this->_response->getBody()); - $this->dispatchAndCheckContentEquals($content); + $this->assertEquals('Réservation impossible', + $this->json->content); } /** @test */ public function popupResultContentWithWebServiceErrorShouldContainsErreurDeCommunication() { - $this->jajm->setIdabon(395749); + Class_IntBib::find(1) + ->clearInstanceCache() + ->setCommSigb('n\'importe quoi'); - $this->_prepareEmprunteurHolding($this->fixture(Class_Exemplaire::class, - ['id' => 456]), - 'Valensole'); - $this->koha->whenCalled('isConnected')->answers(false); - - $this->dispatchAndCheckContentEquals("Une erreur de communication avec le serveur a fait échouer la requête. Merci de signaler ce problème à la bibliothèque."); + $this->dispatch('/recherche/reservationajax/id_bib/1/copy_id/456/code_annexe/VS'); + $this->json = json_decode($this->_response->getBody()); + $this->assertEquals('Impossible de contacter le serveur de votre bibliothèque.', + $this->json->content); } /** @test */ public function withoutIdAbonpopupResultContentShouldContainsVousDevezVousConnecterSousVotreNumeroDeCarte() { - $this->_prepareEmprunteurHolding($this->fixture(Class_Exemplaire::class, - ['id' => 456]), - 'Valensole'); - $this->jajm->setIdabon(null)->save(); - $this->dispatchAndCheckContentEquals("Vous devez vous connecter sous votre numéro de carte pour effectuer une réservation."); + Class_Users::find(1)->setIdabon('')->save(); + + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://bib.valensol.net:80?service=GetRecords&id=32468', + KohaFixtures::xmlGetRecordLeChatLePlusMignonDuMonde()); + + $this->dispatch('/recherche/reservationajax/id_bib/1/copy_id/456/code_annexe/VS'); + $this->json = json_decode($this->_response->getBody()); + $this->assertEquals('Vous devez vous connecter sous votre numéro de carte pour effectuer une réservation.', + $this->json->content); } } @@ -1151,8 +1197,10 @@ class RechercheControllerReservationWithMailFormValidPostTest -abstract class RechercheControllerReservationPickupAjaxWithNanookPickupLocationsTestCase - extends RechercheControllerReservationTestCase{ + +class RechercheControllerReservationPickupAjaxNanookPickupLocationsItemLibraryHoldTest + extends RechercheControllerReservationTestCase +{ public $jajm; public $nanook; @@ -1161,54 +1209,35 @@ abstract class RechercheControllerReservationPickupAjaxWithNanookPickupLocations { parent::setUp(); - $bib = $this - ->fixture(Class_IntBib::class, - ['id' => 12, - 'comm_sigb' => Class_IntBib::COM_NANOOK, - 'comm_params' => ['url_serveur' => 'http://bib.valensol.net']]); + Class_CosmoVar::setValueOf('site_retrait_resa', Class_CosmoVar::PICKUP_LOCATION_PATRON); - $this->jajm = $this->fixture(Class_Users::class, - ['id' => 1, - 'login' => 'jajm', - 'password' => 'secret', - 'idabon' => '0000007', - 'int_bib' => $bib]); - - $this->nanook =(new Class_Testing_WebService_SIGB_Nanook_Service()) - ->whenCalled('isConnected')->answers(true) - ->whenCalled('providesPickupLocations')->answers(true) - - ->whenCalled('pickupLocationsFor') - ->answers(['36' => 'Annecy', - '37' => 'Cran', - '45' => 'Istres', - '99' => 'Lunel <strong>(Disponible)</strong>']); - - Class_WebService_SIGB_Nanook::setService(['url_serveur' => 'http://bib.valensol.net', - 'id_bib' => 12, - 'type' => Class_IntBib::COM_NANOOK,], - $this->nanook); + $this->fixture(Class_Notice::class, + ['id' => 7, + 'type_doc' => Class_Typedoc::LIVRE, + 'titre_principal' => 'Robinson Crusoe', + 'auteur_principal' => 'Daniel Dafoe']); - ZendAfi_Auth::getInstance()->logUser($this->jajm); + Class_Exemplaire::find('13425') + ->setIdOrigine('7307') + ->setIdNotice(7) + ->assertSave(); - $this->fixture(Class_Exemplaire::class, - ['id' => 12]); - } + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/HoldTitle/bibId/7307/patronId/8798/pickupLocation/12', + NanookFixtures::xmlHoldTitleSuccess()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::xmlGetPatronChristelDelpeyroux()); + $this->dispatch('recherche/reservation-pickup-ajax?id_bib=12&id_origine=12&code_annexe=36©_id=13425'); - public function choices() { - return [[36], [37], [45]]; + $this->_json = json_decode($this->_response->getBody()); } - /** - * @test - * @dataProvider choices - */ - public function choiceShouldBePresent($location_id) { - $this->_xpath - ->assertXPath($this->_json->content, - '//input[@type="radio"][@value="' . $location_id . '"]'); + /** @test */ + public function jsonReturnedVotreReservationEstEnregistree() { + $this->assertEquals('Votre réservation est enregistrée.<br>Nous vous informerons quand le document \'Robinson Crusoe / Daniel Dafoe\' sera disponible pour être retiré à : Vanne', $this->_json->content); } } @@ -1216,7 +1245,7 @@ abstract class RechercheControllerReservationPickupAjaxWithNanookPickupLocations class RechercheControllerReservationPickupAjaxNanookPickupLocationsPrecheckPatronTest - extends RechercheControllerReservationPickupAjaxWithNanookPickupLocationsTestCase { + extends RechercheControllerReservationTestCase { public $nanook; @@ -1224,12 +1253,28 @@ class RechercheControllerReservationPickupAjaxNanookPickupLocationsPrecheckPatro { parent::setUp(); - $this->nanook->whenCalled('getUserAnnexe')->answers('45') - ->whenCalled('reserverExemplaire')->answers(['status' => true, - 'erreur' => '']); + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::axelPatronInfo()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/0/patronId/0/siteId/0', + NanookFixtures::pickupLocationsAnswersAnnecyAndCranIstresLunel()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/12/patronId/8798/siteId/36', + NanookFixtures::pickupLocationsAnswersAnnecyAndCranIstresLunel()); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 5, + 'code' => '45', + 'id_origine' => '45', + 'libelle' => 'Istres']); - $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=37©_id=12'); + $this->fixture(Class_IntBib::class, + ['id' => 45, + 'comm_sigb' => Class_IntBib::COM_NANOOK, + 'comm_params' => ['url_serveur' => 'http://valensol.net', + 'provides_pickup_locations' => '1']]); + $this->dispatch('recherche/reservation-pickup-ajax?id_bib=12&id_origine=12&code_annexe=45©_id=13425'); $this->_json = json_decode($this->_response->getBody()); } @@ -1245,26 +1290,48 @@ class RechercheControllerReservationPickupAjaxNanookPickupLocationsPrecheckPatro class RechercheControllerReservationPickupAjaxNanookPickupLocationsPrecheckRequestedTest - extends RechercheControllerReservationPickupAjaxWithNanookPickupLocationsTestCase { + extends RechercheControllerReservationTestCase +{ - public $nanook; - - public function setUp(): void + public function setUp() : void { parent::setUp(); - $this->nanook->whenCalled('getUserAnnexe')->answers('66'); + Class_CosmoVar::setValueOf('site_retrait_resa', Class_CosmoVar::PICKUP_LOCATION_CHOICE); + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::axelPatronInfo()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/0/patronId/0/siteId/0', + NanookFixtures::pickupLocationsAnswersAnnecyAndCranIstresLunel()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/12/patronId/8798/siteId/36', + NanookFixtures::pickupLocationsAnswersAnnecyAndCranIstresLunel()); + + $this->dispatch('recherche/reservation-pickup-ajax?id_bib=12&id_origine=12&code_annexe=36©_id=13425'); + $this->_json = json_decode($this->_response->getBody()); + } - $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=37©_id=12'); - $this->_json = json_decode($this->_response->getBody()); + public function choices() { + return [[36], [37], [45], [99]]; + } + + + /** + * @test + * @dataProvider choices + */ + public function choiceShouldBePresent($location_id) { + $this->_xpath + ->assertXPath($this->_json->content, + '//input[@type="radio"][@value="' . $location_id . '"]'); } /** @test */ public function cranShouldBeChecked() { $this->_xpath - ->assertXPath($this->_json->content, '//input[@type="radio"][@value="37"][@checked]'); + ->assertXPath($this->_json->content, '//input[@type="radio"][@value="36"][@checked]'); } } @@ -1272,7 +1339,7 @@ class RechercheControllerReservationPickupAjaxNanookPickupLocationsPrecheckReque class RechercheControllerReservationPickupAjaxNanookPickupLocationsNoPrecheckTest - extends RechercheControllerReservationPickupAjaxWithNanookPickupLocationsTestCase { + extends RechercheControllerReservationTestCase { public $nanook; @@ -1280,9 +1347,16 @@ class RechercheControllerReservationPickupAjaxNanookPickupLocationsNoPrecheckTes { parent::setUp(); - $this->nanook->whenCalled('getUserAnnexe')->answers('66'); + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::axelPatronInfo()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/0/patronId/0/siteId/0', + NanookFixtures::pickupLocationsAnswersAnnecyAndCranIstresLunel()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/12/patronId/8798/siteId/36', + NanookFixtures::pickupLocationsAnswersAnnecyAndCranIstresLunel()); - $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=77©_id=12'); + $this->dispatch('recherche/reservation-pickup-ajax?id_bib=12&id_origine=12&code_annexe=77©_id=13425'); $this->_json = json_decode($this->_response->getBody()); } @@ -1302,7 +1376,7 @@ class RechercheControllerReservationPickupAjaxNanookPickupLocationsNoPrecheckTes class RechercheControllerReservationPickupAjaxNanookPickupLocationsStrongInLabel - extends RechercheControllerReservationPickupAjaxWithNanookPickupLocationsTestCase { + extends RechercheControllerReservationTestCase { public $nanook; @@ -1310,9 +1384,22 @@ class RechercheControllerReservationPickupAjaxNanookPickupLocationsStrongInLabel { parent::setUp(); - $this->nanook->whenCalled('getUserAnnexe')->answers('66'); + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::axelPatronInfo()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/0/patronId/0/siteId/0', + NanookFixtures::pickupLocationsAnswersAnnecyAndCranIstresLunel()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPickupLocation/bibId/12/patronId/8798/siteId/36', + NanookFixtures::pickupLocationsAnswersAnnecyAndCranIstresLunel()); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 5, + 'code' => '99', + 'id_origine' => '99', + 'libelle' => 'Lunel']); - $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=99©_id=12'); + $this->dispatch('recherche/reservation-pickup-ajax?id_bib=12&id_origine=12&code_annexe=99©_id=13425'); $this->_json = json_decode($this->_response->getBody()); } @@ -1322,9 +1409,54 @@ class RechercheControllerReservationPickupAjaxNanookPickupLocationsStrongInLabel * @see https://forge.afi-sa.net/issues/94332 * @test */ - public function LunelShouldContainStrong() { - $this->_xpath - ->assertXPath($this->_json->content, '//strong',$this->_json->content); + public function formShouldContainsStrongLunel() { + $this->assertContains('Lunel <strong>(Disponible)</strong>', + $this->_json->content); + } +} + + + +class RechercheControllerReservationPickupAjaxLocationsByPatronStrongInLocationLabel + extends RechercheControllerReservationTestCase { + + public function setUp() : void + { + parent::setUp(); + + Class_CosmoVar::setValueOf('site_retrait_resa', Class_CosmoVar::PICKUP_LOCATION_PATRON); + + $this->fixture(Class_Notice::class, + ['id' => 7, + 'type_doc' => Class_Typedoc::LIVRE, + 'titre_principal' => 'Robinson Crusoe', + 'auteur_principal' => 'Daniel Dafoe']); + + Class_Exemplaire::find('13425') + ->setIdOrigine('12501') + ->setIdNotice(7) + ->assertSave(); + + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->addRequestWithResponse('http://valensol.net:80/service/HoldTitle/bibId/12501/patronId/8798/pickupLocation/12', + NanookFixtures::xmlHoldTitleSuccess()) + ->addRequestWithResponse('http://valensol.net:80/service/GetPatronInfo/patronId/8798', + NanookFixtures::xmlGetPatronChristelDelpeyroux()); + + $this->dispatch('recherche/reservation-pickup-ajax?id_bib=12&id_origine=12&code_annexe=37©_id=13425'); + + $this->_json = json_decode($this->_response->getBody()); + } + + + /** + * @see https://forge.afi-sa.net/issues/94332 + * @test + */ + public function formShouldContainsStrongLunel() { + $this->assertEquals($this->_json->content, + 'Votre réservation est enregistrée.<br>Nous vous informerons quand le document \'Robinson Crusoe / Daniel Dafoe\' sera disponible pour être retiré à : Lunel <strong>(Disponible)</strong>'); } } @@ -1332,7 +1464,7 @@ class RechercheControllerReservationPickupAjaxNanookPickupLocationsStrongInLabel abstract class RechercheControllerReservationPickupAjaxAndNotifyByMailEnabledTestCase - extends RechercheControllerReservationWithPickupChoiceTestCase { + extends RechercheControllerReservationTestCase { public $jajm; public $mock; @@ -1363,6 +1495,7 @@ abstract class RechercheControllerReservationPickupAjaxAndNotifyByMailEnabledTes $this->fixture(Class_CodifAnnexe::class, ['id' => 34, + 'id_bib' => 1, 'libelle'=>'BDM', 'id_origine' => 23]); @@ -1390,6 +1523,7 @@ abstract class RechercheControllerReservationPickupAjaxAndNotifyByMailEnabledTes <title>Mireille l\'abeille</title> <pickup_location>Bibliothèque Départementale de la Meuse</pickup_location> </HoldTitle>') + ->whenCalled('getServerRoot')->answers('http://bib.valensol.net/cgi-bin/koha/ilsdi.pl') ->whenCalled('reserverExemplaire')->answers(['statut'=>true,'erreur'=>'']); Class_WebService_SIGB_KohaLegacy::setService(['url_serveur' => 'http://bib.valensol.net/cgi-bin/koha/ilsdi.pl', @@ -1401,9 +1535,10 @@ abstract class RechercheControllerReservationPickupAjaxAndNotifyByMailEnabledTes $this->fixture(Class_Exemplaire::class, ['id' => 12, + 'id_bib' => 1, 'id_origine' =>13, 'code_barres' =>12341, - 'id_bib' => 1, + 'int_bib' => $this->_intbib, 'notice'=> $this ->fixture(Class_Notice::class, ['id'=>54, @@ -1547,18 +1682,17 @@ class RechercheControllerReservationPickupAjaxAndNotifyByMailWithMailEnabledWith -require_once 'tests/fixtures/KohaFixtures.php'; - class RechercheControllerReservationWithWebServiceKohaAndItypesTest extends AbstractControllerTestCase { protected $_response; protected $_xpath; + protected $json; public function setUp(): void { parent::setUp(); - Class_WebService_SIGB_AbstractRESTService::shouldThrowError(true); + Class_CosmoVar::setValueOf('site_retrait_resa', 1); $koha_service_params = ['url_serveur' => 'http://bib.valensol.net', 'grouped_holds_itypes' => " PRET_MALLE @@ -1570,31 +1704,22 @@ PRET_VALISE", 'id_bib' => 1, 'type' => 5]; - $bib = $this->fixture(Class_IntBib::class, + $this->fixture(Class_IntBib::class, ['id' => 1, 'comm_sigb' => Class_IntBib::COM_KOHA_LEGACY, 'comm_params' => $koha_service_params]); - $http_client = (new Class_Testing_WebService_SimpleWebClient) - ->whenCalled('open_url') - ->with('http://bib.valensol.net?service=GetRecords&id=678') - ->answers(KohaFixtures::getRecordsWithGroupHoldsItypes()); - - Class_WebService_SIGB_KohaLegacy::getService($koha_service_params) - ->setWebClient($http_client); - - $record = - $this->fixture(Class_Notice::class, - ['id' => 8890, - 'titre_principal' => 'Elementaire mon cher polar', - 'auteur_principal' => 'Conan Doyle']); + $this->fixture(Class_Notice::class, + ['id' => 8890, + 'titre_principal' => 'Elementaire mon cher polar', + 'auteur_principal' => 'Conan Doyle']); $this->fixture(Class_Exemplaire::class, ['id' => 456, 'id_origine' => 678, 'code_barres' => 5360246264, 'id_int_bib' => 1, - 'notice' => $record]); + 'id_notice' => 8890]); $this->fixture(Class_CodifAnnexe::class, ['id' => 3, @@ -1610,35 +1735,44 @@ PRET_VALISE", 'libelle' => 'Annecy', 'no_pickup' => '0']); - Class_CosmoVar::setValueOf('site_retrait_resa', 1); + $user = + $this->fixture(Class_Users::class, + ['id' => 1, + 'login' => 'jajm', + 'role_level' => 2, + 'password' => 'secret', + 'id_int_bib' => 1, + 'id_site' => 1, + 'idabon' => '395749' + ]); - $user = $this->fixture(Class_Users::class, - ['id' => 1, - 'login' => 'jajm', - 'password' => 'secret', - 'int_bib' => $bib, - 'id_site' => 3, - 'idabon' => '395749' - ]); + ZendAfi_Auth::getInstance()->logUser($user); $this->_xpath = new Storm_Test_XPath; - ZendAfi_Auth::getInstance()->logUser($user); + + + Class_HttpClientFactory::forTest() + ->addRequestWithResponse('http://bib.valensol.net:80?service=GetRecords&id=678', + KohaFixtures::getRecordsWithGroupHoldsItypes()) + ->addPostRequestWithResponse('http://bib.valensol.net:80', + ['service' => 'AuthenticatePatron', + 'username' => 'jajm', + 'password' => 'secret'], + KohaFixtures::xmlAuthenticatePatronOk()) + ->addRequestWithResponse('http://bib.valensol.net:80?service=GetPatronInfo&patron_id=96138&show_contact=1&show_loans=0&show_holds=1', + KohaFixtures::xmlGetPatronInfoJamesBond()); + } /** @test */ public function reservationShouldSelectUserAnnexeByDefault() { - $emprunteur = new Class_WebService_SIGB_Emprunteur('395749', 'jajm'); - $emprunteur->setLibraryCode('VS'); - Class_CommSigb::setInstance(( new Class_Testing_CommSigb) - ->whenCalledAnswers('ficheAbonne',[] - ,['fiche' => $emprunteur])); - - $this->dispatch('/recherche/reservation-pickup-ajax/id_bib/1/copy_id/456/code_annexe/AN'); + $json = json_decode($this->_response->getBody()); - $this->_xpath - ->assertXPath($json->content, '//input[@type="radio"][@name="code_annexe"][ @value="VS"][ @checked="checked"]', $json->content); + $this->_xpath->assertXPath($json->content, + '//input[@type="radio"][@name="code_annexe"][ @value="VS"][ @checked="checked"]', + $json->content); } @@ -1723,6 +1857,7 @@ class RechercheControllerReservationPickupAjaxWithMailPostAction $this->fixture(Class_Exemplaire::class, ['id' => 45, 'id_bib' => 4, + 'id_int_bib' => 1, 'id_notice' => 4, 'code_barres' => '1234' ]); diff --git a/tests/application/modules/opac/controllers/RechercheControllerTest.php b/tests/application/modules/opac/controllers/RechercheControllerTest.php index da2d5260af63a4f0663054470d42564c361fd55d..9ec2c8fe17d9dbb711fb8f4411af42692258b9d4 100644 --- a/tests/application/modules/opac/controllers/RechercheControllerTest.php +++ b/tests/application/modules/opac/controllers/RechercheControllerTest.php @@ -2774,13 +2774,29 @@ abstract class RechercheControllerPermalinkWithIdIntBibTestCase Class_CosmoVar::setValueOf('mode_doublon', '' . Class_CosmoVar::DOUBLE_SEARCH_NONE); + $this->fixture(Class_CodifAnnexe::class, + ['id' => 3, + 'code' => 'MPL', + 'libelle' => 'Montpellier', + 'id_origine' => 'MPL', + 'id_bib' => 4 + ]); + + $this->fixture(Class_Bib::class, + ['id' => 4, + 'libelle' => 'Montpellier', + 'annexe' => 3, + 'id_origine' => 'MPL' + ]); + Class_Notice::find(15) ->setType($this->_getNoticeType()) ->setExemplaires([$this->fixture(Class_Exemplaire::class, ['id' => 999, 'type' => $this->_getNoticeType(), - 'id_bib' => 1, + 'id_bib' => 4, 'id_int_bib' => 1, + 'annexe' => 3, 'id_origine' => 1111])]) ->assertSave(); @@ -2811,37 +2827,37 @@ class RechercheControllerPermalinkWithIdIntBibAndTypeBibliographicTest /** @test */ public function permalinkShouldBeDisplay() { - $this->assertXPath('//img[contains(@class, "permalink")][contains(@data-url, "/recherche/viewnotice/id_sigb/1111/id_int_bib/1")]'); + $this->assertXPath('//img[contains(@class, "permalink")][contains(@data-url, "/recherche/viewnotice/id_sigb/1111/id_int_bib/1/id_site/3/record_type/1")]'); } /** @test */ public function contextfacebookLinkShouldContainsIdIntBib() { - $this->assertXPath('//div[contains(@class, "reseaux-sociaux")]/img[contains(@onclick, "id_int_bib")]'); + $this->assertXPath('//div[contains(@class, "reseaux-sociaux")]/img[contains(@onclick, "id_site")]'); } /** @test */ public function permalinkShouldNotBeDisplayedWithContextExpressionRecherche() { - $this->assertNotXPath('//img[contains(@class, "permalink")][contains(@data-url, "id_sigb/1111/id_int_bib/1/expressionRecherche")]'); + $this->assertNotXPath('//img[contains(@class, "permalink")][contains(@data-url, "id_sigb/1111/id_site/3/expressionRecherche")]'); } /** @test */ public function permalinkShouldNotBeDisplayedWithIdProfil() { - $this->assertNotXPath('//img[contains(@class, "permalink")][contains(@data-url, "id_sigb/1111/id_int_bib/1?id_profil")]'); + $this->assertNotXPath('//img[contains(@class, "permalink")][contains(@data-url, "id_sigb/1111/id_site/3?id_profil")]'); } /** @test */ public function othersLinkShouldNotBeDisplayedWithIdIntBib() { - $this->assertNotXPath('//a[contains(@href, "id_sigb/1111/id_int_bib/1")]'); + $this->assertNotXPath('//a[contains(@href, "id_sigb/1111/id_site/3")]'); } /** @test */ public function permalinkWithIdIntBibShouldBeDisplayOnlyOnce() { - $this->assertXPathCount('//img[contains(@class, "permalink")][contains(@data-url, "/recherche/viewnotice/id_sigb/1111/id_int_bib/1")]', 1); + $this->assertXPathCount('//img[contains(@class, "permalink")][contains(@data-url, "/recherche/viewnotice/id_sigb/1111/id_int_bib/1/id_site/3")]', 1); } } @@ -2864,13 +2880,13 @@ class RechercheControllerPermalinkWithIdIntBibAndTypeBibliographicInTemplateTest /** @test */ public function permalinkViewNoticeWithIdSigb1111AndIdIntBib1ShouldBeDisplay() { - $this->assertXPath('//body[@data-template="INTONATION"]//a[contains(@class, "view_permalink permalink")][contains(@href, "/recherche/viewnotice/id_sigb/1111/id_int_bib/1")]'); + $this->assertXPath('//body[@data-template="INTONATION"]//a[contains(@class, "view_permalink permalink")][contains(@href, "/recherche/viewnotice/id_sigb/1111/id_int_bib/1/id_site/3")]'); } /** @test */ public function onlyOneLinkShouldContainIdIntBibOne() { - $this->assertXPathCount('//a[contains(@href, "id_int_bib/1")]', 1); + $this->assertXPathCount('//a[contains(@href, "id_site/3")]', 1); } } @@ -2901,13 +2917,13 @@ class RechercheControllerViewNoticePermalinkWithIdIntBibInTemplateTest /** @test */ public function permalinkViewNoticeWithIdSigb1111AndIdIntBib1ShouldBeDisplay() { - $this->assertXPath('//body[@data-template="INTONATION"]//a[contains(@class, "view_permalink permalink")][contains(@href, "/recherche/viewnotice/id_sigb/1111/id_int_bib/1")]'); + $this->assertXPath('//body[@data-template="INTONATION"]//a[contains(@class, "view_permalink permalink")][contains(@href, "/recherche/viewnotice/id_sigb/1111/id_int_bib/1/id_site/3")]'); } /** @test */ public function onlyOneLinkShouldContainIdIntBibOne() { - $this->assertXPathCount('//a[contains(@href, "id_int_bib/1")]', 1); + $this->assertXPathCount('//a[contains(@href, "id_site/3")]', 1); } } diff --git a/tests/application/modules/telephone/controllers/RechercheControllerHarryPotterTest.php b/tests/application/modules/telephone/controllers/RechercheControllerHarryPotterTest.php index 7f40f776c103bbec9d157810c591b50f03c8b273..8219c6978ea74a7de02ee8853b4cb51bab2896ae 100644 --- a/tests/application/modules/telephone/controllers/RechercheControllerHarryPotterTest.php +++ b/tests/application/modules/telephone/controllers/RechercheControllerHarryPotterTest.php @@ -418,7 +418,7 @@ class Telephone_RechercheControllerHarryPotterExemplaireReservableTest $item = $this->fixture(Class_Exemplaire::class, ['id' => 33, 'cote' => 'JRROW', - 'annexe' => 'MOUL', + 'annexe' => 4, 'bib' => $florilege, 'int_bib' => $int_bib_florilege, 'id_int_bib' => 2, diff --git a/tests/application/modules/telephone/controllers/RechercheControllerTest.php b/tests/application/modules/telephone/controllers/RechercheControllerTest.php index 70661eb843561087a3e3c0a297649f4408a71cbd..e43498a30151412931f7dd52e9574226dd81b7df 100644 --- a/tests/application/modules/telephone/controllers/RechercheControllerTest.php +++ b/tests/application/modules/telephone/controllers/RechercheControllerTest.php @@ -353,7 +353,9 @@ class Telephone_RechercheControllerReservationNemoInfoTest extends TelephoneAbst 'titre_principal' => 'Nemo']); $nemo_item_sigb = new Class_WebService_SIGB_Exemplaire(1); - $nemo_item_sigb->beReservable(); + $nemo_item_sigb + ->setCodeAnnexe('PLOP') + ->beReservable(); $nemo_item = $this->fixture(Class_Exemplaire::class, @@ -362,7 +364,7 @@ class Telephone_RechercheControllerReservationNemoInfoTest extends TelephoneAbst 'bib' => $bib, 'int_bib' => $int_bib, 'cote' => 123, - 'annexe' => 'PLOP']); + 'annexe' => 1]); $nemo->setExemplaires([$nemo_item])->save(); diff --git a/tests/fixtures/KohaFixtures.php b/tests/fixtures/KohaFixtures.php index 0f43a1ffa9c61215c743e0126f5cd11a276bd20e..6109eb29111e695d3e42797734bd8865f9945620 100644 --- a/tests/fixtures/KohaFixtures.php +++ b/tests/fixtures/KohaFixtures.php @@ -984,6 +984,14 @@ class KohaFixtures { } + public static function xmlAuthenticatePatronJameBondOk() { + return '<?xml version="1.0" encoding="UTF-8" ?> + <AuthenticatePatron> + <id>007</id> + </AuthenticatePatron>'; + } + + public static function xmlAuthenticatePatronLostCard() { return '<?xml version="1.0" encoding="UTF-8" ?> <AuthenticatePatron> @@ -4075,7 +4083,9 @@ class KohaFixtures { <GetPatronInfo> <borrowernumber>007</borrowernumber> <cardnumber>007</cardnumber> + <branchcode>VS</branchcode> <itype>I_WILL_CRASH_YOU</itype> + <branchcode>VS</branchcode> <holds> <hold> <expirationdate>2019-12-31</expirationdate> @@ -4090,12 +4100,12 @@ class KohaFixtures { <title>Élémentaire mon cher polar</title> <notforloan>0</notforloan> <itemtype>MAL_EXPO</itemtype> - <homebranch>BDY</homebranch> - <holdingbranch>BDY</holdingbranch> + <homebranch>VS</homebranch> + <holdingbranch>VS</holdingbranch> <itype>PRET_MALLE</itype> <biblioitemnumber>96629</biblioitemnumber> </item> - <branchname>BDP</branchname> + <branchname>VS</branchname> <reserve_id>1124</reserve_id> <itemnumber>112194</itemnumber> <status>NEW</status> @@ -5766,6 +5776,20 @@ class KohaFixtures { </HoldItem>'; } + + public static function holdTitleResponseWithEmptyPickupLocation() { + return '<?xml version="1.0" encoding="UTF-8" ?> +<HoldItem> + <pickup_location></pickup_location> +</HoldItem>'; + } + + + public static function holdTitleResponseError() { + return '<?xml version="1.0" encoding="UTF-8" ?>'; + } + + public static function xmlGetRecordLeChatLePlusMignonDuMonde() { return '<?xml version="1.0" encoding="UTF-8" ?> <GetRecords> diff --git a/tests/fixtures/NanookFixtures.php b/tests/fixtures/NanookFixtures.php index 142bc38226ae29bb501a07f695ebad5f5ab10021..9f93f2f2837eafee07386705c2658a25b28e7dde 100644 --- a/tests/fixtures/NanookFixtures.php +++ b/tests/fixtures/NanookFixtures.php @@ -338,7 +338,8 @@ class NanookFixtures { <itemId>7105</itemId> <title>Contes des quatre vents</title> <author>Natha Caputo</author> - <locationLabel>Site Principal</locationLabel> + <locationId>36</locationId> + <locationLabel>Vanne</locationLabel> <priority>1</priority> <availabilityDate>15/06/2012</availabilityDate> </hold> @@ -354,7 +355,7 @@ class NanookFixtures { <itemId>14586</itemId> <title>Le Chant du lac</title> <author>Olympe Bhêly-Quénum</author> - <locationLabel>Site Principal</locationLabel> + <locationLabel><![CDATA[Lunel <strong>(Disponible)</strong>]]></locationLabel> <priority>53</priority> <available>1</available> </hold> @@ -769,6 +770,44 @@ class NanookFixtures { } + public static function pickupLocationsOkAnswersAnnecyAndCran() { + return '<?xml version="1.0" encoding="UTF-8"?> + <pickup_locations> + <pickup_location> + <pickup_location_label>Annecy</pickup_location_label> + <pickup_location_id>36</pickup_location_id> + </pickup_location> + <pickup_location> + <pickup_location_label>Cran library</pickup_location_label> + <pickup_location_id>37</pickup_location_id> + </pickup_location> + </pickup_locations>'; + } + + + public static function pickupLocationsAnswersAnnecyAndCranIstresLunel() { + return '<?xml version="1.0" encoding="UTF-8"?> + <pickup_locations> + <pickup_location> + <pickup_location_label>Annecy</pickup_location_label> + <pickup_location_id>36</pickup_location_id> + </pickup_location> + <pickup_location> + <pickup_location_label>Cran library</pickup_location_label> + <pickup_location_id>37</pickup_location_id> + </pickup_location> +<pickup_location> + <pickup_location_label>Istres</pickup_location_label> + <pickup_location_id>45</pickup_location_id> + </pickup_location> +<pickup_location> + <pickup_location_label><![CDATA[Lunel <strong>(Disponible)</strong>]]></pickup_location_label> + <pickup_location_id>99</pickup_location_id> + </pickup_location> + </pickup_locations>'; + } + + public static function pickupLocationsErrorAnswer() { return '<?xml version="1.0" encoding="UTF-8"?> <GetPickupLocation> diff --git a/tests/library/Class/CodifAnnexeFindByCodeAndBibCacheTest.php b/tests/library/Class/CodifAnnexeFindByCodeAndBibCacheTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b3e3baa3f2c79d2056bd785302efd4ae2d4cdb31 --- /dev/null +++ b/tests/library/Class/CodifAnnexeFindByCodeAndBibCacheTest.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright (c) 2012-2024, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class CodifAnnexeFindByCodeAndBibCacheTest extends ModelTestCase +{ + public function setUp(): void + { + parent::setUp(); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 100, + 'code' => '2', + 'id_origine' => '2', + 'id_bib' => 30]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 101, + 'code' => '2', + 'id_origine' => '2', + 'id_bib' => 5]); + + + Class_CodifAnnexe::findByCodeAndBib('2', 30); + } + + /** @test */ + public function code2AndBib5ShouldGetAnnexeId101() + { + $this->assertEquals(101, Class_CodifAnnexe::findByCodeAndBib('2', 5)->getId()); + } +} diff --git a/tests/library/Class/CommSigbTest.php b/tests/library/Class/CommSigbTest.php index a5f30afaf0503a7cbebfe347bc7f24c12511fdac..52ff8390761e40674f60dc5b8e3ef1655cf83721 100644 --- a/tests/library/Class/CommSigbTest.php +++ b/tests/library/Class/CommSigbTest.php @@ -20,6 +20,7 @@ */ abstract class CommSigbTestCase extends ModelTestCase { + protected string $_url_server = ''; public $comm_sigb; public $florence; @@ -158,31 +159,59 @@ abstract class CommSigbTestCase extends ModelTestCase { } - public function createMockForService($name) { + public function createMockForService(string $name = '') { $class_name = 'Class_Testing_WebService_SIGB_'.$name.'_Service'; $this->mock_service = new $class_name(null, '', '',''); + $this->mock_service + ->whenCalled('getServerRoot') + ->answers($this->_url_server); return $this->mock_service; } + public function successStatus(): array + { + return ['statut' => 1, + 'erreur' =>'']; + } + + + public function prepareLibraryAndService(array $params, + int $comm_type, + string $sigb_name): void + { + Class_IntBib::getLoader() + ->newInstanceWithId(5) + ->setCommParams($params) + ->setCommSigb($comm_type); + $webservice_class = 'Class_WebService_SIGB_'.$sigb_name; + $webservice_class::setService(array_merge($params, + ['id_bib' => 5, + 'type' => $comm_type]), + $this->createMockForService($sigb_name) + ); + } + + /** @test */ public function reserverExemplaireShouldReturnAnArrayWithStatus() { $this->mock_service ->whenCalledAnswers('reserverExemplaire', - [$this->userModel, - $this - ->fixture(Class_Exemplaire::class, - ['id' => '123', 'id_notice' => 7888]), - 'ABC'], - ['statut' => 1, - 'erreur' => '']); - - $this->assertEquals(['statut' => 1, - 'erreur' => ''], + [$this->userModel, + $this + ->fixture(Class_Exemplaire::class, + ['id' => '123', + 'id_notice' => 7888, + 'id_int_bib' => 5]), + 'ABC'], + $this->successStatus()); + + $this->assertEquals($this->successStatus(), $this->comm_sigb ->reserveItem($this ->fixture(Class_Exemplaire::class, ['id' => '123', + 'id_int_bib' => 5, 'id_notice' => 7888]), 'ABC')); @@ -229,11 +258,10 @@ abstract class CommSigbTestCase extends ModelTestCase { /** @test */ public function supprimerReservationShouldReturnStatutOK() { $this->mock_service->whenCalledAnswers('supprimerReservation', - [$this->userModel, 345], - ['statut' => 1, - 'erreur' => '']); + [$this->userModel, 345], + $this->successStatus()); - $this->assertEquals(['statut' => 1, 'erreur' => ''], + $this->assertEquals($this->successStatus(), $this->comm_sigb->supprimerReservation($this->florence, 345)); return $this->zend_cache; } @@ -252,10 +280,10 @@ abstract class CommSigbTestCase extends ModelTestCase { public function prolongerPretShouldReturnStatutOK() { $this->mock_service ->whenCalledAnswers('prolongerPret', - [$this->userModel, 456], ['statut' => 1, - 'erreur' => '']); + [$this->userModel, 456], + $this->successStatus()); - $this->assertEquals(['statut' => 1, 'erreur' => ''], + $this->assertEquals($this->successStatus(), $this->comm_sigb->prolongerPret($this->florence, 456)); return $this->zend_cache; } @@ -281,14 +309,16 @@ class CommSigbAstrolabeOpsysTest extends CommSigbTestCase { { parent::setUp(); - $this->bib_astro = Class_IntBib::getLoader() - ->newInstanceWithId(5) - ->setCommParams(["url_serveur" => 'http://astrolabe.com/opsys.wsdl']) - ->setCommSigb(2); + $this->_url_server = 'http://astrolabe.com/opsys.wsdl'; + $this->prepareLibraryAndService(["url_serveur" => $this->_url_server], + 2, + 'Opsys'); + $this->mock_service + ->setSearchClient($this->mock() + ->whenCalled('getWsdlUrl') + ->answers($this->_url_server)); - Class_WebService_SIGB_Opsys::setService(["url_serveur" => 'http://astrolabe.com/opsys.wsdl', - 'id_bib' => 5, - 'type' => 2], $this->createMockForService('Opsys')); + $this->bib_astro = Class_IntBib::find(5); } @@ -315,15 +345,13 @@ class CommSigbMoulinsVSmartTest extends CommSigbTestCase { { parent::setUp(); - $this->bib_moulins = $this->fixture(Class_IntBib::class, - ['id' => 5, - 'comm_params' => ["url_serveur" => 'http://vpn.agglo-moulins.fr/production/'], - 'comm_sigb' => 4]); + $this->_url_server = 'http://vpn.agglo-moulins.fr/production/'; - Class_WebService_SIGB_VSmart::setService(["url_serveur" => 'http://vpn.agglo-moulins.fr/production/', - 'id_bib' => 5, - 'type' => 4 -],$this->createMockForService('VSmart')); + $this->prepareLibraryAndService(["url_serveur" => $this->_url_server], + 4, + 'VSmart'); + + $this->bib_moulins = Class_IntBib::find(5); } @@ -472,39 +500,36 @@ class CommSigbMoulinsVSmartTest extends CommSigbTestCase { class CommSigbMeuseKohaTest extends CommSigbTestCase { - public $bib_koha; - public $comm_sigb; - public $userModel; - public $mock_service; - protected $_service; public function setUp(): void { parent::setUp(); - $params = ['url_serveur' => 'http://cat-aficg55.biblibre.com/cgi-bin/koha/ilsdi.pl', + $this->_url_server = 'http://cat-aficg55.biblibre.com/cgi-bin/koha/ilsdi.pl'; + + $params = ['url_serveur' => $this->_url_server, 'Codification_disponibilites' => "1:En prêt\r\n2:Réservable"]; - $this->bib_koha = Class_IntBib::getLoader() - ->newInstanceWithId(5) - ->setCommParams(serialize($params)) - ->setCommSigb(5); - $this->_service = $this->createMockForService('KohaLegacy') ; - Class_WebService_SIGB_KohaLegacy::setService(array_merge($params, - ['id_bib' => 5, - 'type' => Class_IntBib::COM_KOHA_LEGACY]), - $this->_service); + $this->prepareLibraryAndService($params, + Class_IntBib::COM_KOHA_LEGACY, + 'KohaLegacy'); + + $this->bib_koha = Class_IntBib::find(5); } /** @test */ public function reserverExemplaireWithParamsReserveAndExpirationDataShouldPassParamsToKohaService() { - $item = $this->fixture(Class_Exemplaire::class, ['id' => '123', 'id_notice' => 7888]); + $item = $this->fixture(Class_Exemplaire::class, + ['id' => '123', + 'id_notice' => 7888, + 'id_int_bib' => 5]); + $this->comm_sigb->reserveItem( $item, 'ABC' ); - $this->assertTrue($this->_service + $this->assertTrue($this->mock_service ->assertMethodWith('reserverExemplaire', [$this->userModel, $item, @@ -520,9 +545,9 @@ class CommSigbMeuseKohaTest extends CommSigbTestCase { 'int_bib' => $this->bib_koha]); $this->mock_service ->whenCalledAnswers('holdsForItem', - [ $item], - ['statut' => true, - 'holds' => []]); + [ $item], + ['statut' => true, + 'holds' => []]); $this->assertEquals(['statut' => true, 'holds' => []], @@ -547,15 +572,16 @@ class CommSigbLocalNanookTest extends CommSigbTestCase { public function setUp(): void { parent::setUp(); - $this->bib_pontault = Class_IntBib::newInstanceWithId(5) - ->setCommParams(["url_serveur" => 'http://192.168.2.3:9080/afi_Nanook-0.7.5/ilsdi/']) - ->setCommSigb(7); + $this->_url_server = 'http://192.168.2.3:9080/afi_Nanook-0.7.5/ilsdi/'; + + $params = ["url_serveur" => $this->_url_server]; - Class_WebService_SIGB_Nanook::setService(['url_serveur' => 'http://192.168.2.3:9080/afi_Nanook-0.7.5/ilsdi/', - 'id_bib' => 5, - 'type' => Class_IntBib::COM_NANOOK,], - $this->createMockForService('Nanook')); + $this->prepareLibraryAndService($params, + Class_IntBib::COM_NANOOK, + 'Nanook'); + + $this->bib_pontault = Class_IntBib::find(5); } @@ -579,15 +605,15 @@ class CommSigbWaterbearTest extends CommSigbTestCase { { parent::setUp(); - $this->bib_pontault = $this->fixture('Class_IntBib', - ['id' => 5, - 'comm_params' => ['url_serveur' => 'http://waterbear.info/bib_ws.php'], - 'comm_sigb' => Class_IntBib::COM_WATERBEAR]); + $this->_url_server = 'http://waterbear.info/bib_ws.php'; + + $params = ["url_serveur" => $this->_url_server]; + $this->prepareLibraryAndService($params, + Class_IntBib::COM_WATERBEAR, + 'Nanook'); - Class_WebService_SIGB_Waterbear::setService( ['url_serveur' => 'http://waterbear.info/bib_ws.php', - 'id_bib' => 5, - 'type' => 14], $this->createMockForService('Waterbear')); + $this->bib_pontault = Class_IntBib::find(5); } @@ -611,14 +637,15 @@ class CommSigbCarthameTest extends CommSigbTestCase { { parent::setUp(); - $this->bib_ifr = Class_IntBib::getLoader() - ->newInstanceWithId(5) - ->setCommParams(["url_serveur" => 'http://ifr.ro/webservices/index.php']) - ->setCommSigb(6); + $this->_url_server = 'http://ifr.ro/webservices/index.php'; + + $params = ["url_serveur" => $this->_url_server]; - Class_WebService_SIGB_Carthame::setService([ "url_serveur" => 'http://ifr.ro/webservices/index.php', - 'id_bib' => 5, - 'type' => 6], $this->createMockForService('Carthame')); + $this->prepareLibraryAndService($params, + Class_IntBib::COM_CARTHAME, + 'Carthame'); + + $this->bib_ifr = Class_IntBib::find(5); } @@ -642,21 +669,20 @@ class CommSigbOrpheeTest extends CommSigbTestCase { { parent::setUp(); - $comm_params = ['url_serveur' => 'http://213.144.218.252:8080/wsOrphee/service.asmx?WSDL']; - $this->bib_stomer = Class_IntBib::getLoader() - ->newInstanceWithId(5) - ->setCommParams($comm_params) - ->setCommSigb(8); + $this->_url_server = 'http://213.144.218.252:8080/wsOrphee/service.asmx?WSDL'; - $emprunteur_florence = Class_WebService_SIGB_Orphee_Emprunteur::newInstance('0123456789', 'Florence'); + $params = ["url_serveur" => $this->_url_server]; - $this->createMockForService('Orphee') - ->whenCalledAnswers('getEmprunteur', [$this->userModel], $emprunteur_florence); + $this->prepareLibraryAndService($params, + Class_IntBib::COM_ORPHEE, + 'Orphee'); - Class_WebService_SIGB_Orphee::setService(array_merge($comm_params, - ['id_bib' => 5, - 'type' => Class_IntBib::COM_ORPHEE]), - $this->mock_service); + $this->bib_stomer = Class_IntBib::find(5); + + $emprunteur_florence = Class_WebService_SIGB_Orphee_Emprunteur::newInstance('0123456789', 'Florence'); + + $this->mock_service + ->whenCalledAnswers('getEmprunteur', [$this->userModel], $emprunteur_florence); } @@ -680,14 +706,15 @@ class CommSigbMicrobibTest extends CommSigbTestCase { { parent::setUp(); - $this->bib_maze = Class_IntBib::getLoader() - ->newInstanceWithId(5) - ->setCommParams(["url_serveur" => 'http://80.11.188.93/webservices/ws_maze.wsdl']) - ->setCommSigb(9); + $this->_url_server = 'http://80.11.188.93/webservices/ws_maze.wsdl'; + + $params = ["url_serveur" => $this->_url_server]; - Class_WebService_SIGB_Microbib::setService([ "url_serveur" => 'http://80.11.188.93/webservices/ws_maze.wsdl', - 'id_bib' => 5, - 'type' => 9], $this->createMockForService('Microbib')); + $this->prepareLibraryAndService($params, + Class_IntBib::COM_MICROBIB, + 'Microbib'); + + $this->bib_maze = Class_IntBib::find(5); } @@ -709,14 +736,15 @@ class CommSigbBiblixNetTest extends CommSigbTestCase { { parent::setUp(); - $this->bib_wormhout = Class_IntBib::getLoader() - ->newInstanceWithId(5) - ->setCommParams(["url_serveur" => 'http://mediathequewormhout.biblixnet.com/exporte_afi']) - ->setCommSigb(10); + $this->_url_server = 'http://mediathequewormhout.biblixnet.com/exporte_afi'; + + $params = ["url_serveur" => $this->_url_server]; - Class_WebService_SIGB_BiblixNet::setService([ "url_serveur" => 'http://mediathequewormhout.biblixnet.com/exporte_afi', - 'id_bib' => 5, - 'type' => 10], $this->createMockForService('BiblixNet')); + $this->prepareLibraryAndService($params, + Class_IntBib::COM_BIBLIXNET, + 'BiblixNet'); + + $this->bib_wormhout = Class_IntBib::find(5); } @@ -741,17 +769,18 @@ class CommSigbDynixTest extends CommSigbTestCase { { parent::setUp(); - $this->bib_pc94 = Class_IntBib::newInstanceWithId(5) - ->setCommParams(["url_serveur" => 'http://www.dynix.fr:8080/capcvm/', - 'client_id' => 'SymWS', - 'mails_bib' => 'ALFA:alfa@here.fr']) - ->setCommSigb(11); + $this->_url_server = 'http://www.dynix.fr:8080/capcvm/'; + + $params = ["url_serveur" => $this->_url_server, + 'client_id' => 'SymWS', + 'mails_bib' => 'ALFA:alfa@here.fr']; + - Class_WebService_SIGB_Dynix::setService([ "url_serveur" => 'http://www.dynix.fr:8080/capcvm/', - 'client_id' => 'SymWS', - 'mails_bib' => 'ALFA:alfa@here.fr', - 'id_bib' => 5, - 'type' => 11], $this->createMockForService('Dynix')); + $this->prepareLibraryAndService($params, + Class_IntBib::COM_DYNIX, + 'Dynix'); + + $this->bib_pc94 = Class_IntBib::find(5); $this->mock_service ->whenCalledAnswers('setClientId',[], $this->mock_service) @@ -834,19 +863,22 @@ class CommSigbWithNotAbonneTest extends ModelTestCase { /** @test */ public function reserveItemShouldReturnError() { $item = $this->fixture(Class_Exemplaire::class, ['id' => 12]); - $this->assertEquals(['erreur' => 'Communication SIGB indisponible'], + $this->assertEquals(['erreur' => 'Impossible de contacter le serveur de votre bibliothèque.'], $this->comm_sigb->reserveItem($item, 12, 0)); } /** @test */ public function getDispoExemplairesShouldReturnNonReservable() { - $this->assertFalse($this->comm_sigb->getDispoExemplaires([$this->fixture(Class_Exemplaire::class, - ['id' => 2, - 'id_origine' => 0, - 'code_barres' => 0, - 'id_int_bib' => 0]) - ])[0]->isReservable()); + $this->assertFalse($this + ->comm_sigb + ->getDispoExemplaires([$this->fixture(Class_Exemplaire::class, + ['id'=> 19, + 'id' => 2, + 'id_origine' => 0, + 'code_barres' => 0, + 'id_int_bib' => 0]) + ])[0]->isReservable()); } } @@ -909,21 +941,18 @@ class CommSigbFloraTest extends CommSigbTestCase { { parent::setUp(); - $this->bib_maze = $this - ->fixture(Class_IntBib::class, - ['id' => 5, - 'comm_params' => ["url_serveur" => 'http://flora.org', - 'login' => 'api', - 'password' => 'secret'], - 'comm_sigb' => Class_IntBib::COM_FLORA - ]); - - Class_WebService_SIGB_Flora::setService(["url_serveur" => 'http://flora.org', - 'login' => 'api', - 'password' => 'secret', - 'id_bib' => 5, - 'type' => 15], - $this->createMockForService('Flora')); + $this->_url_server = 'http://flora.org'; + + $params = ["url_serveur" => $this->_url_server, + 'login' => 'api', + 'password' => 'secret']; + + + $this->prepareLibraryAndService($params, + Class_IntBib::COM_FLORA, + 'Flora'); + + $this->bib_maze = Class_IntBib::find(5); } diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseBatchesPostProcessingTest.php b/tests/library/Class/Cosmogramme/Integration/PhaseBatchesPostProcessingTest.php index ba8502646cb6005cc25a9ef39878b71502b2094d..cb19f6a85247113be0a6cf9bfc2c1072ff6c8ef4 100644 --- a/tests/library/Class/Cosmogramme/Integration/PhaseBatchesPostProcessingTest.php +++ b/tests/library/Class/Cosmogramme/Integration/PhaseBatchesPostProcessingTest.php @@ -1,6 +1,10 @@ <?php /** +<<<<<<< HEAD * Copyright (c) 2012-2025, Agence Française Informatique (AFI). All rights reserved. +======= + * Copyright (c) 2012-2014, Agence Française Informatique (AFI). All rights reserved. +>>>>>>> ed977a38e4 (Fix error on Phase Batch Post Processing) * * BOKEH is free software; you can redistribute it and/or modify * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by @@ -20,9 +24,14 @@ */ -abstract class PhaseBatchesPostProcessingTestCase - extends Class_Cosmogramme_Integration_PhaseTestCase + + +abstract class PhaseBatchesPostProcessingTestCase extends Class_Cosmogramme_Integration_PhaseTestCase { + protected $_not_runnable; + protected Class_Batch_Abstract $_batch; + protected Class_Batch_Abstract $_not_runnable_batch; + protected Storm_Test_ObjectWrapper $_mock_http_client; public function setUp(): void { @@ -48,32 +57,29 @@ abstract class PhaseBatchesPostProcessingTestCase Class_Batch::setTimeSource(new TimeSourceForTest('2025-08-29')); // tuesday for pick_day $this->fixture(Class_Batch::class, - ['id' => 34, - 'pick_day' => '2', - 'processing_phase' => Class_Batch::AFTER_PROCESSING_RECORDS, - 'type' => 'TestingTest']); + ['id' => 34, + 'pick_day' => '2', + 'processing_phase' => Class_Batch::AFTER_PROCESSING_RECORDS, + 'type' => 'TestingTest']); - $batch = $this->_batchMock('Testing Batch Prepocessing'); + $this->_batch = $this->_batchMock('Testing Batch Prepocessing'); - $this->fixture(Class_Batch::class, - ['id' => 99, - 'pick_day' => '3', - 'type' => 'TestingNotRunnableTest']); + $this->_not_runnable = $this->fixture(Class_Batch::class, + ['id' => 99, + 'pick_day' => '3', + 'type' => 'TestingNotRunnableTest']); - $not_runnable_batch = $this->_batchMock('Testing Not Runnable Batch'); + $this->_not_runnable_batch = $this->_batchMock('Testing Not Runnable Batch'); $this ->onLoaderOfModel(Class_Batch::class) - ->whenCalled('getKnownType')->with('TestingTest')->answers($batch) - ->whenCalled('getKnownType')->with('TestingNotRunnableTest')->answers($not_runnable_batch); + ->whenCalled('getKnownType')->with('TestingTest')->answers($this->_batch) + ->whenCalled('getKnownType')->with('TestingNotRunnableTest')->answers($this->_not_runnable_batch); } - protected function _batchMock(string $label): Class_Batch_Abstract { - return new class($label) extends Class_Batch_Abstract { - protected string $_label; protected bool $_has_run = false; diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseItemFacetsTest.php b/tests/library/Class/Cosmogramme/Integration/PhaseItemFacetsTest.php index 8d3623f462fa45ced526056d21f06d1d5a2b4546..ab4dde401aae010aa7df6307448a3f58912a778a 100644 --- a/tests/library/Class/Cosmogramme/Integration/PhaseItemFacetsTest.php +++ b/tests/library/Class/Cosmogramme/Integration/PhaseItemFacetsTest.php @@ -225,7 +225,7 @@ class PhaseItemFacetsExecutePhaseTest extends PhaseItemFacetsTestCase { protected function _prepareFixtures() { $this->fixture(Class_Notice::class, - ['id' => 1]); + ['id' => 1]); $album = $this->fixture(Class_Album::class, ['id' => 2, @@ -245,3 +245,95 @@ class PhaseItemFacetsExecutePhaseTest extends PhaseItemFacetsTestCase { $this->assertEquals('TAssimil V0 HNRNR0001 Lfre Y1', Class_Notice::find(1)->getFacettes()); } } + + + + +/* @see https://forge.afi-sa.net/issues/208000 */ +class PhaseItemFacetsExemplaireWithAnnexeExecutePhaseTest extends PhaseItemFacetsTestCase { + + protected function _getPreviousPhase() { + Class_Cosmogramme_Integration_PhaseAbstract::shouldThrowError(true); + return (new Class_Cosmogramme_Integration_Phase(4)) + ->beCron(); + } + + + protected function _prepareFixtures() { + $notice = $this->fixture(Class_Notice::class, + ['id' => 1, + 'type_doc' => Class_TypeDoc::LIVRE, + 'titres' => 'La plus que vive', + 'authors' => 'Christian Bobin', + 'date_maj' => '2024-01-01 00:00:00', + 'exemplaires' => [$this->fixture(Class_Exemplaire::class, + ['id' => 123, + 'annexe' => 3, + 'code_barres' => '123', + 'type_doc' => Class_TypeDoc::LIVRE + ])] + ]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 3, + 'id_bib' => 2, + 'code' => '1', + 'id_origine' => '1', + 'libelle' => 'Mirepoix' + ]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 6, + 'id_bib' => 2, + 'code' => '3', + 'id_origine' => '3', + 'libelle' => 'Pau' + ]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 5, + 'id_bib' => 4, + 'code' => '1', + 'id_origine' => '1', + 'libelle' => 'Foix' + ]); + } + + + /** @test */ + public function facettesShouldContainsY3() { + $this->assertContains(' Y3 ', Class_Notice::find(1)->getFacettes()); + } +} + + + + +/* @see https://forge.afi-sa.net/issues/211651 */ +class PhaseItemFacetsExemplaireWithMultipleAnnexeExecutePhaseTest extends PhaseItemFacetsTestCase { + protected $_record; + + protected function _getPreviousPhase() { + Class_Cosmogramme_Integration_PhaseAbstract::shouldThrowError(true); + return (new Class_Cosmogramme_Integration_Phase(4)) + ->beCron(); + } + + + protected function _prepareFixtures() { + $this->_record = unserialize(file_get_contents( __DIR__ . '/bizarre_notice.txt')); + + $this + ->onLoaderOfModel('Class_Notice') + ->whenCalled('findAllAfter') + ->with(0, '0000-00-00 00:00:00') + ->answers([$this->_record]); + xdebug_break(); + } + + + /** @test */ + public function facettesShouldContainsAllDistinctItemFacets() { + $this->assertContains('B1 S17 E43 Y2 V1 B36 G214 S16 Y20 V36 HNRNR0001', $this->_record->getFacettes()); + } +} diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTest.php b/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTest.php index 901890936fc1bf5551e47e614ec260f330757c15..d288aa94bd4903976d5bcfbb97fbb3d0a5ed8a6b 100644 --- a/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTest.php +++ b/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTest.php @@ -846,3 +846,70 @@ class PhaseNoticeAuthorRenamedTest extends PhaseNoticeTestCase { $this->assertEquals('Oscar Wilde', Class_CodifAuteur::find(11)->getLibelle()); } } + + + + +/* hotline: https://forge.afi-sa.net/issues/208000 */ +class PhaseNoticeFacetteSiteTest + extends PhaseNoticeTestCase +{ + protected function _prepareFixtures() { + parent::_prepareFixtures(); + + + $this->fixture(Class_Bib::class, + ['id' => 1, + 'libelle' => 'BDA' + ]); + + Class_IntBib::find(2) + ->setSigb(Class_IntBib::SIGB_ORPHEE) + ->save(); + + $orphee = array_merge(Class_IntProfilDonnees::forOrphee()->getRawAttributes(), + [ 'accents' => Class_IntProfilDonnees::ENCODING_UTF8]); + $attributs = unserialize($orphee['attributs']); + $attributs[0][Class_IntProfilDonnees::FIELD_ITEM_ANNEXE] = 'h'; + $attributs[Class_IntProfilDonnees::FIELD_ITEM_ANNEXE] = 'h'; + $orphee['attributs'] = serialize($attributs); + Class_IntProfilDonnees::find(102) + ->updateAttributes($orphee) + ->save(); + + Class_Cosmogramme_Integration::deleteBy([]); + $value = $this->fixture(Class_Cosmogramme_Integration::class, + ['id' => 123, + 'bib' => Class_IntBib::find(2), + 'profil_donnees' => Class_IntProfilDonnees::find(102), + 'type_operation' => Class_Cosmogramme_Integration::TYPE_OPERATION_TOTAL, + 'traite' => 'non', + 'fichier' => 'cabret.txt', + 'pointeur_reprise' => 0]); + $value->assertSave(); + + Class_Cosmogramme_Integration_PhaseAbstract::shouldThrowError(true); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 3, + 'id_bib' => 2, + 'code' => '1', + 'id_origine' => '1', + 'libelle' => 'Mirepoix' + ]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 2, + 'id_bib' => 4, + 'code' => '1', + 'id_origine' => '1', + 'libelle' => 'Foix' + ]); + } + + + /** @test */ + public function annexeShouldContainsBe3() { + $this->assertEquals(3, Class_Exemplaire::find(1)->getAnnexe()); + } +} diff --git a/tests/library/Class/Cosmogramme/Integration/PhasePatronsTest.php b/tests/library/Class/Cosmogramme/Integration/PhasePatronsTest.php index 6357dbf41837a684ec9c5c1cc016d095df405f80..262461b1c19d37e985ba326b52292ebbf1fcfc96 100644 --- a/tests/library/Class/Cosmogramme/Integration/PhasePatronsTest.php +++ b/tests/library/Class/Cosmogramme/Integration/PhasePatronsTest.php @@ -51,6 +51,12 @@ abstract class PhasePatronsTestCase extends Class_Cosmogramme_Integration_PhaseT 'code' => 'SEYNOD', 'id_bib' => 2]); + $this->fixture(Class_CodifAnnexe::class, + ['id' => 36, + 'id_origine' => 'SEYNOD', + 'code' => 'SEYNOD', + 'id_bib' => 1]); + $this->fixture(Class_IntBib::class, ['id' => 1, 'sigb' => Class_IntBib::COM_NANOOK, @@ -280,9 +286,9 @@ class PhasePatronsFullImportTest extends PhasePatronsTestCase { /** @test */ - public function chiengPinkLibraryShouldBeSeynod() { + public function chiengPinkLibraryShouldBeAnnecy() { $chhieng = Class_Users::findFirstBy(['login' => 'A-000893']); - $this->assertEquals('Seynod', $chhieng->getBib()->getLibelle()); + $this->assertEquals('Annecy', $chhieng->getBib()->getLibelle()); } diff --git a/tests/library/Class/Cosmogramme/Integration/PhasePrepareIntegrationsTest.php b/tests/library/Class/Cosmogramme/Integration/PhasePrepareIntegrationsTest.php index eb9330eb4b94df52f6faab2c856c78412aeed956..81adf9ba5fb54e72d4ddab7aa465e3d9089bbcd0 100644 --- a/tests/library/Class/Cosmogramme/Integration/PhasePrepareIntegrationsTest.php +++ b/tests/library/Class/Cosmogramme/Integration/PhasePrepareIntegrationsTest.php @@ -408,6 +408,12 @@ abstract class PhasePrepareIntegrationsNanookStandardTestCase 'type_operation' => Class_Cosmogramme_Integration::TYPE_OPERATION_TOTAL, 'profil' => 102]); + Zend_Registry::set('sql', $this->mock() + ->whenCalled('query') + ->with('ALTER TABLE `notices` ADD FULLTEXT KEY IF NOT EXISTS `mots_notice` (`titres`, `auteurs`, `editeur`, `collection`, `matieres`, `dewey`, `other_terms`, `facets`)') + ->answers(true) + ->beStrict()); + $storm_file_system = (new Storm_FileSystem_Volatile) ->mkdir('ftp/my-library.net/integration') ->mkdir('ftp/my-library.net/transferts/foo'); @@ -512,7 +518,7 @@ abstract class PhasePrepareIntegrationsNanookStandardTestCase 'date_maj' => '2012-03-06 00:00:00']); $this->fixture(Class_CodifAnnexe::class, - ['id' => 8, + ['id' => 34, 'id_origine' => '34', 'libelle' => 'Library 1']); @@ -589,7 +595,8 @@ class PhasePrepareIntegrationsNanookWithRemovedLibraryTest $this->fixture(Class_IntMajAuto::class, ['id' => 1, - 'id_bib' => 3]); + 'id_bib' => 3, + 'nom_fichier' => '']); $this->fixture(Class_Cosmogramme_Integration::class, ['id' => 555, diff --git a/tests/library/Class/Cosmogramme/Integration/PhasePseudoRecordCmsTest.php b/tests/library/Class/Cosmogramme/Integration/PhasePseudoRecordCmsTest.php index 49ae146ca635dfa0e4a49defc68ed77af09008cb..6fd94afeab17fcfe14529a9378aa5d9cc4c2d8fa 100644 --- a/tests/library/Class/Cosmogramme/Integration/PhasePseudoRecordCmsTest.php +++ b/tests/library/Class/Cosmogramme/Integration/PhasePseudoRecordCmsTest.php @@ -33,6 +33,10 @@ class PhasePseudoRecordCmsUnindexTest extends Class_Cosmogramme_Integration_Phas Zend_Registry::set('sql', $this->mock() + ->whenCalled('query') + ->with('ALTER TABLE `notices` ADD FULLTEXT KEY IF NOT EXISTS `mots_notice` (`titres`, `auteurs`, `editeur`, `collection`, `matieres`, `dewey`, `other_terms`, `facets`)') + ->answers(true) + ->whenCalled('fetchAllByColumn')->answers([]) ->whenCalled('fetchAllByColumn') @@ -194,6 +198,10 @@ class PhasePseudoRecordCmsIndexWithTranslatedRecordTest ->with('select n.id_notice from notices as n inner join exemplaires as e on (n.id_notice=e.id_notice and n.type=1 and n.type_doc="8") inner join cms_article as a on a.id_article=e.id_origine or a.parent_id = e.id_origine where (a.debut is not null and date(a.debut) > date(now())) or (a.fin is not null and date(a.fin) < date(now()))') ->answers([]) + ->whenCalled('fetchAllByColumn') + ->with('select id_article from cms_article where id_article not in (select a.id_article from notices as n inner join exemplaires as e on (n.id_notice=e.id_notice and n.type=1 and n.type_doc="8") inner join cms_article as a on a.id_article=e.id_origine or a.parent_id = e.id_origine) and ((debut is null or date(debut) <= date(now())) and (fin is null or date(fin) >= date(now()))) and status=3 and indexation=1 order by id_article') + ->answers([]) + ->whenCalled('fetchAllByColumn') ->with('select id_article from cms_article where id_article not in (select a.id_article from notices as n inner join exemplaires as e on (n.id_notice=e.id_notice and n.type=1 and n.type_doc="8") inner join cms_article as a on a.id_article=e.id_origine) and ((debut is null or date(debut) <= date(now())) and (fin is null or date(fin) >= date(now()))) and status=3 and indexation=1') ->answers([22299]) @@ -202,6 +210,10 @@ class PhasePseudoRecordCmsIndexWithTranslatedRecordTest ->with('select id_article from cms_article where id_article not in (select a.id_article from notices as n inner join exemplaires as e on (n.id_notice=e.id_notice and n.type=1 and n.type_doc="8") inner join cms_article as a on a.id_article=e.id_origine or a.parent_id = e.id_origine) and ((debut is null or date(debut) <= date(now())) and (fin is null or date(fin) >= date(now()))) and status=3 and indexation=1') ->answers([]) + ->whenCalled('query') + ->with('ALTER TABLE `notices` ADD FULLTEXT KEY IF NOT EXISTS `mots_notice` (`titres`, `auteurs`, `editeur`, `collection`, `matieres`, `dewey`, `other_terms`, `facets`)') + ->answers(true) + ->beStrict()); $this->fixture(Class_Notice::class, diff --git a/tests/library/Class/Cosmogramme/Integration/bizarre_notice.txt b/tests/library/Class/Cosmogramme/Integration/bizarre_notice.txt new file mode 100644 index 0000000000000000000000000000000000000000..3c7cfb7df6f877f3c4d9606427cd2f6d22447c2d Binary files /dev/null and b/tests/library/Class/Cosmogramme/Integration/bizarre_notice.txt differ diff --git a/tests/library/Class/Cosmogramme/Integration/cabret.txt b/tests/library/Class/Cosmogramme/Integration/cabret.txt new file mode 100644 index 0000000000000000000000000000000000000000..3cd60378ce64100222c1c7d6ee2b64d51d917964 --- /dev/null +++ b/tests/library/Class/Cosmogramme/Integration/cabret.txt @@ -0,0 +1 @@ +01923cam 2200229 450 001001500000010004700015100004100062101001300103102000700116105001800123200013500141210005400276215005500330330038900385345001800774700003600792702004000828801003300868995026400901995026401165995026401429frOr0293414425 a978-2-7470-2423-5bRel. ss jaq.d17.90 EUR a20081121d2008 a |0fre|01 ||||ba0 afreceng aFR aaa 0||y|1 aL'invention de Hugo Cabreteroman en mots et en imagesfde Brian Selznickgtraduit de l'anglais par (Etats-Unis) Danielle Laruelle aMontrouge (Hauts-de-Seine)cBayard Jeunessed2008 a533 p.cillustrations en noir et blancd22 x 15 cm aLe père d'Hugo Cabret est mort dans l'incendie du musée où il travaillait en tant qu'horloger. Hugo a pour compagnon un automate et un oncle alcoolique qui l'héberge. Le jour où il disparaît, Hugo se cache et continue son travail de réglage d'horloges. Il répare l'automate de son père, persuadé qu'il va lui délivrer un important message. Prix Caldecott 2007 (Etats-Unis). b9782747024235 1aSelznickbBrianf1966-....4070 139836000133aLaruellebDanièle4730 aFRbElectrec20081121gAFNOR00a4419070054b293414425cLd905fJ SEL ig1h1i1j1301700011k100022l100056m03/06/2024n28/02/2027o04/11/2016p23/02/2024q04/04/2014r04/07/2014t1300200008w1x1022y2z2A1300100008B1790C17/02/2009D151G6H6NGOUP7R7S905T1U11V905W11Z2944190700a4419080054b293414425cLd905fJ SEL ig1h1i1j1301700011k100026l100025m14/11/2023n31/12/2026o01/12/2022p08/12/2022q22/09/2022r01/12/2022t1315500001w1x1026y2z2A1300100008B1790C17/02/2009D151G8H8NGOUP7R1S905T1U11V905W11Z2944190800a4419090054b293414425cLd905fJ SEL ig1h1i1j1301700011k1300200002l100030m30/06/2022n31/12/2025o04/12/2018p31/05/2022q03/11/2015r04/12/2018t100004w1x1131y2z2A1300100008B1790C17/02/2009D151G6H6NGOUP7R1S905T1U11V905W11Z29441909 \ No newline at end of file diff --git a/tests/library/Class/MoteurRecherche/MoteurRechercheFacettesTest.php b/tests/library/Class/MoteurRecherche/MoteurRechercheFacettesTest.php index 1b75ec477cfe14064c06fe9caa7a9a4a72ce8e8b..106cdc9d71bc936982c2b95f1f376bca0e11cc45 100644 --- a/tests/library/Class/MoteurRecherche/MoteurRechercheFacettesTest.php +++ b/tests/library/Class/MoteurRecherche/MoteurRechercheFacettesTest.php @@ -25,9 +25,9 @@ abstract class MoteurRechercheFacettesTestCase extends ModelTestCase { public $facettes; protected array $_facets = [ - 'M6567 HCCCC0001 B3 Lfre A4656 T4 Y2 V1 A37135', + 'M6567 HCCCC0001 B3 Lfre A4656 T4 Y20 V1 A37135', 'HTES10002 Lfre T1 Y7MA V1 A556 A5242', - 'HTES100010003 Lfre B3 T2 Y2 V1 A5242 A4656', + 'HTES100010003 Lfre B3 T2 Y20 V1 A5242 A4656', 'M6567 Lfre T4 Y7MA V1 A4656', 'M6567 Lfre T4 Y7MA V0 A4656 A1234', 'Lfre T2 Y7MA V1 A37135 A4656', @@ -124,13 +124,15 @@ abstract class MoteurRechercheFacettesTestCase extends ModelTestCase { 'libelle_facette' => null]); $this->fixture(Class_CodifAnnexe::class, - ['id' => '7MA', + ['id' => 7, 'id_origine' => '7MA', + 'code' => '7MA', 'libelle' => 'Maison environnement']); $this->fixture(Class_CodifAnnexe::class, ['id' => 20, 'id_origine' => '2', + 'code' => '2', 'libelle' => 'Seynod']); $this->fixture(Class_CodifAuteur::class, @@ -228,7 +230,7 @@ class MoteurRechercheFacettesSearchAlbumsPommesNewsTest extends MoteurRechercheF 'T' => ['T4' => 4, 'T1' => 1, 'T2' => 2], - 'Y' => ['Y2' => 2, + 'Y' => ['Y20' => 2, 'Y7MA' => 4], 'B' => ['B3' => 2, 'B2' => 1], @@ -441,9 +443,10 @@ class MoteurRechercheFacettesSearchEmptyWithSpecificSettingsToUserTest /** @test */ public function emptySearchWithDefaultBookmarkedLibShoulSucced() { + $f = Class_CodifAnnexe::find(20); $this->assertEquals([['id' => 'HCCCC0001', 'label' => 'Domaines : Games (1)'], - ['id' => 'Y2', + ['id' => 'Y20', 'label' => 'Site : Seynod (2)']], $this->facettes['bookmarks']); } diff --git a/tests/library/Class/MoteurRechercheTest.php b/tests/library/Class/MoteurRechercheTest.php index 514937445fa9aaea97fabfae75f10fde55141de0..23ccba53f9cef320545237988023b94fc53c720a 100644 --- a/tests/library/Class/MoteurRechercheTest.php +++ b/tests/library/Class/MoteurRechercheTest.php @@ -708,11 +708,11 @@ class MoteurRechercheCatalogueTest extends MoteurRechercheTestCase 'type_doc' => '1;4']); $this->fixture(Class_Catalogue::class, - ['id' => 89, - 'libelle' => 'Nouveautés Annecy, Seynod', - 'nouveaute' => 1, - 'annexe' => 'ANNECY;SEYNOD', - 'genre' => '26;25']); + ['id' => 89, + 'libelle' => 'Nouveautés Annecy, Seynod', + 'nouveaute' => 1, + 'annexe' => '2;7', + 'genre' => '26;25']); $this->fixture(Class_Catalogue::class, ['id' => 99, @@ -733,7 +733,7 @@ class MoteurRechercheCatalogueTest extends MoteurRechercheTestCase return [ [['id_catalogue' => 89], - 'sql' => "SELECT `notices`.`id_notice`, `notices`.`facettes` FROM `notices` WHERE ((`notices`.`date_creation` >= '2012-05-03' AND MATCH(`notices`.`titres`, `notices`.`auteurs`, `notices`.`editeur`, `notices`.`collection`, `notices`.`matieres`, `notices`.`dewey`, `notices`.`other_terms`, `notices`.`facets`) AGAINST('+(F_G25 F_G26) +(F_YANNECY F_YSEYNOD) +(F_HNANA0001 F_HNANA0002)' IN BOOLEAN MODE)) AND `notices`.`type` = 1) ORDER BY `notices`.`annee` DESC, `notices`.`alpha_titre` ASC"], + 'sql' => "SELECT `notices`.`id_notice`, `notices`.`facettes` FROM `notices` WHERE ((`notices`.`date_creation` >= '2012-05-03' AND MATCH(`notices`.`titres`, `notices`.`auteurs`, `notices`.`editeur`, `notices`.`collection`, `notices`.`matieres`, `notices`.`dewey`, `notices`.`other_terms`, `notices`.`facets`) AGAINST('+(F_G25 F_G26) +(F_Y2 F_Y7) +(F_HNANA0001 F_HNANA0002)' IN BOOLEAN MODE)) AND `notices`.`type` = 1) ORDER BY `notices`.`annee` DESC, `notices`.`alpha_titre` ASC"], [['id_catalogue' => 88], 'sql' => "SELECT `notices`.`id_notice`, `notices`.`facettes` FROM `notices` WHERE ((`notices`.`date_creation` >= '2012-05-03' AND MATCH(`notices`.`titres`, `notices`.`auteurs`, `notices`.`editeur`, `notices`.`collection`, `notices`.`matieres`, `notices`.`dewey`, `notices`.`other_terms`, `notices`.`facets`) AGAINST('+(F_T1 F_T4)' IN BOOLEAN MODE)) AND `notices`.`type` = 1) ORDER BY `notices`.`annee` DESC, `notices`.`alpha_titre` ASC"], @@ -769,8 +769,9 @@ class MoteurRechercheCatalogueTest extends MoteurRechercheTestCase (new Class_MoteurRecherche) ->lancerRecherche($criteres_recherche); - $this->assertSqlEquals(['SELECT `codif_thesaurus`.* FROM `codif_thesaurus` WHERE (`codif_thesaurus`.`code` = \'Nouveauté par annexe\' AND `codif_thesaurus`.`id_thesaurus` LIKE \'NANA%\') ORDER BY `codif_thesaurus`.`id_thesaurus` DESC LIMIT 1', - "SELECT `notices`.`id_notice`, `notices`.`facettes` FROM `notices` WHERE ((`notices`.`date_creation` >= '2012-05-03' AND MATCH(`notices`.`titres`, `notices`.`auteurs`, `notices`.`editeur`, `notices`.`collection`, `notices`.`matieres`, `notices`.`dewey`, `notices`.`other_terms`, `notices`.`facets`) AGAINST('+(F_HNANA0001 F_HNANA0002) +F_F565 +(F_G25 F_G26) +(F_YANNECY F_YSEYNOD)' IN BOOLEAN MODE)) AND `notices`.`type` = 1) ORDER BY `notices`.`annee` DESC, `notices`.`alpha_titre` ASC"]); + $this->assertSqlEquals(['SELECT `codif_annexe`.* FROM `codif_annexe` WHERE (`codif_annexe`.`id_annexe` IN (\'2\', \'7\'))', + 'SELECT `codif_thesaurus`.* FROM `codif_thesaurus` WHERE (`codif_thesaurus`.`code` = \'Nouveauté par annexe\' AND `codif_thesaurus`.`id_thesaurus` LIKE \'NANA%\') ORDER BY `codif_thesaurus`.`id_thesaurus` DESC LIMIT 1', + "SELECT `notices`.`id_notice`, `notices`.`facettes` FROM `notices` WHERE ((`notices`.`date_creation` >= '2012-05-03' AND MATCH(`notices`.`titres`, `notices`.`auteurs`, `notices`.`editeur`, `notices`.`collection`, `notices`.`matieres`, `notices`.`dewey`, `notices`.`other_terms`, `notices`.`facets`) AGAINST('+(F_HNANA0001 F_HNANA0002) +F_F565 +(F_G25 F_G26) +(F_Y2 F_Y7)' IN BOOLEAN MODE)) AND `notices`.`type` = 1) ORDER BY `notices`.`annee` DESC, `notices`.`alpha_titre` ASC"]); $this->assertEquals(['HNANA0001', 'HNANA0002', 'F565'], $criteres_recherche->getMultiFacets()); } diff --git a/tests/library/Class/NoticeTest.php b/tests/library/Class/NoticeTest.php index 6c3035314163ce6d683fb54c12e466a3be4d3e53..e3722d4652f1209824dbc23b70792625fd5aeb79 100644 --- a/tests/library/Class/NoticeTest.php +++ b/tests/library/Class/NoticeTest.php @@ -1055,6 +1055,7 @@ class NoticeUpdateFacetsFromItemsTest extends ModelTestCase { $this->fixture(Class_CodifAnnexe::class, ['id' => 43, + 'id_bib' => 10, 'libelle' => 'Roubaix', 'id_origine' => 'ROUB']); @@ -1067,7 +1068,7 @@ class NoticeUpdateFacetsFromItemsTest extends ModelTestCase { 'id_notice' => 5, 'id_bib' => 10, 'date_nouveaute' => '2016-05-11', - 'annexe' => 'ROUB']); + 'annexe' => 43]); $this->fixture(Class_Exemplaire::class, ['id' => 56, @@ -1081,9 +1082,9 @@ class NoticeUpdateFacetsFromItemsTest extends ModelTestCase { /** @test */ public function recordFacetsShouldContainsNoveltyForRoubaixAndNoveltyForLille() { - $this->assertEquals('A1 T0 B10 YROUB HNNNN0001 HNANA0001 B11 HNNNN0002 HNRNR0001', + $this->assertEquals('A1 T0 B10 Y43 HNNNN0001 HNANA0001 B11 HNNNN0002 HNRNR0001', Class_Notice::find(5)->getFacettes()); - $this->assertEquals('F_A1 F_T0 F_B10 F_YROUB F_HNNNN0001 F_HNANA0001 F_B11 F_HNNNN0002 F_HNRNR0001', + $this->assertEquals('F_A1 F_T0 F_B10 F_Y43 F_HNNNN0001 F_HNANA0001 F_B11 F_HNNNN0002 F_HNRNR0001', Class_Notice::find(5)->getFacets()); } } diff --git a/tests/library/Class/Testing/WebService/SIGB/Opsys/Service.php b/tests/library/Class/Testing/WebService/SIGB/Opsys/Service.php index e2340f9cf4bc2e792b840b5d334f3426e6aaedca..969657e5a93d06a8d49a454b20100d2c2649bc33 100644 --- a/tests/library/Class/Testing/WebService/SIGB/Opsys/Service.php +++ b/tests/library/Class/Testing/WebService/SIGB/Opsys/Service.php @@ -22,6 +22,8 @@ class Class_Testing_WebService_SIGB_Opsys_Service extends Class_WebService_SIGB_Opsys_Service{ use Trait_WebService; + protected $search_client; + public function connect() { return $this; } @@ -29,4 +31,11 @@ class Class_Testing_WebService_SIGB_Opsys_Service extends Class_WebService_SIGB_ public function disconnect() { return $this; } + + // Testing + public function setSearchClient( $mock_object): self + { + $this->search_client = $mock_object; + return $this; + } } diff --git a/tests/library/Class/WebService/SIGB/KohaLegacyTest.php b/tests/library/Class/WebService/SIGB/KohaLegacyTest.php index 4b5f0c240fb53bc5e4d309e9684e120de37febe0..5b9082d8d5beca25ca617346cfcfa9ba88400fe1 100644 --- a/tests/library/Class/WebService/SIGB/KohaLegacyTest.php +++ b/tests/library/Class/WebService/SIGB/KohaLegacyTest.php @@ -110,10 +110,9 @@ abstract class KohaLegacyTestCase extends ModelTestCase { Class_AdminVar::set('KOHA_MULTI_SITES', ''); - $this->service = Class_WebService_SIGB_KohaLegacy::getService(['url_serveur' => 'http://cat-aficg55.biblibre.com/cgi-bin/koha/ilsdi.pl']); + $this->service = Class_WebService_SIGB_KohaLegacy::getService(['url_serveur' => 'http://cat-aficg55.biblibre.com/cgi-bin/koha/ilsdi.pl', 'id_bib' => 1]); $this->mock_web_client = (new Class_Testing_WebService_SimpleWebClient); - $this->service->setWebClient($this->mock_web_client); } @@ -585,22 +584,24 @@ class KohaLegacyGetEmprunteurLaureAfondTest extends KohaLegacyTestCase { $this->fixture(Class_CodifAnnexe::class, ['id' => 33, + 'id_bib' => 1, 'libelle' => 'Biblio Meuse', 'id_origine' => 'BDM']); $this->fixture(Class_CodifAnnexe::class, ['id' => 34, + 'id_bib' => 1, 'libelle' => 'Montmedy', 'id_origine' => 'MON']); $this->fixture(Class_Bib::class, - ['id' => 88]); + ['id' => 1]); $this->fixture(Class_CodifAnnexe::class, ['id' => 35, 'libelle' => 'Médiathèque publique', 'id_origine' => 'MPU', - 'id_bib' => 88]); + 'id_bib' => 1]); $this->mock_web_client ->whenCalled('postData') @@ -679,9 +680,9 @@ class KohaLegacyGetEmprunteurLaureAfondTest extends KohaLegacyTestCase { /** @test */ - public function firstHoldWaitingToBePulledLocationIdShouldBe88() { + public function firstHoldWaitingToBePulledLocationIdShouldBe1() { $waiting_holds = $this->laurent->getHoldsWaitingToBePulled(); - $this->assertEquals(88, $waiting_holds[0]->getLocationId()); + $this->assertEquals(1, $waiting_holds[0]->getLocationId()); } @@ -1134,6 +1135,7 @@ class KohaLegacyGetEmprunteurJeanAndreWithIdSIGBTest extends KohaLegacyTestCase $this->fixture(Class_CodifAnnexe::class, ['id' => 33, + 'id_bib' => 1, 'libelle' => 'Testing branch', 'id_origine' => 'BIB']); @@ -1304,8 +1306,9 @@ class KohaLegacyGetRecordElementaireMonCherPolarTest extends KohaLegacyTestCase /** @test */ public function reserverExemplaireWithReserveAndExpirationDateShouldRequestHoldTitle() { - $this->fixture('Class_CodifAnnexe', + $this->fixture(Class_CodifAnnexe::class, ['id' => 8, + 'id_bib' => 1, 'code' => '007', 'id_origine' => '007']); @@ -1606,8 +1609,9 @@ public function tearDown(): void { /** @test */ function reserverExemplaireShouldSendPickupLocationIfGiven() { - $this->fixture('Class_CodifAnnexe', + $this->fixture(Class_CodifAnnexe::class, ['id' => 56, + 'id_bib' => 89863, 'id_origine' => 'BLV', 'libelle' => 'bib LV']); diff --git a/tests/library/Class/WebService/SIGB/NanookTest.php b/tests/library/Class/WebService/SIGB/NanookTest.php index 7036e8a26ab66e7348ed9849e5ece1308b2ee3be..9bb2959e7e04e463de6d8272d6c9e6814e6e0dfb 100644 --- a/tests/library/Class/WebService/SIGB/NanookTest.php +++ b/tests/library/Class/WebService/SIGB/NanookTest.php @@ -119,12 +119,13 @@ abstract class NanookTestCase extends ModelTestCase { $this->fixture(Class_CodifAnnexe::class, ['id' => 15, 'libelle' => 'MaBib', + 'code' => '11', 'id_origine' => '11']); $this->fixture(Class_Exemplaire::class, ['id' => '1234', 'id_origine' => '2', - 'annexe' => '11']); + 'annexe' => 15]); } @@ -1414,22 +1415,22 @@ class NanookOperationsTest extends NanookTestCase { /** @test */ public function reserverExemplaireOnExistingAnnexeOfLibraryWithTwoAnnexesShouldReturnSuccess() { - $this->fixture(Class_CodifAnnexe::class, + $this->fixture(Class_CodifAnnexe::class , ['id' => 5, 'libelle' => 'Archives', - 'id_bib' => 3, - 'id_origine' => 3]); + 'id_bib' => 182, + 'id_origine' => 182]); $this->_mock_web_client ->whenCalled('open_url') - ->with('http://localhost:8080/afi_Nanook/ilsdi/service/HoldTitle/bibId/196895/patronId/1/pickupLocation/3') + ->with('http://localhost:8080/afi_Nanook/ilsdi/service/HoldTitle/bibId/196895/patronId/1/pickupLocation/182') ->answers(NanookFixtures::xmlHoldTitleSuccess()); $this->assertEquals(['statut' => true, 'erreur' => ''], $this->_service->reserverExemplaire( - Class_Users::getLoader()->newInstance() ->setIdSigb('1'), + Class_Users::getLoader()->newInstance()->setIdSigb('1'), Class_Exemplaire::getLoader()->newInstance()->setIdOrigine('196895'), - 3 + 182 )); } diff --git a/tests/library/Class/WebService/SIGB/OpsysServiceTest.php b/tests/library/Class/WebService/SIGB/OpsysServiceTest.php index decb156c91100c36c23b04407fda3d160fd3640f..04cdbc8673c1bdffb31c1a68c0444dcf747117af 100644 --- a/tests/library/Class/WebService/SIGB/OpsysServiceTest.php +++ b/tests/library/Class/WebService/SIGB/OpsysServiceTest.php @@ -476,6 +476,7 @@ abstract class OpsysServiceWithSessionTestCase extends ModelTestCase { $donnes_infos->ValeursDonnees->string = ['Tin', 'Tin', '10/12/2012', '23 45 67 89', '1', '1', 'X00987', '10/12/1983']; $this->search_client + ->whenCalled('getWsdlUrl')->answers('true') ->whenCalled('OuvrirSession')->answers($this->ouvre_session_res) ->whenCalled('FermerSession')->answers(null) ->whenCalled('EmprAuthentifier')->answers($auth_response) diff --git a/tests/library/Class/WebService/SIGB/OrpheeFixtures.php b/tests/library/Class/WebService/SIGB/OrpheeFixtures.php index c662b23e9f23f9d32fcc5bd5f477f33b19d87be7..025ed68ee2bea851df104c97654af11d5dcf97ef 100644 --- a/tests/library/Class/WebService/SIGB/OrpheeFixtures.php +++ b/tests/library/Class/WebService/SIGB/OrpheeFixtures.php @@ -479,10 +479,11 @@ class OrpheeFixtures { } - public static function xmlGetLstPretHenryDupont() { - return '<datas> + public static function xmlGetLstPretHenryDupont(int $nb_prets = 2) { + return <<<XML_PRETS + <datas> <infos> - <nb_res> <![CDATA[2]]> </nb_res> <!-- Nombre de résultats --> + <nb_res> <![CDATA[$nb_prets]]> </nb_res> <!-- Nombre de résultats --> </infos> <documents> <document> @@ -513,7 +514,8 @@ class OrpheeFixtures { <tit></tit> <!-- Titre --> </document> </documents> -</datas> '; +</datas> +XML_PRETS; } public static function xmlGetLstPretHenryDupontVersion092015() { diff --git a/tests/library/Class/WebService/SIGB/OrpheeServiceTest.php b/tests/library/Class/WebService/SIGB/OrpheeServiceTest.php index 74aa9b04069a03c795d37409779af8402cd9f9c7..72b95ce67267862cc66a1f9d3335573bdd606788 100644 --- a/tests/library/Class/WebService/SIGB/OrpheeServiceTest.php +++ b/tests/library/Class/WebService/SIGB/OrpheeServiceTest.php @@ -168,6 +168,13 @@ abstract class OrpheeServiceTestCase extends ModelTestCase { } + public function tearDown() : void + { + Class_WebService_SIGB_Orphee::reset(); + parent::tearDown(); + } + + public function _beforeOrpheeServiceCreate(){ $this->_search_client ->whenCalled('hasFunction')->with('GetId')->answers(true) @@ -213,20 +220,7 @@ class OrpheeServiceBorrowerSoapActionDetectionTest extends OrpheeServiceTestCase /** @test */ - public function withGetAdhButNotLoginThroughSIGBOnlyProvidesChangePasswordShouldAnswerFalse() { - Class_AdminVar::set('LOGIN_THROUGH_SIGB_ONLY', 0); - $this->_search_client - ->whenCalled('hasFunction') - ->with('SetPwdAdh') - ->answers(true); - - $this->assertFalse($this->_orphee->providesChangePasswordService()); - } - - - /** @test */ - public function withGetAdhAndLoginThroughSIGBOnlyProvidesChangePasswordShouldAnswerTrue() { - Class_AdminVar::set('LOGIN_THROUGH_SIGB_ONLY', 1); + public function withSetPwdAdhProvidesChangePasswordShouldAnswerTrue() { $this->_search_client ->whenCalled('hasFunction') ->with('SetPwdAdh') @@ -1004,6 +998,7 @@ class OrpheeServiceGetInfoUserCarteHenryDupontTest extends OrpheeServiceTestCase $this->fixture(Class_CodifAnnexe::class, ['id' => 3, 'id_origine' => 'A3', + 'code' => 'A3', 'libelle' => 'Annecy Bonlieu', 'id_bib' => 3]); @@ -1013,6 +1008,22 @@ class OrpheeServiceGetInfoUserCarteHenryDupontTest extends OrpheeServiceTestCase 'libelle' => 'Romains']); + $this->fixture(Class_CodifAnnexe::class, + ['id' => 22, + 'code' => 17, + 'id_origine' => 17, + 'id_bib' => 42, + 'libelle' => 'Bib départementale ariège']); + + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 23, + 'code' => 17, + 'id_origine' => 17, + 'id_bib' => 6, + 'libelle' => 'Mediatheque Foix']); + + $this->fixture(Class_Bib::class, ['id' => 3, 'libelle' => 'Bonlieu']); @@ -1023,6 +1034,7 @@ class OrpheeServiceGetInfoUserCarteHenryDupontTest extends OrpheeServiceTestCase 'code_barres' => '123456', 'annexe' => 'A3', 'id_bib' => 3, + 'annexe' => 3, 'notice' => $this->fixture(Class_Notice::class, ['id' => 5, 'titre_principal' => 'Harry Potter', @@ -1033,6 +1045,7 @@ class OrpheeServiceGetInfoUserCarteHenryDupontTest extends OrpheeServiceTestCase ['id' => 32, 'code_barres' => '98374', 'id_bib' => 3, + 'annexe' => 3, 'notice' => $this->fixture(Class_Notice::class, ['id' => '974898302', 'titre_principal' => 'Le Chemin', @@ -1042,6 +1055,7 @@ class OrpheeServiceGetInfoUserCarteHenryDupontTest extends OrpheeServiceTestCase Class_Exemplaire::class, ['id' => 33, 'code_barres' => '678', + 'annexe' => 3, 'id_bib' => 3]); @@ -1057,20 +1071,30 @@ class OrpheeServiceGetInfoUserCarteHenryDupontTest extends OrpheeServiceTestCase ->whenCalled('GetLstRsv') ->with(GetLstRsv::withAdhAndCountPerPage('100753', -1)) ->answers(GetLstRsvResponse::withResult(OrpheeFixtures::xmlGetLstRsvHenryDupont())) - ->whenCalled('setTri') + ->whenCalled('SetTri') ->with(SetTri::withTypeTriAndOrdre(SetTri::SORT_ISSUE, SetTri::ORDER_DESC)) ->answers(true); $this->emprunteur = $this->_orphee->getEmprunteur($this->_henry_dupont); + $this->emprunteur->setIdIntBib(6); $this->_reservations = $this->emprunteur->getReservations(); } + public function tearDown() : void + { + $this->emprunteur = null; + $this->_reservations = null; + parent::tearDown(); + } + + /** @test */ public function emprunteurShouldNotBeEmpty() { $this->assertNotEmpty($this->emprunteur); } + /** @test */ public function emprunteurShouldNotBeBlocked() { $this->assertFalse($this->emprunteur->isBlocked()); @@ -1097,6 +1121,12 @@ class OrpheeServiceGetInfoUserCarteHenryDupontTest extends OrpheeServiceTestCase } + /** @test */ + public function emprunteurLibraryNameShouldBeMediathequeFoix() { + $this->assertEquals('Mediatheque Foix', $this->emprunteur->getLibraryLabel()); + } + + /** @test */ public function firstWaitingToBePulledHoldShouldHaveLocationId3ForBonlieu() { $this->assertEquals(3, $this->emprunteur->getHoldsWaitingToBePulled()[0]->getLocationId()); @@ -1544,6 +1574,7 @@ class OrpheeServiceGetInfoUserCarteHenryDupontVersion092015Test extends OrpheeSe $this->emprunteur = $this->_orphee->getEmprunteur($this->_henry_dupont); + $this->emprunteur->setIdIntBib(6); $this->_reservations = $this->emprunteur->getReservations(); } } diff --git a/tests/library/ZendAfi/View/Helper/Abonne/ResumeTest.php b/tests/library/ZendAfi/View/Helper/Abonne/ResumeTest.php index f7a191e9dc3a8276ee5778dd91adca948a92aec8..09e0598cb26bc189f9f7de02350e3f0c7c220675 100644 --- a/tests/library/ZendAfi/View/Helper/Abonne/ResumeTest.php +++ b/tests/library/ZendAfi/View/Helper/Abonne/ResumeTest.php @@ -40,7 +40,7 @@ class View_Helper_Abonne_ResumeAsAbonneSIGBTest extends ViewHelperTestCase // Salut moi de 2024, le 15 mars 2022 on faisait tomber les masques contre le COVID 19 et ce test plantait… Alors on rajoute 2 ans pour mieux nous retrouver. À suivre … $emprunteur ->empruntsAddAll([Class_WebService_SIGB_Emprunt::newInstanceWithEmptyExemplaire()->setDateRetour('13/03/2011'), - Class_WebService_SIGB_Emprunt::newInstanceWithEmptyExemplaire()->setDateRetour('13/03/2024')]); + Class_WebService_SIGB_Emprunt::newInstanceWithEmptyExemplaire()->setDateRetour('13/07/2024')]); $user = Class_Users::newInstanceWithId(3, ['fiche_sigb' => ['fiche' => $emprunteur], diff --git a/tests/library/ZendAfi/View/Helper/FacettesTest.php b/tests/library/ZendAfi/View/Helper/FacettesTest.php index 3fda5cf2101ce74e4017ae801baaed33c3f0dad6..f0a73cf73f0a6b2cf13bc3d3f4d65d4872d7afea 100644 --- a/tests/library/ZendAfi/View/Helper/FacettesTest.php +++ b/tests/library/ZendAfi/View/Helper/FacettesTest.php @@ -110,15 +110,18 @@ abstract class ZendAfi_View_Helper_FacettesTestCase extends ViewHelperTestCase { $this->_facettes = ['T' => ['T1' => 34], 'M' => ['M6567' => 22], 'HGENR' => ['HGENR0001' => 1], - 'Y' => ['YMDE' => 1, - 'YSEY' => 1, - 'YMEY' => 1], + + 'Y' => ['Y1' => 1, + 'Y2' => 1, + 'Y3' => 1 + ], 'S' => ['S1' => 1, 'S2' => 1, 'S3' => 1], 'G' => ['G4' => 1, 'G5' => 1, 'G6' => 1], + 'A' => ['A4656' => 58, 'A4657' => 40, 'A6752' => 21, @@ -174,7 +177,7 @@ class ZendAfi_View_Helper_FacettesRestrainedTest extends ZendAfi_View_Helper_Fac /** @test */ public function linkForFacetMaisonEnvironnementShouldBePresentAtSecondPosition() { $this->assertXPathContentContains($this->_html, - '//div[@class="facette"]//ul/li[2]//ul//a[@class="facette"][contains(@href, "/recherche/simple/facette/YMDE")]', + '//div[@class="facette"]//ul/li[2]//ul//a[@class="facette"][contains(@href, "/recherche/simple/facette/Y1")]', 'Maison environnement'); } @@ -318,6 +321,7 @@ class ZendAfi_View_Helper_DisabledMultiFacettesTest extends ZendAfi_View_Helper_ + class ZendAfi_View_Helper_FacettesFromAdvancedSearchTest extends ZendAfi_View_Helper_FacettesTestCase { @@ -345,23 +349,9 @@ class ZendAfi_View_Helper_FacettesFromAdvancedSearchTest /** @test */ - public function checkboxForFacetYMDEshouldNotBeChecked() { - $this->assertXPath($this->_html, - '//li[@class="facet_item facette"]//input[@name="multifacet_YMDE"][@value="0"]'); - } - - - /** @test */ - public function checkboxForFacetYSEYshouldBeChecked() { - $this->assertXPath($this->_html, - '//li[@class="facet_item facette"]//input[@name="multifacet_YSEY"][@value="1"]'); - } - - - /** @test */ - public function checkboxForFacetYMEYshouldBeChecked() { + public function checkboxForFacetYOneshouldNotBeChecked() { $this->assertXPath($this->_html, - '//li[@class="facet_item facette"]//input[@name="multifacet_YMEY"][@value="1"]'); + '//li[@class="facet_item facette"]//input[@name="multifacet_Y1"][@value="0"]'); } diff --git a/tests/scenarios/HandleBranchcode/HandleBranchcodeTest.php b/tests/scenarios/HandleBranchcode/HandleBranchcodeTest.php index 70dbcf1ac68cb283fb1e302628a64d55ca7f7a26..f6a012093cbe494a1aaf571415a3308fb57c8bd3 100644 --- a/tests/scenarios/HandleBranchcode/HandleBranchcodeTest.php +++ b/tests/scenarios/HandleBranchcode/HandleBranchcodeTest.php @@ -20,6 +20,7 @@ */ require_once 'tests/fixtures/ChamberyKohaFixtures.php'; +require_once 'tests/fixtures/KohaFixtures.php'; abstract class HandleBranchcodeTestCase extends AbstractControllerTestCase { @@ -127,8 +128,9 @@ class HandleBranchcodeHoldItemTest extends HandleBranchcodeTestCase { ->with($this->ilsdi . '?service=HoldItem&patron_id=18&bib_id=16&item_id=&pickup_location=CHY-GB') ->willDo(function(): void {$this->expected_call = true;}); - $this->fixture('Class_Exemplaire', + $this->fixture(Class_Exemplaire::class, ['id' => 16, + 'id_int_bib' => 3, 'id_origine' => 16]); } @@ -151,83 +153,173 @@ class HandleBranchcodeHoldItemTest extends HandleBranchcodeTestCase { -class HandleBranchcodeHoldItemAndHoldTitleTest extends HandleBranchcodeTestCase { +abstract class HandleBranchcodeHoldsWithItemTestCase extends AbstractControllerTestCase { + public function setUp() : void + { + parent::setUp(); + Class_AdminVar::set('KOHA_TRY_HOLD_ITEM', 1); - protected $expected_call = []; + $koha_profile = Class_IntProfilDonnees::forKoha(); + $koha_profile->save(); + Class_AdminVar::newInstanceWithId('KOHA_MULTI_SITES', ['valeur' => '' ]); + Class_CosmoVar::setValueOf('site_retrait_resa', 2); + $this->ilsdi = 'http://chamb.com/koha/ilsdi.pl'; - /** @test */ - public function wsKohaShouldBeCallTwiceWithUnavailabeStatus() { - Class_AdminVar::set('KOHA_TRY_HOLD_ITEM', 1); + $this->service = Class_WebService_SIGB_KohaLegacy::getService(['url_serveur' => $this->ilsdi, + 'id_bib' => 3, + 'type' => Class_IntBib::COM_KOHA_LEGACY]); - $this->mock_web_client - ->whenCalled('open_url') - ->with($this->ilsdi . '?service=HoldItem&patron_id=18&item_id=&pickup_location=CHY-GB') - ->willDo(function(): void {$this->expected_call [] = 1;}) + $this->fixture(Class_CodifAnnexe::class, + ['id' => 58, + 'code' => 'CHYGB', + 'libelle' => 'Bibliothèque Georges Brassens', + 'id_origine' => 'CHY-GB']); - ->whenCalled('open_url') - ->with($this->ilsdi . '?service=HoldTitle&patron_id=18&request_location=127.0.0.1&pickup_location=CHY-GB') - ->willDo(function(): void {$this->expected_call [] = 2;}) + $this->fixture(Class_CodifAnnexe::class, + ['id' => 15, + 'code' => 'VS', + 'libelle' => 'Valensole', + 'id_origine' => 'CHY-GB']); - ->beStrict(); + $sigb_gb = $this->fixture(Class_IntBib::class, + [ + 'id' => 3, + 'comm_params' => ['url_serveur' => $this->ilsdi], + 'comm_sigb' => Class_IntBib::COM_KOHA_LEGACY + ]); - $this->fixture('Class_Exemplaire', - ['id' => 16]); + $this->fixture(Class_Bib::class, + ['id' => 12, + 'libelle' => 'Bibliothèque Georges Brassens', + 'annexe' => 15, + 'int_bib' => $sigb_gb]); - $this->dispatch('/opac/recherche/reservation-pickup-ajax/id_notice/15/id_int_bib/1/id_bib/1/copy_id/16/code_annexe/CHYGB', true); + $this->user = $this->fixture(Class_Users::class, + ['id' => 78, + 'login' => 'Chambelle', + 'password' => 'upw', + 'idabon' => '93658', + 'id_site' => 12, + 'int_bib' => $sigb_gb, + 'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB]); + + + $this->fixture(Class_Exemplaire::class, + ['id' => 16, + 'id_origine' => 1342, + 'code_barres' => 45679, + 'id_data_profile' => $koha_profile->getId(), + 'zone_995' => serialize(['code' => '9', + 'valeur'=> '09876']), + 'id_int_bib' => 3]); - $this->assertEquals([1,2], $this->expected_call); + ZendAfi_Auth::getInstance()->logUser($this->user); } +} - /** @test */ - public function wsKohaShouldBeCallTwiceWithItemHoldNotAllowed() { - Class_AdminVar::set('KOHA_TRY_HOLD_ITEM', 1); - $this->mock_web_client - ->whenCalled('open_url') - ->with($this->ilsdi . '?service=HoldItem&patron_id=18&item_id=&pickup_location=CHY-GB') - ->willDo(function() {$this->expected_call [] = 1; - return '<HoldItem> - <code>OpacItemHoldNotAllowed</code> - </HoldItem>'; - }) - ->whenCalled('open_url') - ->with($this->ilsdi . '?service=HoldTitle&patron_id=18&request_location=127.0.0.1&pickup_location=CHY-GB') - ->willDo(function(): void {$this->expected_call [] = 2;}) +class HandleBranchcodeHoldItemAndHoldTitleTest extends HandleBranchcodeHoldsWithItemTestCase { - ->beStrict(); + protected $expected_call = []; + + + /** @test */ + public function wsKohaShouldBeCallTwiceWithUnavailabeStatus() { + + Class_HttpClientFactory::forTest() + ->addPostRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl', + ['service'=>'AuthenticatePatron', + 'username'=>'Chambelle', + 'password'=>'upw'], + KohaFixtures::xmlAuthenticatePatronOk()) + ->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl?service=GetPatronInfo&patron_id=96138&show_contact=1&show_loans=0&show_holds=1', + KohaFixtures::xmlGetPatronInfoJamesBond()) + ->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl?service=GetRecords&id=1342', + KohaFixtures::xmlGetRecordsWithTransfert()) + // ->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl?service=HoldItem&patron_id=96138&bib_id=&item_id=&pickup_location=CHY-GB', + // KohaFixtures::holdTitleResponseWithItemHoldsItypeOut()) + ->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl?service=HoldItem&patron_id=96138&bib_id=1342&item_id=', + KohaFixtures::holdTitleResponseWithItemHoldsItypeOut()) + ; - $this->fixture('Class_Exemplaire', - ['id' => 16]); $this->dispatch('/opac/recherche/reservation-pickup-ajax/id_notice/15/id_int_bib/1/id_bib/1/copy_id/16/code_annexe/CHYGB', true); - $this->assertEquals([1,2], $this->expected_call); + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->checkCalls( $this); + } + + + /** @test */ + public function wsKohaShouldBeCallTwiceWithItemHoldNotAllowed() { + + Class_HttpClientFactory::forTest() + ->addPostRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl', + ['service'=>'AuthenticatePatron', + 'username'=>'Chambelle', + 'password'=>'upw'], + KohaFixtures::xmlAuthenticatePatronOk()) + ->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl?service=GetPatronInfo&patron_id=96138&show_contact=1&show_loans=0&show_holds=1', + KohaFixtures::xmlGetPatronInfoJamesBond()) + ->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl?service=GetRecords&id=1342', + KohaFixtures::xmlGetRecordsWithTransfert()) + // ->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl?service=HoldItem&patron_id=96138&bib_id=&item_id=&pickup_location=CHY-GB', + // '<HoldItem> + // <code>OpacItemHoldNotAllowed</code> + // </HoldItem>') + ->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl?service=HoldItem&patron_id=96138&bib_id=1342&item_id=', + '<HoldItem> + <code>OpacItemHoldNotAllowed</code> + </HoldItem>') + ->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl?service=HoldTitle&patron_id=96138&bib_id=1342&request_location=127.0.0.1', + KohaFixtures::holdTitleResponseWithItemHoldsItypeOut()) + //->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl??service=HoldTitle&patron_id=96138&bib_id=&request_location=127.0.0.1', + // KohaFixtures::holdTitleResponseWithItemHoldsItypeOut()) + ; + + $this->dispatch('/opac/recherche/reservation-pickup-ajax/id_notice/15/id_int_bib/1/id_bib/1/copy_id/16/code_annexe/CHYGB'); + + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->checkCalls( $this); } /** @test */ public function wsKohaShouldBeCallOnceWithItemHold() { - Class_AdminVar::set('KOHA_TRY_HOLD_ITEM', 1); - $this->mock_web_client - ->whenCalled('open_url') - ->with($this->ilsdi . '?service=HoldItem&patron_id=18&item_id=&pickup_location=CHY-GB') - ->willDo(function() {$this->expected_call [] = 1; - return '<HoldTitle> + Class_HttpClientFactory::forTest() + ->addPostRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl', + ['service'=>'AuthenticatePatron', + 'username'=>'Chambelle', + 'password'=>'upw'], + KohaFixtures::xmlAuthenticatePatronOk()) + ->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl?service=GetPatronInfo&patron_id=96138&show_contact=1&show_loans=0&show_holds=1', + KohaFixtures::xmlGetPatronInfoJamesBond()) + ->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl?service=GetRecords&id=1342', + KohaFixtures::xmlGetRecordsWithTransfert()) + ->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl?service=HoldItem&patron_id=96138&bib_id=1342&item_id=', + '<HoldTitle> <title>Mireille l\'abeille</title> <pickup_location>Bibliothèque Départementale de la Meuse</pickup_location> - </HoldTitle>'; - }) - ->beStrict(); - - $this->fixture('Class_Exemplaire', - ['id' => 16]); + </HoldTitle>' + ) + // ->addRequestWithResponse('http://chamb.com:80/koha/ilsdi.pl?service=HoldItem&patron_id=18&item_id=&pickup_location=CHY-GB', + // '<HoldTitle> + // <title>Mireille l\'abeille</title> + // <pickup_location>Bibliothèque Départementale de la Meuse</pickup_location> + // </HoldTitle>' + // ) + ; $this->dispatch('/opac/recherche/reservation-pickup-ajax/id_notice/15/id_int_bib/1/id_bib/1/copy_id/16/code_annexe/CHYGB', true); - $this->assertEquals([1], $this->expected_call); + Class_HttpClientFactory::getInstance() + ->getLastHttpClient() + ->checkCalls( $this); } } diff --git a/tests/scenarios/SearchResult/SearchResultTest.php b/tests/scenarios/SearchResult/SearchResultTest.php index 22a7f67b36eacb7951ac9004120c10652141e3ba..dc4ea884dc2ab57bc44d8edc2d3cf2ed1acb43b3 100644 --- a/tests/scenarios/SearchResult/SearchResultTest.php +++ b/tests/scenarios/SearchResult/SearchResultTest.php @@ -118,14 +118,14 @@ class SearhResultFilterDomainsFromProfilTest extends AbstractControllerTestCase $this->fixture(Class_CodifThesaurus::class, ['id' => 4, - 'id_thesaurus' => 'CCCC0001', + 'id_thesaurus' => 'CCCC1', 'id_origine' => 4, 'code' => 'Catalogue', 'libelle' => 'Youths']); $this->fixture(Class_CodifThesaurus::class, ['id' => 5, - 'id_thesaurus' => 'CCCC0002', + 'id_thesaurus' => 'CCCC2', 'id_origine' => 5, 'code' => 'Catalogue', 'libelle' => 'Adults']); diff --git a/tests/scenarios/Templates/TemplatesAbonneCentralizedHoldsTest.php b/tests/scenarios/Templates/TemplatesAbonneCentralizedHoldsTest.php index 3aa7b6188c1851a5621366f3e7676613009088be..89def629e5324e7247443c4d8087f0b4ff9b3adc 100644 --- a/tests/scenarios/Templates/TemplatesAbonneCentralizedHoldsTest.php +++ b/tests/scenarios/Templates/TemplatesAbonneCentralizedHoldsTest.php @@ -29,11 +29,13 @@ abstract class TemplatesAbonneCentralizedHoldsTestCase protected $_search_client, $_orphee, + $_orphee2, $_henry_dupont, $_john_lemon, $_foix; - public function setUp(): void { + public function setUp(): void + { parent::setUp(); Class_CosmoVar::setValueOf('centralized_hold_mode', 34); @@ -42,6 +44,38 @@ abstract class TemplatesAbonneCentralizedHoldsTestCase $comm_params = ['url_serveur' => 'tests/fixtures/orphee.wsdl', 'allow_hold_available_items' => true]; + $this->fixture(Class_CodifAnnexe::class, + ['id' => 82, + 'id_bib' => 34, + 'code' => 34, + 'id_origine' => 34, + 'libelle' => 'JolieVille' + ]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 83, + 'id_bib' => 37, + 'code' => 37, + 'id_origine' => 37, + 'libelle' => 'WonderTown' + ]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 84, + 'id_bib' => 36, + 'code' => 'Fx', + 'id_origine' => 'Fx', + 'libelle' => 'Foix' + ]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 85, + 'id_bib' => 36, + 'code' => 'MTG', + 'id_origine' => 'MTG', + 'libelle' => 'Montgaillard' + ]); + $this->fixture(Class_Bib::class, ['id' => 34, 'mail' => 'test@jolieville.net', @@ -53,6 +87,7 @@ abstract class TemplatesAbonneCentralizedHoldsTestCase 'id_bib' => 34, 'nom' => 'JolieVille', 'nom_court' => 'JV', + 'sigb' => Class_IntBib::SIGB_ORPHEE, 'comm_sigb' => Class_IntBib::COM_ORPHEE, 'comm_params' => $comm_params ]); @@ -69,9 +104,55 @@ abstract class TemplatesAbonneCentralizedHoldsTestCase 'nom' => 'WonderTown', 'nom_court' => 'WT', 'mail' => 'intbib@WonderTown.net', + 'sigb' => Class_IntBib::SIGB_ORPHEE, 'comm_sigb' => Class_IntBib::COM_ORPHEE, - 'comm_params' => array_merge($comm_params, - ['use_card_number' => '1301500012'])]); + 'comm_params' => ['url_serveur' => 'tests/fixtures/orphee2.wsdl', + 'allow_hold_available_items' => true, + 'use_card_number' => '1301500012']]); + + $this->fixture(Class_IntBib::class, + ['id' => 37, + 'id_bib' => 37, + 'nom' => 'Eightth Wonder', + 'nom_court' => '8THW', + 'mail' => 'intbibqsdf@WonderTown.net', + 'sigb' => Class_IntBib::SIGB_NANOOK, + 'comm_sigb' => Class_IntBib::COM_NANOOK, + 'comm_params' => ['url_serveur' => 'http://bib.valensol.net', + 'provide_pickup_locations' => true, + 'use_card_number' => '1301500012']]); + + $this->fixture(Class_IntBib::class, + ['id' => 38, + 'id_bib' => 38, + 'nom' => 'Bibliothèque Sans réservations centralisées', + 'nom_court' => 'BSRC', + 'mail' => 'bsrc@WonderTown.net', + 'sigb' => Class_IntBib::SIGB_NANOOK, + 'comm_sigb' => Class_IntBib::COM_NANOOK, + 'comm_params' => ['url_serveur' => 'http://bib.valenciel.net']]); + + $this->fixture(Class_IntBib::class, + ['id' => 40, + 'id_bib' => 40, + 'nom' => 'Bibliothèque Sans réservations centralisées', + 'nom_court' => 'BSRC', + 'mail' => 'bsrc@WonderTown.net', + 'sigb' => Class_IntBib::SIGB_NANOOK, + 'comm_sigb' => Class_IntBib::COM_NANOOK, + 'comm_params' => ['url_serveur' => 'http://bib.valenciel.net']]); + + $this->fixture(Class_IntBib::class, + ['id' => 39, + 'id_bib' => 39, + 'nom' => 'Médiathèque Dun', + 'nom_court' => 'Dun', + 'mail' => 'intbibqsdf@dunedain.net', + 'sigb' => Class_IntBib::SIGB_NANOOK, + 'comm_sigb' => Class_IntBib::COM_NANOOK, + 'comm_params' => ['url_serveur' => 'http://bib.valensol.net', + 'provide_pickup_locations' => true, + 'use_card_number' => '1301500014']]); $this->_john_lemon = $this->fixture(Class_Users::class, @@ -83,10 +164,9 @@ abstract class TemplatesAbonneCentralizedHoldsTestCase 'idabon' => '130425', 'password' => 'secret', 'mail' => 'johnlemon@abbeyroad.net', - 'id_int_bib' => 36, 'int_bib' => $intbib_wondertown, 'bib' => $bib_wondertown, - 'id_bib' => 36 + 'id_sigb' => '789789789' ]); $this->_foix = @@ -118,11 +198,18 @@ abstract class TemplatesAbonneCentralizedHoldsTestCase ['id' => 2345, 'id_notice' => 3, 'id_bib' => 34, + 'annexe' => 34, 'id_int_bib' => 34, 'type_doc' => Class_TypeDoc::LIVRE, 'id_origine' => 312412, 'code_barres' => '012345']); + $this->fixture(Class_CodifAnnexe::class, + ['id' => 37, + 'libelle' => 'Paris', + 'id_bib' => 37, + 'id_origine' => 10]); + $this->fixture(Class_Exemplaire::class, ['id' => 2346, 'id_notice' => 3, @@ -130,8 +217,19 @@ abstract class TemplatesAbonneCentralizedHoldsTestCase 'id_int_bib' => 37, 'type_doc' => Class_TypeDoc::LIVRE, 'id_origine' => 312413, + 'annexe' =>37, 'code_barres' => '012346']); + $this->fixture(Class_Exemplaire::class, + ['id' => 2348, + 'id_notice' => 3, + 'id_bib' => 38, + 'id_int_bib' => 38, + 'type_doc' => Class_TypeDoc::LIVRE, + 'id_origine' => 312415, + 'annexe' => 38, + 'code_barres' => '012348']); + $this->fixture(Class_Exemplaire::class, ['id' => 2347, 'id_notice' => 3, @@ -141,16 +239,62 @@ abstract class TemplatesAbonneCentralizedHoldsTestCase 'id_origine' => 312414, 'code_barres' => '012347']); - $this->_search_client = $this->mock(); - $this->_search_client + $this->_search_client = $this->_setupSearchClient(); + + $allow_hold_available_items=true; + $this->_orphee = Class_WebService_SIGB_Orphee_Service::getService('tests/fixtures/orphee.wsdl', null, $allow_hold_available_items); + $this->_orphee->setSearchClient($this->_search_client); + $this->_orphee->isConnected(); + + $this->_henry_dupont = + $this->fixture(Class_Users::class, + ['id' => 2, + 'login' => '10900000753', + 'idabon' => '100753', + 'password' => 'secret', + 'id_int_bib' => 34, + 'id_site' => 34]); + + $this->_henry_dupont->beAbonneSIGB()->assertSave(); + + Class_WebService_SIGB_Orphee::setService(array_merge($comm_params, + ['id_bib' => 34, + 'type' => Class_IntBib::COM_ORPHEE]), + $this->_orphee); + + $this->_orphee2 = Class_WebService_SIGB_Orphee_Service::getService('tests/fixtures/orphee2.wsdl', + null, + $allow_hold_available_items); + $this->_orphee2->setSearchClient($this->_search_client); + $this->_orphee2->beHoldModeItem(); + $this->_orphee2->isConnected(); + + Class_WebService_SIGB_Orphee::setService(array_merge($comm_params, + ['id_bib' => 36, + 'url_serveur' => 'tests/fixtures/orphee2.wsdl', + 'type' => Class_IntBib::COM_ORPHEE, + 'use_card_number' => '1301500012']), + $this->_orphee2); + } + + + protected function _setupSearchClient() + { + return $this + ->mock() + ->whenCalled('__getLastRequest') ->answers('last request') + ->whenCalled('__getLastResponse') ->answers('last response') + ->whenCalled('__getLastResponseHeaders') ->answers('last response headers') + ->whenCalled('__getLastRequestHeaders') ->answers('last response') + ->whenCalled('hasFunction') ->answers(false) @@ -164,6 +308,7 @@ abstract class TemplatesAbonneCentralizedHoldsTestCase ->whenCalled('GetId') ->with(new GetId()) + ->answers(GetIdResponse::withIdResult('1234')) ->whenCalled('hasFunction')->with('GetAdh')->answers(true) @@ -174,6 +319,12 @@ abstract class TemplatesAbonneCentralizedHoldsTestCase ->whenCalled('getXml') ->answers(OrpheeFixtures::xmlGetInfoUserCarteHenryDupont())) + ->whenCalled('GetAdh') + ->with(GetAdh::withNo('uselogon')) + ->answers(Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetInfoUserCarteHenryDupont())) + ->whenCalled('GetAdh') ->with(GetAdh::withNo('1301500012')) ->answers(Storm_Test_ObjectWrapper::mock() @@ -185,40 +336,38 @@ abstract class TemplatesAbonneCentralizedHoldsTestCase ->answers(Storm_Test_ObjectWrapper::mock() ->whenCalled('getXml') ->answers(OrpheeFixtures::xmlGetAdhFoix())) + ->whenCalled('GetLstDmt') ->with(GetLstDmt::withNtcAndFas('312412', 0)) ->answers(GetLstDmtResponse::withResult(OrpheeFixtures::xmlGetLstDmtMillenium())) - ->whenCalled('RsvNtcAdh') - ->with(RsvNtcAdh::withNoticeUserNo('312412', '1301500012', 0)) - ->answers(RsvNtcAdhResponse::withResult('<datas><msg><code><![CDATA[1]]></code><libelle><![CDATA[Réservation mise en attente]]></libelle></msg></datas>')); + ->whenCalled('GetLstDmt') + ->with(GetLstDmt::withNtcAndFas('312414', 0)) + ->answers(GetLstDmtResponse::withResult(OrpheeFixtures::xmlGetLstDmtMillenium())) - $allow_hold_available_items=true; - $this->_orphee = Class_WebService_SIGB_Orphee_Service::getService('tests/fixtures/orphee.wsdl', null, $allow_hold_available_items); - $this->_orphee->setSearchClient($this->_search_client); - $this->_orphee->isConnected(); + ->whenCalled('GetLstRsv') + ->with(GetLstRsv::withAdhAndCountPerPage(1301500012, 200)) + ->answers(GetLstRsvResponse::withResult(OrpheeFixtures::xmlGetLstRsvHenryDupont())) - $this->_henry_dupont = - $this->fixture(Class_Users::class, - ['id' => 2, - 'login' => '10900000753', - 'idabon' => '100753', - 'password' => 'secret', - 'id_int_bib' => 34, - 'id_site' => 34]); + ->whenCalled('RsvNtcAdh') + ->with(RsvNtcAdh::withNoticeUserNo('312414', '1301500012', 0)) + ->answers(RsvNtcAdhResponse::withResult('<datas><msg><code><![CDATA[1]]></code><libelle><![CDATA[Réservation mise en attente]]></libelle></msg></datas>')) - $this->_henry_dupont->beAbonneSIGB()->assertSave(); + ->whenCalled('RsvNtcAdh') + ->with(RsvNtcAdh::withNoticeUserNo('312412', '1301500012', 0)) + ->answers(RsvNtcAdhResponse::withResult('<datas><msg><code><![CDATA[1]]></code><libelle><![CDATA[Réservation mise en attente]]></libelle></msg></datas>')) - Class_WebService_SIGB_Orphee::setService(array_merge($comm_params, - ['id_bib' => 34, - 'type' => Class_IntBib::COM_ORPHEE]), - $this->_orphee); + ->whenCalled('RsvDmtAdh') + ->with(RsvDmtAdh::withNoticeItemUser('312414', '', '100753')) + ->answers(RsvDmtAdhResponse::withResult('<datas><msg><code><![CDATA[1]]></code><libelle><![CDATA[Réservation mise en attente]]></libelle></msg></datas>')) - Class_WebService_SIGB_Orphee::setService(array_merge($comm_params, - ['id_bib' => 36, - 'type' => Class_IntBib::COM_ORPHEE, - 'use_card_number' => '1301500012']), - $this->_orphee); + ->whenCalled('RsvDmtAdh') + ->with(RsvDmtAdh::withNoticeItemUser('312414', '', '1301500012')) + ->answers(RsvDmtAdhResponse::withResult('<datas><msg><code><![CDATA[1]]></code><libelle><![CDATA[Réservation mise en attente]]></libelle></msg></datas>')) + + ->whenCalled('GetLstRsv') + ->with(GetLstRsv::withAdhAndCountPerPage('100753', 200)) + ->answers(GetLstRsvResponse::withResult(OrpheeFixtures::xmlGetLstRsvHenryDupont())); } @@ -229,24 +378,67 @@ abstract class TemplatesAbonneCentralizedHoldsTestCase } + + +class TemplatesAbonneCentralizedHoldsWithHoldModeFailuresTest extends TemplatesAbonneCentralizedHoldsTestCase { + + public function _setHoldMode() { + $this->_orphee->beHoldModeItem(); + return $this; + } + + + /** @test */ + public function johnLemonReserveItem2345ShouldReturnDocumentUnavailable() { + Class_CosmoVar::setValueOf('centralized_hold_mode', 34); + ZendAfi_Auth::getInstance()->logUser($this->_john_lemon); + $this->dispatch('/recherche/reservationajax/id_bib/36/copy_id/2345/id_origine/312412/id/123'); + $this->assertContains('Votre réservation est enregistrée.<br>Nous vous informerons quand le document \'La disparition / PEREC, Georges\' sera disponible', + json_decode($this->_response->getBody())->content); + } + + + /** @test */ + public function noParameterForCentralizedLibraryShouldReturnError() { + Class_CosmoVar::setValueOf('centralized_hold_mode',39); + ZendAfi_Auth::getInstance()->logUser($this->_john_lemon); + $this->dispatch('/recherche/reservationajax/id_bib/36/copy_id/2346/id_origine/312412/id/123'); + $this->assertContains('Vous ne pouvez pas réserver cet exemplaire !', + json_decode($this->_response->getBody())->content); + } + + + /** @test */ + public function foixUserReservationPickupAjaxShouldReturnReservationEnregistree() { + Class_CosmoVar::setValueOf('centralized_hold_mode',34); + ZendAfi_Auth::getInstance()->logUser($this->_foix); + $this->dispatch('/recherche/reservation-pickup-ajax/id_bib/34/copy_id/2345/id_origine/312412/id/123'); + $this->assertContains('Votre réservation est enregistrée.<br>Nous vous informerons', + json_decode($this->_response->getBody())->content); + } +} + + + + class TemplatesAbonneCentralizedHoldsFailuresTest extends TemplatesAbonneCentralizedHoldsTestCase { protected $_response; /** @test */ public function HenryDupontShouldUseUniquePatronShouldBeFalse() { - $this->assertFalse($this->_henry_dupont->shouldUseUniquePatron()); + $this->assertFalse($this->_henry_dupont->shouldUseUniquePatron(Class_Exemplaire::find(2346))); } /** @test */ public function JohnLemonShouldUseUniquePatronShouldBeTrue() { - $this->assertTrue($this->_john_lemon->shouldUseUniquePatron()); + $this->assertTrue($this->_john_lemon->shouldUseUniquePatron(Class_Exemplaire::find(2345))); } /** @test */ public function FoixShouldUseUniquePatronShouldBeFalse() { - $this->assertFalse($this->_foix->shouldUseUniquePatron()); + $this->assertFalse($this->_foix->shouldUseUniquePatron(Class_Exemplaire::find(2345))); } @@ -260,7 +452,16 @@ class TemplatesAbonneCentralizedHoldsFailuresTest extends TemplatesAbonneCentral public function johnLemonReserveItem2346ShouldReturnReservationImpossibleNonReservable() { ZendAfi_Auth::getInstance()->logUser($this->_john_lemon); $this->dispatch('/recherche/reservationajax/id_bib/36/copy_id/2346/id_origine/312412/id/123'); - $this->assertContains('Réservation impossible : l\'exemplaire n\'est pas réservable', + $this->assertContains('Vous ne pouvez pas réserver cet exemplaire !', + json_decode($this->_response->getBody())->content); + } + + + /** @test */ + public function johnLemonReserveItem23247ShouldReturnReservationEnregistree() { + ZendAfi_Auth::getInstance()->logUser($this->_john_lemon); + $this->dispatch('/recherche/reservationajax/id_bib/36/copy_id/2347/id_origine/312414/id/123'); + $this->assertContains('Votre réservation est enregistrée.', json_decode($this->_response->getBody())->content); } @@ -268,9 +469,10 @@ class TemplatesAbonneCentralizedHoldsFailuresTest extends TemplatesAbonneCentral /** @test */ public function henryDupontReservItem2345ShouldReturnReservationImpossibleDocumentBibliothequeCentrale() { Class_CosmoVar::setValueOf('centralized_hold_mode',36); + $this->_henry_dupont->setIntBib(Class_IntBib::find(38)); ZendAfi_Auth::getInstance()->logUser($this->_henry_dupont); $this->dispatch('/recherche/reservationajax/id_bib/36/copy_id/2347/id_origine/312412/id/123'); - $this->assertContains('votre bibliothèque n\'autorise pas la réservation des documents de la bibliotheque centrale', + $this->assertContains('Vous ne pouvez pas réserver cet exemplaire !', json_decode($this->_response->getBody())->content); } @@ -287,6 +489,9 @@ class TemplatesAbonneCentralizedHoldsReservationSuccessTest $this->_mock_transport = new MockMailTransport(); Zend_Mail::setDefaultTransport($this->_mock_transport); Class_Profil::getCurrentProfil()->setMailSite('laurent@afi-sa.fr'); + $this->_john_lemon + ->setIdIntBib(37) + ->setIntBib(Class_IntBib::find(37)); ZendAfi_Auth::getInstance()->logUser($this->_john_lemon); $this->dispatch('/recherche/reservationajax/id_bib/36/copy_id/2345/id_origine/312412/id/123'); } @@ -319,7 +524,7 @@ class TemplatesAbonneCentralizedHoldsReservationSuccessTest public function getRecipients(){ return [[0, 'test@jolieville.net'], - [1, 'intbib@WonderTown.net'], + [1, 'intbibqsdf@WonderTown.net'], [2,'johnlemon@abbeyroad.net']]; } @@ -370,12 +575,10 @@ HTML_LIBRARY; $mail_to_user= <<<HTML_USER <p>Bonjour,</p> -<p>Une réservation a été effectuée par un utilisateur de votre bibliothèque sur le portail BDP.</p> -<p>Il s'agit du document : La disparition de Code Barre : 012345</p> -<p>Pour l'utilisateur : John Lemon</p> -<p>Pour la bibliothèque : WonderTown. -La réservation a été reportée dans le Orphée BDP au nom de votre bibliothèque avec le code adhérent 1301500012. -Le document doit vous être envoyé par la BDP. +<p>Vous avez demandé à faire venir le document La disparition de la Bibliothèque Départemantale de Prêt à la bibliothèque WonderTown.</p> +<p>Votre bibliothèque vous informera lorsque ce document sera disponible.</p> +<p>Cordialement,</p> +<p>La Bibliothèque Départementale de l'Ariège.</p> HTML_USER; return [[0, $mail_to_central_library], @@ -390,3 +593,866 @@ HTML_USER; $this->assertEquals(quoted_printable_decode($this->_mock_transport->getSentMails()[$email_count]->getBodyHtml()->getContent()), $mail_content); } } + + + + +include_once 'tests/fixtures/NanookFixtures.php'; + +class TemplatesAbonneCentralizedHoldsReservationPickupAjaxNetworkTest + extends TemplatesAbonneCentralizedHoldsTestCase{ + protected + $_mock_web_client, + $_service; + + public function setUp() : void + { + parent::setUp(); + $this + ->_john_lemon + ->setIntBib(Class_IntBib::find(37)); + + $this->_mock_web_client = $this->mock() + ->whenCalled('open_url') + ->with('http://bib.valensol.net/service/GetPickupLocation/bibId/0/patronId/0/siteId/0') + ->answers(NanookFixtures::pickupLocationsOkAnswer()) + + ->whenCalled('open_url') + ->with('http://bib.valensol.net/service/GetPickupLocation/bibId/312413/patronId/789789789/siteId/37') + ->answers(NanookFixtures::pickupLocationsOkAnswer()) + + ->whenCalled('open_url') + ->with('http://bib.valensol.net/service/HoldTitle/bibId/312413/patronId/789789789/pickupLocation/') + ->answers(NanookFixtures::pickupLocationsOkAnswer()) + + ->whenCalled('open_url') + ->with('http://bib.valensol.net/service/GetPickupLocation/bibId/312413/patronId/789789789/siteId/10') + ->answers(NanookFixtures::pickupLocationsOkAnswer()) + + ->whenCalled('hasErrors') + ->answers(false); + + $_service = Class_WebService_SIGB_Nanook_Service::newInstance() + ->setServerRoot('http://bib.valensol.net') + ->setUseCardNumber('1301500012') + ->setWebClient($this->_mock_web_client); + + $this + ->_service = Class_WebService_SIGB_Nanook::setService(['url_serveur' => 'http://bib.valensol.net', + 'provide_pickup_locations' => true, + 'use_card_number' => '1301500012', + 'id_bib' => 37, + 'type' => 7], + $_service); + + Class_WebService_SIGB_AbstractRESTService::shouldThrowError(true); + + ZendAfi_Auth::getInstance()->logUser($this->_john_lemon); + } + + + public function tearDown() : void + { + $this->_service = null; + $this->_mock_web_client = null; + Class_WebService_SIGB_Nanook::reset(); + Class_WebService_SIGB_AbstractRESTService::shouldThrowError(false); + parent::tearDown(); + } + + + /** @test */ + public function reservationPickupAjaxForItemDifferentIlsShouldDisplayReservationImpossible() { + Class_CosmoVar::setValueOf('site_retrait_resa', 0); + Class_CosmoVar::setValueOf('centralized_hold_mode', 34); + $this->dispatch('/recherche/reservation-pickup-ajax/id_bib/36/copy_id/2347/id_origine/312414/id/123'); + $this->assertContains(json_decode( $this->_response->getBody())->content,'Vous ne pouvez pas réserver cet exemplaire !'); + $this->assertContains(json_decode( $this->_response->getBody())->title,'Réservation impossible'); + } + + + /** @test */ + public function reservationPickupAjaxForItemCentralLibraryShouldDisplayReservationEnregistree() { + $this->dispatch('/recherche/reservation-pickup-ajax/id_bib/34/copy_id/2345/id_origine/312412/id/123'); + $this->assertContains('Votre réservation est enregistrée',json_decode( $this->_response->getBody())->content); + $this->assertContains(json_decode( $this->_response->getBody())->title,'Réservation'); + } + + + /** @test */ + public function reservationPickupAjaxForItemSameIlsShouldShowIlsPickupLibraries() { + Class_CosmoVar::setValueOf('site_retrait_resa', 1); + $this->dispatch('/recherche/reservation-pickup-ajax/id_bib/37/copy_id/2346/id_origine/312413/id/123'); + $this->assertContains('First library', json_decode($this->_response->getBody())->content); + } + + + /** @test */ + public function reservationPickupAjaxForItemNotInIlsCentralizedHoldModeShouldCallCentralizedHold() { + Class_CosmoVar::setValueOf('site_retrait_resa', 0); + Class_CosmoVar::setValueOf('centralized_hold_mode', 36); + $this->dispatch('/recherche/reservation-pickup-ajax/id_bib/36/copy_id/2347/id_origine/312414/id/123'); + $this->assertContains('Votre réservation est enregistrée',json_decode( $this->_response->getBody())->content); + } + + + /** @test */ + public function reservationPickupAjaxForItemNotInIlsCentralizedHoldModeAndSiteRetraitResaEnabledShouldCallCentralizedHold() { + Class_CosmoVar::setValueOf('site_retrait_resa', 1); + Class_CosmoVar::setValueOf('centralized_hold_mode', 36); + $this->dispatch('/recherche/reservation-pickup-ajax/id_bib/36/copy_id/2347/id_origine/312414/id/123'); + $this->assertContains('Votre réservation est enregistrée',json_decode( $this->_response->getBody())->content); + } + + + /** @test */ + public function reservationPickupAjaxWithUnknownItemShouldContainsError() { + $this->dispatch('/recherche/reservation-pickup-ajax/id_bib/36/copy_id/7897892347/id_origine/312414/id/123'); + $this->assertContains('Document introuvable',json_decode( $this->_response->getBody())->content); + } +} + + + + +class TemplatesAbonneCentralizedHoldsPickupLocationForOrpheeTest + extends TemplatesAbonneCentralizedHoldsTestCase +{ + protected $_json; + protected $_xpath; + public function setUp() : void + { + parent::setUp(); + $user = $this->fixture(Class_Users::class, + ['id' => 98, + 'nom' => 'foix', + 'prénom' => 'Madame', + 'idAbon' => '130154', + 'id_int_bib' => 36, + 'id_bib' => 36, + 'password' => '@qsdlkfj', + 'login' => 'mfoix', + 'id_origine' => 2243, + 'mail' => 'test@exemple.com' + ]); + $comm_params = ['url_serveur' => 'tests/fixtures/orphee4.wsdl', + 'allow_hold_available_items' => true, + 'use_card_number' => '1301500012']; + Class_IntBib::find(36)->setCommParams($comm_params)->assertSave(); + + ZendAfi_Auth::getInstance()->logUser($user); + $this->_orphee = Class_WebService_SIGB_Orphee_Service::getService('tests/fixtures/orphee4.wsdl', null, true); + $this->_orphee->setSearchClient($this->_search_client); + $this->_orphee->isConnected(); + + Class_CosmoVar::setValueOf('site_retrait_resa', 1); + Class_CosmoVar::setValueOf('centralized_hold_mode', 34); + + Class_WebService_SIGB_Orphee::setService(array_merge($comm_params, + ['id_bib' => 36, + 'type' => Class_IntBib::COM_ORPHEE, + 'use_card_number' => '1301500012']), + $this->_orphee); + + $this->dispatch('/recherche/reservation-pickup-ajax/id_bib/36/copy_id/2347/id_origine/312414/id/2243'); + $this->_xpath = new Storm_Test_XPath; + $this->_json = (json_decode($this->_response->getBody()))->content; + } + + + /** @test */ + public function pageShouldContainsTwoChoices() + { + $this->_xpath->assertXPathCount($this->_json, + '//label[contains(@class,"multi-element-label col-form-label")]', + 2 + ); + } + + + /** @test */ + public function firstLabelShouldContainsFoix() + { + $this->_xpath->assertXPathContentContains($this->_json, + '(//label[contains(@class,"multi-element-label col-form-label")])[1]', + 'Foix'); + } + + + /** @test */ + public function secondLabelShouldContainsMontgaillard() + { + $this->_xpath->assertXPathContentContains($this->_json, + '(//label[contains(@class,"multi-element-label col-form-label")])[2]', + 'Montgaillard'); + } +} + + + + +abstract class TemplatesAbonneCentralizedHoldsForOrpheeMultipleIntBibsTestCase + extends TemplatesAbonneCentralizedHoldsTestCase +{ + public function setUp() : void + { + parent::setUp(); + $this->fixture(Class_Bib::class, + ['id' => 41, + 'mail' => 'test@WonderTown.net', + 'libelle' => 'WonderTown' + ]); + + $this->fixture(Class_IntBib::class, + ['id' => 41, + 'id_bib' => 41, + 'nom' => 'SleepyHollowTown', + 'nom_court' => 'WT', + 'mail' => 'intbib@slTown.net', + 'sigb' => Class_IntBib::SIGB_ORPHEE, + 'comm_sigb' => Class_IntBib::COM_ORPHEE, + 'comm_params' => ['url_serveur' => 'tests/fixtures/orphee4.wsdl', + 'allow_hold_available_items' => true, + 'use_card_number' => '1301500012']]); + + $this->fixture(Class_Bib::class, + ['id' => 42, + 'mail' => 'test@wonkaTown.net', + 'libelle' => 'WonkaTown' + ]); + + $this->fixture(Class_IntBib::class, + ['id' => 42, + 'id_bib' => 42, + 'nom' => 'WonkaTown', + 'nom_court' => 'WT', + 'mail' => 'intbib@WonderTown.net', + 'sigb' => Class_IntBib::SIGB_ORPHEE, + 'comm_sigb' => Class_IntBib::COM_ORPHEE, + 'comm_params' => ['url_serveur' => 'tests/fixtures/orphee4.wsdl', + 'allow_hold_available_items' => true, + 'use_card_number' => '1301500012']]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 75, + 'id_bib' => 41, + 'id_origine' => 25, + 'code' => 25, + 'libelle' => 'SleepyHollowTown', + 'no_pickup' => 0,]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 76, + 'id_bib' => 41, + 'id_origine' => 26, + 'code' => 26, + 'libelle' => 'SleepyHollowTown 2', + 'no_pickup' => 0,]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 77, + 'id_bib' => 41, + 'id_origine' => 27, + 'code' => 'SL3NotShown', + 'libelle' => 'SleepyHollowTown Not shown', + 'no_pickup' => 1,]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 78, + 'id_bib' => 42, + 'id_origine' => 28, + 'code' => 'WKT', + 'libelle' => 'WonkaTown', + 'no_pickup' => 0,]); + + $user = $this->fixture(Class_Users::class, + ['id' => 98, + 'nom' => 'foix', + 'prénom' => 'Madame', + 'idAbon' => '10900000753', + 'id_int_bib' => 36, + 'id_bib' => 36, + 'password' => '@qsdlkfj', + 'login' => '10900000753', + 'id_origine' => 2243 + ]); + + $comm_params = ['url_serveur' => 'tests/fixtures/orphee4.wsdl', + 'allow_hold_available_items' => true, + 'use_card_number' => '1301500012']; + Class_IntBib::find(36)->setCommParams($comm_params)->assertSave(); + + ZendAfi_Auth::getInstance()->logUser($user); + $this->_orphee = Class_WebService_SIGB_Orphee_Service::getService('tests/fixtures/orphee4.wsdl', null, true); + $this->_search_client + ->whenCalled('GetLstDmt') + ->with(GetLstDmt::withNtcAndFas('312414', 0)) + ->answers(GetLstDmtResponse::withResult(OrpheeFixtures::xmlGetLstDmtMillenium())) + + ->whenCalled('RsvDmtAdh') + ->with(RsvDmtAdh::withNoticeItemUser('312414', '', '100753')) + ->answers(RsvDmtAdhResponse::withResult('<?xml version="1.0" encoding="utf-8"?><datas><msg><code><![CDATA[1]]></code><libelle><![CDATA[YESS ]]></libelle></msg></datas>')) + + ->whenCalled('GetLstRsv') + ->with(GetLstRsv::withAdhAndCountPerPage(100753, 200)) + ->answers(GetLstRsvResponse::withResult(OrpheeFixtures::xmlGetLstRsvHenryDupont())); + + + $this->_orphee->setSearchClient($this->_search_client); + $this->_orphee->beHoldModeItem(); + $this->_orphee->isConnected(); + + Class_CosmoVar::setValueOf('site_retrait_resa', 1); + Class_CosmoVar::setValueOf('centralized_hold_mode', 34); + + Class_WebService_SIGB_Orphee::setService(array_merge($comm_params, + ['id_bib' => 36, + 'type' => Class_IntBib::COM_ORPHEE, + 'use_card_number' => '1301500012']), + $this->_orphee); + } +} + + + + +class TemplatesAbonneCentralizedHoldsPickupLocationForOrpheeMultipleIntBibsTest + extends TemplatesAbonneCentralizedHoldsForOrpheeMultipleIntBibsTestCase +{ + protected $_xpath, $_json; + public function setUp() : void + { + parent::setUp(); + $this->dispatch('/recherche/reservation-pickup-ajax/id_bib/36/copy_id/2347/id_origine/312414/id/2243'); + $this->_xpath = new Storm_Test_XPath; + $this->_json = (json_decode($this->_response->getBody()))->content; + } + + + /** @test */ + public function pageShouldContainsFiveChoices() + { + $this->_xpath->assertXPathCount($this->_json, + '//label[contains(@class,"multi-element-label")]', + 5 + ); + } + + + /** @test */ + public function thirdLabelShouldContainsSleepyHollowTown() + { + $this->_xpath->assertXPathContentContains($this->_json, + '(//label[contains(@class,"multi-element-label col-form-label")])[3]', + 'SleepyHollowTown'); + } + + + /** @test */ + public function fourthLabelShouldContainsSleepyHollowTown2() + { + $this->_xpath->assertXPathContentContains($this->_json, + '(//label[contains(@class,"multi-element-label col-form-label")])[4]','SleepyHollowTown 2'); + } + + + /** @test */ + public function fifthLabelShouldContainsWonkaTown() + { + $this->_xpath->assertXPathContentContains($this->_json, + '(//label[contains(@class,"multi-element-label col-form-label")])[5]','WonkaTown'); + } +} + + + + +class TemplatesAbonneCentralizedHoldsReservationAjaxForOrpheeMultipleIntBibsTest + extends TemplatesAbonneCentralizedHoldsForOrpheeMultipleIntBibsTestCase +{ + public function setUp() : void + { + parent::setUp(); + + $this->dispatch('recherche/reservationajax/id_bib/36/copy_id/2347/id_origine/312414/id/2243/code_annexe/76'); + } + + + /** @test */ + public function bodyContentShouldContainsReservationEnregistree() + { + $this->assertContains('Votre réservation est enregistrée.<br>Nous vous informerons quand le document ', + json_decode( $this->_response->getBody())->content); + } +} + + + + +class TemplatesAbonneCentralizedHoldsCentralisedHoldWithErrorsTest + extends AbstractControllerTestCase +{ + protected $_john_lemon, + $_orphee, + $_search_client; + + public function setUp() : void + { + parent::setUp(); + + $comm_params = ['url_serveur' => 'tests/fixtures/orphee.wsdl', + 'allow_hold_available_items' => true]; + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 82, + 'id_bib' => 34, + 'code' => 34, + 'id_origine' => 34, + 'libelle' => 'JolieVille' + ]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 84, + 'id_bib' => 36, + 'code' => 'Fx', + 'id_origine' => 'Fx', + 'libelle' => 'Foix' + ]); + + $this->fixture(Class_Bib::class, + ['id' => 34, + 'mail' => 'test@jolieville.net', + 'libelle' => 'JolieVille' + ]); + + $this->fixture(Class_IntBib::class, + ['id' => 34, + 'id_bib' => 34, + 'nom' => 'JolieVille', + 'nom_court' => 'JV', + 'sigb' => Class_IntBib::SIGB_ORPHEE, + 'comm_sigb' => Class_IntBib::COM_ORPHEE, + 'comm_params' => $comm_params + ]); + + $this->fixture(Class_IntBib::class, + ['id' => 37, + 'id_bib' => 37, + 'nom' => 'Eightth Wonder', + 'nom_court' => '8THW', + 'mail' => 'intbibqsdf@WonderTown.net', + 'sigb' => Class_IntBib::SIGB_NANOOK, + 'comm_sigb' => Class_IntBib::COM_NANOOK, + 'comm_params' => ['url_serveur' => 'http://bib.valensol.net', + 'provide_pickup_locations' => true, + 'use_card_number' => '1301500012']]); + + $this->_john_lemon = + $this->fixture(Class_Users::class, + ['id' => 142, + 'idAbon' => '', + 'nom' => 'Lemon', + 'prenom' => 'John', + 'login' => 'uselogon', + 'idabon' => '130425', + 'password' => 'secret', + 'mail' => 'johnlemon@abbeyroad.net', + 'id_int_bib' => 37, + 'id_bib' => 37, + 'id_sigb' => '789789789' + ]); + + $this->fixture(Class_Notice::class, + ['id' => 3, + 'titre' => 'La disparition', + 'auteurs' => 'Georges PEREC', + 'unimarc' => (new Class_NoticeUnimarc_Fluent) + ->zoneWithChildren('200', ['a' => 'La disparition', + 'f' => 'PEREC, Georges', + 't' => 't. 1']) + ->render(), + + 'type_doc' => Class_TypeDoc::LIVRE, + ]); + + $this->fixture(Class_Exemplaire::class, + ['id' => 2345, + 'id_notice' => 3, + 'id_bib' => 34, + 'annexe' => 34, + 'id_int_bib' => 34, + 'type_doc' => Class_TypeDoc::LIVRE, + 'id_origine' => 312412, + 'code_barres' => '00106001488142']); + + $this->_search_client = $this->_setupSearchClient(); + + $allow_hold_available_items=true; + $this->_orphee = Class_WebService_SIGB_Orphee_Service::getService('tests/fixtures/orphee.wsdl', null, $allow_hold_available_items); + $this->_orphee->setSearchClient($this->_search_client); + $this->_orphee + ->beHoldModeItem() + ->isConnected(); + + Class_WebService_SIGB_Orphee::setService(array_merge($comm_params, + ['id_bib' => 34, + 'type' => Class_IntBib::COM_ORPHEE]), + $this->_orphee); + + Class_CosmoVar::setValueOf('centralized_hold_mode', 34); + ZendAfi_Auth::getInstance()->logUser($this->_john_lemon); + $this->dispatch('/recherche/reservationajax/id_bib/36/copy_id/2345/id_origine/312412/id/123'); + } + + + protected function _setupSearchClient() + { + return + $this->mock() + ->whenCalled('__getLastRequest') + ->answers('last request') + + ->whenCalled('__getLastResponse') + ->answers('last response') + + ->whenCalled('__getLastResponseHeaders') + ->answers('last response headers') + + ->whenCalled('__getLastRequestHeaders') + ->answers('last response') + + ->whenCalled('hasFunction') + ->answers(false) + + ->whenCalled('__setCookie') + ->answers(null) + + ->whenCalled('EndSession') + ->answers(new EndSessionResponse()) + + ->whenCalled('hasFunction')->with('GetId')->answers(true) + + ->whenCalled('GetId') + ->with(new GetId()) + + ->answers(GetIdResponse::withIdResult('1234')) + + ->whenCalled('hasFunction')->with('GetAdh')->answers(true) + + ->whenCalled('GetAdh') + ->with(GetAdh::withNo('10900000753')) + ->answers(Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetInfoUserCarteHenryDupont())) + + ->whenCalled('GetAdh') + ->with(GetAdh::withNo('1301500012')) + ->answers(Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetAdhFoix())) + + ->whenCalled('GetLstDmt') + ->with(GetLstDmt::withNtcAndFas('312412', 0)) + ->answers(GetLstDmtResponse::withResult(OrpheeFixtures::xmlGetLstDmtMillenium())) + + ->whenCalled('RsvDmtAdh') + ->with(RsvDmtAdh::withNoticeItemUser('312412', '148814', '1301500012')) + ->answers(RsvDmtAdhResponse::withResult('<?xml version="1.0" encoding="utf-8"?><datas><msg><code><![CDATA[0]]></code><libelle><![CDATA[Réservation impossible : Maximum de réservations atteint par support ]]></libelle></msg></datas>')); + } + + + /** @test */ + public function responseShouldContainsReservationImpossible() + { + $this->assertContains('Réservation impossible : Maximum de réservations atteint par support', + json_decode( $this->_response->getBody())->content, + ); + } +} + + + + +/* @see https://forge.afi-sa.net/issues/209507 */ +require_once 'tests/fixtures/DecalogFixtures.php'; +class TemplatesAbonneCentralizedHoldsDecalogTest + extends AbstractControllerTestCase{ + protected + $_search_client, + $_mock_web_client, + $_orphee, + $_john_lemon; + + public function setUp() : void + { + parent::setUp(); + Class_CosmoVar::setValueOf('centralized_hold_mode', 34); + + $this->_buildTemplateProfil(['id'=>1]); + + $comm_params = ['url_serveur' => 'tests/fixtures/orphee.wsdl', + 'allow_hold_available_items' => true]; + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 82, + 'id_bib' => 34, + 'code' => 34, + 'id_origine' => 34, + 'libelle' => 'JolieVille' + ]); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 83, + 'id_bib' => 37, + 'code' => 37, + 'id_origine' => 37, + 'libelle' => 'WonderTown' + ]); + + $this->fixture(Class_Bib::class, + ['id' => 34, + 'mail' => 'test@jolieville.net', + 'libelle' => 'JolieVille' + ]); + + $this->fixture(Class_IntBib::class, + ['id' => 34, + 'id_bib' => 34, + 'nom' => 'JolieVille', + 'nom_court' => 'JV', + 'sigb' => Class_IntBib::SIGB_ORPHEE, + 'comm_sigb' => Class_IntBib::COM_ORPHEE, + 'comm_params' => $comm_params + ]); + + $this->_john_lemon = + $this->fixture(Class_Users::class, + ['id' => 142, + 'idAbon' => '', + 'nom' => 'Lemon', + 'prenom' => 'John', + 'login' => 'uselogon', + 'idabon' => '130425', + 'password' => 'secret', + 'mail' => 'johnlemon@abbeyroad.net', + 'id_int_bib' => 37, + 'id_bib' => 37, + 'id_sigb' => '789789789' + ]); + + $this->fixture(Class_IntBib::class, + ['id' => 37, + 'id_bib' => 37, + 'nom' => 'Eightth Wonder', + 'nom_court' => '8THW', + 'mail' => 'intbibqsdf@WonderTown.net', + 'sigb' => Class_IntBib::SIGB_DECALOG, + 'comm_sigb' => Class_IntBib::COM_DECALOG, + 'comm_params' => ['url_serveur' => 'http://bib.mondecalog/xxx', + 'key' => 'my-key', + 'institution_code' => 'my-institution-code', + 'record_id_prefix' => 'EPPK-', + 'provide_pickup_locations' => false, + 'use_card_number' => '1301500012']]); + + + $this->fixture(Class_Notice::class, + ['id' => 3, + 'titre' => 'La disparition', + 'auteurs' => 'Georges PEREC', + 'unimarc' => (new Class_NoticeUnimarc_Fluent) + ->zoneWithChildren('200', ['a' => 'La disparition', + 'f' => 'PEREC, Georges', + 't' => 't. 1']) + ->render(), + + 'type_doc' => Class_TypeDoc::LIVRE, + ]); + + $this->fixture(Class_Exemplaire::class, + ['id' => 2345, + 'id_notice' => 3, + 'id_bib' => 34, + 'annexe' => 34, + 'id_int_bib' => 34, + 'type_doc' => Class_TypeDoc::LIVRE, + 'id_origine' => 312412, + 'code_barres' => '012345']); + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 37, + 'libelle' => 'Paris', + 'id_bib' => 37, + 'id_origine' => 10]); + + $this->fixture(Class_Exemplaire::class, + ['id' => 2346, + 'id_notice' => 3, + 'id_bib' => 37, + 'id_int_bib' => 37, + 'type_doc' => Class_TypeDoc::LIVRE, + 'id_origine' => 312413, + 'annexe' =>37, + 'code_barres' => '012346']); + + $this->_search_client = $this->_setupSearchClient(); + + $allow_hold_available_items=true; + $this->_orphee = Class_WebService_SIGB_Orphee_Service::getService('tests/fixtures/orphee.wsdl', null, $allow_hold_available_items); + $this->_orphee->setSearchClient($this->_search_client); + $this->_orphee->isConnected(); + + Class_WebService_SIGB_Orphee::setService(array_merge($comm_params, + ['id_bib' => 34, + 'type' => Class_IntBib::COM_ORPHEE]), + $this->_orphee); + + + $this->_mock_web_client = $this->mock() + ->whenCalled('postRawData') + ->with('http://decalog-sigb/my-institution-code/user/login', + 'username=a%40a.fr&password=T4vEyXK', + 'application/x-www-form-urlencoded', + ['headers' => 'apikey:my-key']) + ->answers(DecalogFixtures::jsonUserLoginFrodon()) + ->whenCalled('postRawData') + ->with('http://decalog-sigb/my-institution-code/user/login', + 'username=a%40a.fr&password=secret', + 'application/x-www-form-urlencoded', + ['headers' => 'apikey:my-key']) + ->answers(DecalogFixtures::jsonUserLoginFrodon()) + + ->whenCalled('postRawData') + ->with('http://decalog-sigb/my-institution-code/user/login', + 'username=a%40a.fr&password=9xTJa%2BwMw%2BgA%2FYdugRgj7A', + 'application/x-www-form-urlencoded', + ['headers' => 'apikey:my-key']) + ->answers(DecalogFixtures::jsonUserLoginFrodon()) + + ->whenCalled('open_url') + ->with('http://decalog-sigb/my-institution-code/user/3396790941099222416', + ['headers' => 'apikey:my-key']) + ->answers(DecalogFixtures::jsonUserDetailFrodon()); + + Class_WebService_SIGB_Decalog::setService([], null); + Class_WebService_SIGB_Decalog + ::getService(['url_serveur' => 'http://bib.mondecalog/xxx', + 'key' => 'my-key', + 'institution_code' => 'my-institution-code', + 'record_id_prefix' => 'EPPK-', + 'provide_pickup_locations' => false, + 'use_card_number' => '1301500012' + ]) + ->setWebClient($this->_mock_web_client); + + Class_WebService_SIGB_AbstractRESTService::shouldThrowError(true); + + ZendAfi_Auth::getInstance()->logUser($this->_john_lemon); + $this->dispatch('/recherche/reservation-pickup-ajax/id_bib/34/copy_id/2345/id_origine/312412/id/2243'); + } + + + protected function _setupSearchClient() + { + return $this + ->mock() + + ->whenCalled('__getLastRequest') + ->answers('last request') + + ->whenCalled('__getLastResponse') + ->answers('last response') + + ->whenCalled('__getLastResponseHeaders') + ->answers('last response headers') + + ->whenCalled('__getLastRequestHeaders') + ->answers('last response') + + ->whenCalled('hasFunction') + ->answers(false) + + ->whenCalled('__setCookie') + ->answers(null) + + ->whenCalled('EndSession') + ->answers(new EndSessionResponse()) + + ->whenCalled('hasFunction')->with('GetId')->answers(true) + + ->whenCalled('GetId') + ->with(new GetId()) + + ->answers(GetIdResponse::withIdResult('1234')) + + ->whenCalled('hasFunction')->with('GetAdh')->answers(true) + + ->whenCalled('GetAdh') + ->with(GetAdh::withNo('10900000753')) + ->answers(Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetInfoUserCarteHenryDupont())) + + ->whenCalled('GetAdh') + ->with(GetAdh::withNo('uselogon')) + ->answers(Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetInfoUserCarteHenryDupont())) + + ->whenCalled('GetAdh') + ->with(GetAdh::withNo('1301500012')) + ->answers(Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetAdhFoix())) + + ->whenCalled('GetLstDmt') + ->with(GetLstDmt::withNtcAndFas('312412', 0)) + ->answers(GetLstDmtResponse::withResult(OrpheeFixtures::xmlGetLstDmtMillenium())) + + ->whenCalled('GetLstDmt') + ->with(GetLstDmt::withNtcAndFas('312414', 0)) + ->answers(GetLstDmtResponse::withResult(OrpheeFixtures::xmlGetLstDmtMillenium())) + + ->whenCalled('GetLstRsv') + ->with(GetLstRsv::withAdhAndCountPerPage(1301500012, 200)) + ->answers(GetLstRsvResponse::withResult(OrpheeFixtures::xmlGetLstRsvHenryDupont())) + + ->whenCalled('RsvNtcAdh') + ->with(RsvNtcAdh::withNoticeUserNo('312414', '1301500012', 0)) + ->answers(RsvNtcAdhResponse::withResult('<datas><msg><code><![CDATA[1]]></code><libelle><![CDATA[Réservation mise en attente]]></libelle></msg></datas>')) + + ->whenCalled('RsvNtcAdh') + ->with(RsvNtcAdh::withNoticeUserNo('312412', '1301500012', 0)) + ->answers(RsvNtcAdhResponse::withResult('<datas><msg><code><![CDATA[1]]></code><libelle><![CDATA[Réservation mise en attente]]></libelle></msg></datas>')) + + ->whenCalled('RsvDmtAdh') + ->with(RsvDmtAdh::withNoticeItemUser('312414', '', '100753')) + ->answers(RsvDmtAdhResponse::withResult('<datas><msg><code><![CDATA[1]]></code><libelle><![CDATA[Réservation mise en attente]]></libelle></msg></datas>')) + + ->whenCalled('RsvDmtAdh') + ->with(RsvDmtAdh::withNoticeItemUser('312414', '', '1301500012')) + ->answers(RsvDmtAdhResponse::withResult('<datas><msg><code><![CDATA[1]]></code><libelle><![CDATA[Réservation mise en attente]]></libelle></msg></datas>')) + + ->whenCalled('GetLstRsv') + ->with(GetLstRsv::withAdhAndCountPerPage('100753', 200)) + ->answers(GetLstRsvResponse::withResult(OrpheeFixtures::xmlGetLstRsvHenryDupont())); + } + + + public function tearDown() : void + { + Class_WebService_SIGB_Decalog::setService([], null); + $this->_mock_web_client = null; + Class_WebService_SIGB_Decalog::reset(); + Class_WebService_SIGB_Orphee::reset(); + parent::tearDown(); + } + + + /** @test */ + public function bodyContentShouldContainsReservationEnregistree() + { + $this->assertContains('Votre réservation est enregistrée.<br>Nous vous informerons quand le document ', + json_decode( $this->_response->getBody())->content); + } +} diff --git a/tests/scenarios/Templates/TemplatesAbonneOrpheeBadgePretsTest.php b/tests/scenarios/Templates/TemplatesAbonneOrpheeBadgePretsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..fc15d00bc83d3199569db71d55fdb135a98e7077 --- /dev/null +++ b/tests/scenarios/Templates/TemplatesAbonneOrpheeBadgePretsTest.php @@ -0,0 +1,200 @@ +<?php +/** + * Copyright (c) 2012-2024, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +include_once('Class/WebService/SIGB/Orphee/SessionStrategy.php'); + +include_once 'tests/library/Class/WebService/SIGB/OrpheeFixtures.php'; + +class TemplatesAbonneOrpheeBadgePretsTest + extends AbstractControllerTestCase +{ + protected + $_search_client, + $_orphee; + + + public function setUp() : void + { + parent::setUp(); + $this->_buildTemplateProfil(['id'=>1]); + + $comm_params = ['url_serveur' => 'tests/fixtures/orphee.wsdl', + 'allow_hold_available_items' => true]; + + $this->fixture(Class_CodifAnnexe::class, + ['id' => 82, + 'code' => 34, + 'id_origine' => 34, + 'libelle' => 'JolieVille' + ]); + + $this->fixture(Class_Bib::class, + ['id' => 34, + 'mail' => 'test@jolieville.net', + 'libelle' => 'JolieVille' + ]); + + $this->fixture(Class_IntBib::class, + ['id' => 34, + 'id_bib' => 34, + 'nom' => 'JolieVille', + 'nom_court' => 'JV', + 'comm_sigb' => Class_IntBib::COM_ORPHEE, + 'comm_params' => $comm_params + ]); + + $user = $this->fixture(Class_Users::class, + ['id' => 143, + 'idAbon' => '1301500012', + 'role_level' => 2, + 'nom' => 'FOIX', + 'prenom' => 'FPV', + 'login' => '1301500012', + 'password' => 's3cr3t', + 'id_int_bib' => 34, + 'id_site' => 34 + ]); + + $this->_search_client = $this->mock(); + $this->_search_client + ->whenCalled('__getLastRequest') + ->answers('last request') + + ->whenCalled('__getLastResponse') + ->answers('last response') + + ->whenCalled('__getLastResponseHeaders') + ->answers('last response headers') + + ->whenCalled('__getLastRequestHeaders') + ->answers('last response') + + ->whenCalled('hasFunction') + ->answers(false) + + ->whenCalled('__setCookie') + ->answers(null) + + ->whenCalled('EndSession') + ->with(new EndSession) + ->answers(new EndSessionResponse()) + + ->whenCalled('hasFunction')->with('GetId')->answers(true) + + ->whenCalled('GetId') + ->with(new GetId()) + ->answers(GetIdResponse::withIdResult('1234')) + + ->whenCalled('hasFunction') + ->with('GetAdh') + ->answers(true) + + ->whenCalled('hasFunction') + ->with('GetToken') + ->answers(false) + + ->whenCalled('GetAdh') + ->with(GetAdh::withNo('10900000753')) + ->answers(Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetInfoUserCarteHenryDupont())) + + ->whenCalled('GetAdh') + ->with(GetAdh::withNo('1301500012')) + ->answers(Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetAdhFoix())) + + ->whenCalled('GetAdh') + ->with(GetAdh::withCardAndPassword('1301500012',$user->getPassword())) + ->answers(Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetAdhFoix())) + + ->whenCalled('GetLstPret') + ->with(GetLstPret::withAdhAndCountPerPage('1301500012',1)) + ->answers(Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetLstPretHenryDupont(45))) + + ->whenCalled('SetCritPrets') + ->with(SetCritPrets::withCodeAndVal(1,37)) + ->answers(true) + + ->whenCalled('SetTri') + ->with(SetTri::withTypeTriAndOrdre(4,2)) + ->answers(true) + + ->whenCalled('GetLstRsv') + ->with(GetLstRsv::withAdhAndCountPerPage('1301500012',200)) + ->answers(Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetLstRsvHenryDupont())) + + ->whenCalled('GetLstPret') + ->with(GetLstPret::withAdhAndCountPerPage('1301500012',1)) + ->willDo(fn() => + (1 == $this->_search_client->methodCallCount('GetLstPret')) + ? Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetLstPretHenryDupont(12)) + : Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetLstPretHenryDupont(5))) + ->beStrict(); + + Class_CommSigb::shouldThrowError(true); + + $this->_orphee = Class_WebService_SIGB_Orphee_Service::getService('tests/fixtures/orphee.wsdl', null, true); + $this->_orphee->setSearchClient($this->_search_client); + $this->_orphee->isConnected(); + + Class_WebService_SIGB_Orphee::setService(array_merge($comm_params, + ['id_bib' => 34, + 'type' => Class_IntBib::COM_ORPHEE]), + $this->_orphee); + + ZendAfi_Auth::getInstance()->logUser($user); + + $this->dispatch('/abonne/fiche/id/143'); + } + + + public function tearDown() : void + { + Class_WebService_SIGB_Orphee::reset(); + parent::tearDown(); + } + + + /** @test */ + public function badgeNbPretsEnCoursShouldContains12PretsEnCours() + { + $this->assertXPathContentContains('//span[contains(@class, "badge_text")]', '12 prêt(s) en cours', $this->_response->getBody()); + } + + + /** @test */ + public function badgeNbPretsEnRetardShouldContains5PretsEnRetard() + { + $this->assertXPathContentContains('//span[contains(@class, "badge_text")]', '5 prêt(s) en retard'); + } +} diff --git a/tests/scenarios/Templates/TemplatesAuthPreRegisterTest.php b/tests/scenarios/Templates/TemplatesAuthPreRegisterTest.php index d5f673767bafeaf9197503c8d78d5f3552aaffbd..190b048ef3d4246d04436fba48f12221b8f4eae6 100644 --- a/tests/scenarios/Templates/TemplatesAuthPreRegisterTest.php +++ b/tests/scenarios/Templates/TemplatesAuthPreRegisterTest.php @@ -40,12 +40,22 @@ abstract class TemplatesAuthPreRegisterTestCase extends AbstractControllerTestCa protected function _fixturesIntBib() : self { + $this->fixture(Class_Bib::class, + ['id' => 1, + 'libelle' => 'Tombouctou']); + $this->fixture(Class_IntBib::class, ['id' => 1, + 'id_bib' => 1, 'comm_params' => ['url_serveur' => 'http://super.nano.ok/ilsdi/arcadia', 'pre-registration' => 1], 'comm_sigb' => Class_IntBib::COM_NANOOK]); + $this->fixture(Class_CodifAnnexe::class, + ['id' => 9983, + 'id_bib' => 1, + 'libelle' => 'Tombouctou']); + return $this; } } @@ -71,7 +81,7 @@ class TemplatesAuthPreRegisterActionDispatchTest /** @test */ public function pageShouldContainsSelectedSiteWithEmptyOptionAndOrdered() { $this->assertXPath('//select[@class="zendafi_form_preregistration_nanook_site form-control form-control-sm custom-select custom-select-sm"][@required="required"]/option[not(text())]'); - $this->assertXPath('//select[@class="zendafi_form_preregistration_nanook_site form-control form-control-sm custom-select custom-select-sm"][@required="required"]/option[@label="Tombouctou"][@value="1"][@selected="selected"][text()="Tombouctou"][1]'); + $this->assertXPath('//select[@class="zendafi_form_preregistration_nanook_site form-control form-control-sm custom-select custom-select-sm"][@required="required"]/option[@label="Tombouctou"][@value="1"][@selected="selected"][text()="Tombouctou"][1]', $this->_response->getBody()); } } diff --git a/tests/scenarios/Templates/TemplatesOrpheeOrderLoansTest.php b/tests/scenarios/Templates/TemplatesOrpheeOrderLoansTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3c118e6c30099a83d4f20a3980ca244b74d01e1e --- /dev/null +++ b/tests/scenarios/Templates/TemplatesOrpheeOrderLoansTest.php @@ -0,0 +1,159 @@ +<?php + +/** + * Copyright (c) 2012-2025, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH 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). + * + * BOKEH 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 BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +include_once 'tests/library/Class/WebService/SIGB/OrpheeFixtures.php'; + +class TemplatesOrpheeOrderLoansTest extends AbstractControllerTestCase +{ + protected $_search_client; + + public function setUp(): void + { + parent::setUp(); + + $this->_buildTemplateProfil(['id' => 72]); + + $comm_params = ['url_serveur' => 'tests/fixtures/orphee.wsdl', + 'allow_hold_available_items' => 0]; + + $this->fixture(Class_IntBib::class, + ['id' => 34, + 'comm_sigb' => Class_IntBib::COM_ORPHEE, + 'sigb' => Class_IntBib::SIGB_ORPHEE, + 'comm_params' => $comm_params]); + + $user = $this->fixture(Class_Users::class, + ['id' => 143, + 'idAbon' => '1301500012', + 'role_level' => 2, + 'nom' => 'FOIX', + 'prenom' => 'FPV', + 'login' => '1301500012', + 'password' => 's3cr3t', + 'id_int_bib' => 34, + 'id_site' => 34]); + + $this->_search_client = $this + ->mock() + ->whenCalled('__getLastRequest') + ->answers('last request') + + ->whenCalled('__getLastResponse') + ->answers('last response') + + ->whenCalled('__getLastResponseHeaders') + ->answers('last response headers') + + ->whenCalled('__getLastRequestHeaders') + ->answers('last response') + + ->whenCalled('hasFunction') + ->answers(true) + + ->whenCalled('__setCookie') + ->answers(null) + + ->whenCalled('EndSession') + ->with(new EndSession) + ->answers(new EndSessionResponse()) + + ->whenCalled('hasFunction') + ->answers(true) + ->whenCalled('hasFunction')->with('GetAdh')->answers(true) + ->whenCalled('hasFunction')->with('GetId')->answers(true) + + ->whenCalled('SetCritPrets') + ->with(SetCritPrets::withCodeAndVal(1,37)) + ->answers(true) + + ->whenCalled('SetTri') + ->with(SetTri::withTypeTriAndOrdre(7,2)) + ->answers(true) + + ->whenCalled('SetTri') + ->with(SetTri::withTypeTriAndOrdre(4,2)) + ->answers(true) + + ->whenCalled('GetLstPret') + ->with(GetLstPret::withAdhAndCountPerPage('1301500012',20)) + ->willDo(fn() => + (1 == $this->_search_client->methodCallCount('GetLstPret')) + ? Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetLstPretHenryDupont(12)) + : Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetLstPretHenryDupont(5))) + + ->whenCalled('GetAdh') + ->with(GetAdh::withNo('1301500012')) + ->answers(Storm_Test_ObjectWrapper::mock() + ->whenCalled('getXml') + ->answers(OrpheeFixtures::xmlGetAdhFoix())) + ->beStrict(); + + $orphee = Class_WebService_SIGB_Orphee_Service::getService('tests/fixtures/orphee.wsdl', null, true); + $orphee->setSearchClient($this->_search_client); + $orphee->setSessionStrategy( Storm_Test_ObjectWrapper::on(new Class_WebService_SIGB_TestingService()) + ->whenCalled('isConnected')->answers(true) + ->whenCalled('disconnect')->answers(true)); + + Class_WebService_SIGB_Orphee::setService(array_merge($comm_params, + ['id_bib' => 34, + 'type' => Class_IntBib::COM_ORPHEE]), + $orphee); + + ZendAfi_Auth::getInstance()->logUser($user); + + + } + + public function tearDown(): void + { + Class_WebService_SIGB_Orphee::reset(); + parent::tearDown(); + } + + /** @test */ + public function setCritPretShouldBeCalledWithOrder72() + { + $this->dispatch('opac/abonne/ajax-loans/id/143/order/7_2'); + $this->assertTrue($this->_search_client + ->methodHasBeenCalledWithParams('SetTri', + [SetTri::withTypeTriAndOrdre(7, 2)])); + } + + /** @test */ + public function whenCalledWithoutOrderSetTriShouldBeCalledThreeTimesWithOrder42() + { + $this->dispatch('opac/abonne/ajax-loans/id/143/order/'); + $this->assertEquals($this->_search_client->methodCallCount('SetTri'), + 3); + } + + /** @test */ + public function whenCalledWithoutOrderSetTriShouldNotBeCalledsWithOrderEmpty2() + { + $this->dispatch('opac/abonne/ajax-loans/id/143/order/'); + $this->assertFalse($this->_search_client->methodHasBeenCalledWithParams('SetTri',[SetTri::withTypeTriAndOrdre(0, 2)])); + } +} diff --git a/tests/scenarios/Templates/TemplatesSearchTest.php b/tests/scenarios/Templates/TemplatesSearchTest.php index 3055fd99009594079ef3422b7c3742527c4b2847..11b9081f55b90d0ba92f10c0b13a4d1b8bdf3e5d 100644 --- a/tests/scenarios/Templates/TemplatesSearchTest.php +++ b/tests/scenarios/Templates/TemplatesSearchTest.php @@ -20,6 +20,7 @@ */ require_once 'TemplatesTest.php'; +require_once 'tests/fixtures/NanookFixtures.php'; abstract class TemplatesSearchWithSortParameterInWidgetTestCase extends AbstractControllerTestCase { @@ -173,14 +174,14 @@ class TemplatesDispatchIntonationSearchTest extends TemplatesIntonationTestCase ['id' => 1, 'titres' => 'POMME', 'other_terms' => 'HSUJE_RENNES', - 'facettes' => 'T1 Y1', + 'facettes' => 'T1 Y4', 'type' => 1, 'unimarc' => file_get_contents(ROOT_PATH . 'tests/fixtures/unimarc_vernon.txt')]); $this->fixture(Class_Notice::class, ['id' => 2, 'titres' => 'POMME', 'other_terms' => 'HSUJE_RENNES', - 'facettes' => 'T1 Y1', + 'facettes' => 'T1 Y4', 'type' => 1, 'unimarc' => file_get_contents(ROOT_PATH . 'tests/fixtures/unimarc_terry_pratchet.txt')]); @@ -193,7 +194,7 @@ class TemplatesDispatchIntonationSearchTest extends TemplatesIntonationTestCase ['id' => 1, 'libelle' => 'Rennes']); - $this->dispatch('/opac/recherche/simple/expressionRecherche/pomme/id_profil/72/multifacets/T1-Y1/facette/Y1/section/1/page/1/rech_thesaurus_SUJE/rennes'); + $this->dispatch('/opac/recherche/simple/expressionRecherche/pomme/id_profil/72/multifacets/T1-Y4/facette/Y4/section/1/page/1/rech_thesaurus_SUJE/rennes'); } @@ -897,17 +898,36 @@ class TemplatesSearchReservationPickupAjaxConnectedUserTest $user = $this->fixture(Class_Users::class, ['id' => 8989, 'login' => ',eui', + 'role_level' => 2, + 'id_int_bib' => 1, + 'id_site' => 1, + 'idabon' => 'uRSTI89V798', + 'id_sigb' => '897', 'password' => 'ier']); + + $this->fixture(Class_IntBib::class, + ['id' => 1, + 'comm_sigb' => Class_IntBib::COM_NANOOK, + 'comm_params' => ['url_serveur' => 'http://bib.valensol.net', + 'provide_pickup_locations' => true] + ]); + + Class_Exemplaire::find(12) + ->setIdOrigine(789789) + ->setAnnexe(3); + Class_CosmoVar::setValueOf('site_retrait_resa', Class_CosmoVar::PICKUP_LOCATION_CHOICE); ZendAfi_Auth::getInstance()->logUser($user); + Class_Profil::find(1) ->setBoiteOfTypeInDivision(4, Intonation_Library_Widget_Login_Definition::CODE, ['tri' => Class_CriteresRecherche::SORT_NOVELTY_DESC, 'IntonationFormStyle' => 'toggle']) ->assertSave(); + $this->fixture(Class_CodifAnnexe::class, ['id' => 3, 'code' => '37', @@ -915,7 +935,18 @@ class TemplatesSearchReservationPickupAjaxConnectedUserTest 'libelle' => 'Cran']); Class_AdminVar::set('HOLD_SITE_SELECTION_CUSTOM_MESSAGE', '<b>This is an additional text message</b>')->save(); - $this->dispatch('/recherche/reservation-pickup-ajax/id/34/id_notice/34/id_int_bib/2/id_bib/23'); + + Class_HttpClientFactory::forTest() + ->addRequestWithResponse('http://bib.valensol.net:80/service/GetPickupLocation/bibId/0/patronId/0/siteId/0', + NanookFixtures::pickupLocationsOkAnswer()) + + ->addRequestWithResponse('http://bib.valensol.net:80/service/GetPickupLocation/bibId/789789/patronId/897/siteId/37', + NanookFixtures::pickupLocationsOkAnswersAnnecyAndCran()) + + ->addRequestWithResponse('http://bib.valensol.net:80/service/GetPatronInfo/patronId/897', + NanookFixtures::axelPatronInfo()); + + $this->dispatch('/recherche/reservation-pickup-ajax/id/34/id_notice/34/copy_id/12/id_int_bib/2/id_bib/23'); $this->_xpath = new Storm_Test_XPath(); $this->_html = json_decode($this->_response->getBody(), true)['content']; diff --git a/tests/scenarios/Templates/TemplatesWidgetTest.php b/tests/scenarios/Templates/TemplatesWidgetTest.php index f22d1016b1beadd63b495561766a7d457993048c..0a824280c2cf0dcac774f6b08a6c8f9fcad0f60d 100644 --- a/tests/scenarios/Templates/TemplatesWidgetTest.php +++ b/tests/scenarios/Templates/TemplatesWidgetTest.php @@ -697,7 +697,7 @@ class TemplatesWidgetSearchDefaultStyleTest extends TemplatesIntonationTestCase /** @test */ public function searchOptionForAnnexeShouldDisplayTous() { - $this->assertXPath('//div[contains(@class,"boite rech_simple")]//form//select[@name="custom_multifacets_annexe"]//option[1][@value="0"][@label="tous"]'); + $this->assertXPath('//div[contains(@class,"boite rech_simple")]//form//select[@name="custom_multifacets_annexe"]//option[1][@value=""][@label="tous"]'); } diff --git a/tests_db/UpgradeDBTest.php b/tests_db/UpgradeDBTest.php index 6996558d84648b1e98455028f6b199e35d8588a5..7ab7f32068e1c155f619b097de84bbe33670b670 100644 --- a/tests_db/UpgradeDBTest.php +++ b/tests_db/UpgradeDBTest.php @@ -75,8 +75,8 @@ abstract class UpgradeDBTestCase extends TestCase protected function _getPatchLevel() { preg_match('/UpgradeDB_(\d+)_Test/', - get_class($this), - $matches); + get_class($this), + $matches); return $matches[1]; } @@ -101,7 +101,7 @@ abstract class UpgradeDBTestCase extends TestCase } catch (Exception $e) { $table_exists = false; $message = $message ?: sprintf('Failed asserting that "%s" table EXISTS', - $table); + $table); } $this->assertTrue($table_exists, $message); @@ -113,13 +113,13 @@ abstract class UpgradeDBTestCase extends TestCase try { $this->query(sprintf('select `%s` from `%s` limit 1', - $column, - $table)); + $column, + $table)); } catch (Exception $e) { $column_exists = false; $message = $message ?: sprintf('Failed asserting that "%s" table CONTAINS a "%s" column.', - $table, - $column); + $table, + $column); } $this->assertTrue($column_exists, $message); @@ -131,8 +131,8 @@ abstract class UpgradeDBTestCase extends TestCase try { $this->query(sprintf('select `%s` from `%s` limit 1', - $column, - $table)); + $column, + $table)); } catch (Exception $e) { $column_exists = false; } @@ -140,16 +140,16 @@ abstract class UpgradeDBTestCase extends TestCase if ($column_exists) $message = $message ?: sprintf('Failed asserting that "%s" table does NOT contains column "%s".', - $table, - $column); + $table, + $column); $this->assertFalse($column_exists, $message); } protected function assertIndex(string $table, - string $name, - string $type = 'BTREE', - string $message = ''): void + string $name, + string $type = 'BTREE', + string $message = ''): void { $index_exists = false; $keys = []; @@ -170,9 +170,9 @@ abstract class UpgradeDBTestCase extends TestCase if (!$index_exists) $message = $message ?: sprintf('Failed asserting that "%s" table CONTAINS an index "%s" of type "%s".', - $table, - $name, - $type) + $table, + $name, + $type) . "\n" . json_encode($keys, JSON_PRETTY_PRINT); $this->assertTrue($index_exists, $message); @@ -200,8 +200,8 @@ abstract class UpgradeDBTestCase extends TestCase $message = $primary_exists ? '' : (sprintf('Failed asserting that "%s" table CONTAINS a PRIMARY on column "%s".', - $table, - $name) + $table, + $name) . "\n" . json_encode($keys, JSON_PRETTY_PRINT)); $this->assertTrue($primary_exists, $message); @@ -224,16 +224,16 @@ abstract class UpgradeDBTestCase extends TestCase if ($index_exists) $message = $message ?: sprintf('Failed asserting that "%s" table NOT CONTAINS index "%s" .', - $table, - $name); + $table, + $name); $this->assertFalse($index_exists, $message); } protected function assertFieldType(string $table, - string $name, - string $type, - string $message = ''): void + string $name, + string $type, + string $message = ''): void { $this->assertField($table, $name, $type, 'Type', $message); } @@ -244,32 +244,32 @@ abstract class UpgradeDBTestCase extends TestCase } protected function assertFieldNotNullable(string $table, - string $column, - string $message = ''): void + string $column, + string $message = ''): void { $this->assertField($table, $column, 'NO', 'Null', $message); } protected function assertFieldDefault(string $table, - string $column, - string $default, - string $message = ''): void + string $column, + string $default, + string $message = ''): void { $this->assertField($table, $column, $default, 'Default', $message); } protected function assertField(string $table, - string $column, - string $expected, - string $field, - string $message = ''): void + string $column, + string $expected, + string $field, + string $message = ''): void { $field_exists = false; $fields = []; try { foreach ($this->query(sprintf('show fields from `%s` where field=\'%s\'', - $table, $column))->fetchAll() as $row) { + $table, $column))->fetchAll() as $row) { $fields[] = $row; if ($expected == $row[$field]) { $field_exists = true; @@ -284,11 +284,11 @@ abstract class UpgradeDBTestCase extends TestCase if (!$field_exists) $message = $message ?: sprintf("Failed asserting that TABLE %s contains COLUMN %s with field %s = %s\n\n%s", - $table, - $column, - $field, - $expected, - json_encode($fields, JSON_PRETTY_PRINT)); + $table, + $column, + $field, + $expected, + json_encode($fields, JSON_PRETTY_PRINT)); $this->assertTrue($field_exists, $message); } @@ -301,7 +301,7 @@ abstract class UpgradeDBTestCase extends TestCase protected function dropFieldFrom($table, $field) { return $this->silentQuery(sprintf('alter table %s drop column %s', - $table, $field)); + $table, $field)); } protected function dropFieldsFrom($table, $fields) @@ -377,7 +377,7 @@ class UpgradeDB_268_Test extends UpgradeDBTestCase $this->query('update bib_admin_users set pseudo="' . $hundred_chars_pseudo . '" where id_user=' . static::$user_backup['id_user']); $this->assertEquals($hundred_chars_pseudo, - $this->query('select pseudo from bib_admin_users where id_user=' . static::$user_backup['id_user'])->fetch()['pseudo']); + $this->query('select pseudo from bib_admin_users where id_user=' . static::$user_backup['id_user'])->fetch()['pseudo']); } } @@ -393,7 +393,7 @@ class UpgradeDB_274_Test extends UpgradeDBTestCase { $data = $this->query('select valeur from bib_admin_var where clef="CNIL_CONSENT_ENABLE"')->fetch(); $this->assertEquals('1', - $data['valeur']); + $data['valeur']); } } @@ -527,7 +527,7 @@ class UpgradeDB_283_Test extends UpgradeDBTestCase public function shouldHaveAvenioImportFormat() { $this->assertContains('8:CSV Avenio', - $this->query("select liste from variables where clef='import_format'")->fetch()['liste']); + $this->query("select liste from variables where clef='import_format'")->fetch()['liste']); } } @@ -585,8 +585,8 @@ class UpgradeDB_284_Test extends UpgradeDBTestCase public function albumUsageConstraintsShouldHaveColumnItemIdThatReferencesFirstAlbumItemId() { $this->assertEquals(['serialized_datas' => 'for tests'], - $this->query('select serialized_datas from album_usage_constraints where item_id=' . static::$item_id)->fetch(), - 'item id: ' . static::$item_id); + $this->query('select serialized_datas from album_usage_constraints where item_id=' . static::$item_id)->fetch(), + 'item id: ' . static::$item_id); } /** @test */ @@ -787,7 +787,7 @@ class UpgradeDB_293_Test extends UpgradeDBTestCase public function dedupModeNoneShouldExists() { $this->assertContains("\r\n2:aucun", - $this->query("select liste from variables where clef='mode_doublon'")->fetch()['liste']); + $this->query("select liste from variables where clef='mode_doublon'")->fetch()['liste']); } } @@ -825,8 +825,8 @@ class UpgradeDB_295_Test extends UpgradeDBTestCase $facets = 'HSOUS0001 HSOUS0002 HLANG0001 A191462 A155897 A191463 A133747 A23754 A191464 A81181 A191465 A47146 A191466 A133767 A134066 A191467 A191468 A191469 A191470 A191471 A191472 A191473 A191474 A191475 A191476 A191477 A191478 A103360 A103361 A191479 A191480 A65390 Lfre Leng G60 G1 G5 T4 B1 S1 YROU HCCCC0002 HCCCC0002011500320011'; $this->assertEquals($facets, - $this->query('select clean_spaces("' . $facets . '") as facets') - ->fetch()['facets']); + $this->query('select clean_spaces("' . $facets . '") as facets') + ->fetch()['facets']); } } @@ -909,7 +909,7 @@ class UpgradeDB_299_Test extends UpgradeDBTestCase public function urlWebSvcShouldPortOnAfiDotSa() { $this->assertEquals('https://websvc.afi-sa.net/afi_opac_services/main.php', - Class_CosmoVar::get('url_services')); + Class_CosmoVar::get('url_services')); } } @@ -964,8 +964,8 @@ class UpgradeDB_302_Test extends UpgradeDBTestCase public function barcodeFieldsShouldContains949Dollar6() { $this->assertContains("\r\n" . '949:949$6', - $this->query('select liste from variables where clef=\'champ_code_barres\'') - ->fetch()['liste']); + $this->query('select liste from variables where clef=\'champ_code_barres\'') + ->fetch()['liste']); } } @@ -1370,7 +1370,7 @@ class UpgradeDB_317_Test extends UpgradeDBTestCase public function datas() { return array_map(fn($item) => [$item], - $this->_columns); + $this->_columns); } /** @@ -1760,7 +1760,7 @@ class UpgradeDB_332_Test extends UpgradeDBTestCase public function datas() { return array_map(fn($item) => [$item], - $this->_columns); + $this->_columns); } /** @@ -1828,9 +1828,9 @@ class UpgradeDB_335_Test extends UpgradeDBTestCase } foreach ([ 'MOISSONAGE_JAMENDO', - Class_Batch_PanierUser::TYPE] as $type) - if (!$this->fetchBatchByType($type)) - $this->query('insert into batchs (type, last_run) values("' . $type . '", "")'); + Class_Batch_PanierUser::TYPE] as $type) + if (!$this->fetchBatchByType($type)) + $this->query('insert into batchs (type, last_run) values("' . $type . '", "")'); } /** @test */ @@ -2110,7 +2110,7 @@ class UpgradeDB_341_Test extends UpgradeDBTestCase ->fetch(); $this->assertEquals('http://pad.philharmoniedeparis.fr/EXPLOITATION/oaiserver.ashx', - $datas['valeur']); + $datas['valeur']); } /** @test */ @@ -2118,7 +2118,7 @@ class UpgradeDB_341_Test extends UpgradeDBTestCase { $datas = $this->query('select url_origine from album where id=' . static::$cite_mus_album_id)->fetch(); $this->assertEquals('http://pad.philharmoniedeparis.fr/EXPLOITATION/oaiserver.ashx', - $datas['url_origine']); + $datas['url_origine']); } /** @test */ @@ -2126,7 +2126,7 @@ class UpgradeDB_341_Test extends UpgradeDBTestCase { $datas = $this->query('select url_origine from album where id=' . static::$big_bug_album_id)->fetch(); $this->assertEquals('http://media.citedesbugs.fr', - $datas['url_origine']); + $datas['url_origine']); } /** @test */ @@ -2488,7 +2488,7 @@ class UpgradeDB_357_Test extends UpgradeDBTestCase 'ordre' => 2, 'verrou' => 'checked', 'hidden' => 0], - $other_index_fields); + $other_index_fields); } } @@ -2843,7 +2843,7 @@ class UpgradeDB_373_Test extends UpgradeDBTestCase { $this->assertEquals(['0' => 'Code-barres uniquement', '1' => 'Bibliothèque + codes-barres'], - Class_CosmoVar::getList('unicite_code_barres')); + Class_CosmoVar::getList('unicite_code_barres')); } } @@ -2879,14 +2879,14 @@ class UpgradeDB_375_Test extends UpgradeDBTestCase public function variableNewRegistrerationShouldContainsBRInsteadOfNL() { $this->assertEquals('Hello<br><br>MyFriend', - $this->query('select valeur from bib_admin_var where clef="NOTIFICATION_TEMPLATE_NEW_REGISTRATION"')->fetch()['valeur']); + $this->query('select valeur from bib_admin_var where clef="NOTIFICATION_TEMPLATE_NEW_REGISTRATION"')->fetch()['valeur']); } /** @test */ public function variableNewUserShouldContainsBRInsteadOfNL() { $this->assertEquals('Hello<br><br>You have a new friend', - $this->query('select valeur from bib_admin_var where clef="NOTIFICATION_TEMPLATE_NEW_USER"')->fetch()['valeur']); + $this->query('select valeur from bib_admin_var where clef="NOTIFICATION_TEMPLATE_NEW_USER"')->fetch()['valeur']); } } @@ -3216,7 +3216,7 @@ class UpgradeDB_383_Test extends UpgradeDBTestCase ->fetch()['filters']; $this->assertEquals('{"search_role_level":"2", "search_id_site":"7"}', - $filters); + $filters); } } @@ -3385,8 +3385,8 @@ class UpgradeDB_386_Test extends UpgradeDBTestCase public function newslettersMailSubjectShouldDefaultToTitle() { $this->assertEquals('db testing', - current($this->query("select mail_subject from newsletters where titre='db testing'") - ->fetch())); + current($this->query("select mail_subject from newsletters where titre='db testing'") + ->fetch())); } } @@ -3608,7 +3608,7 @@ class UpgradeDB_395_Test extends UpgradeDBTestCase public function columns() { return array_map(fn($column) => [$column], - $this->_columns); + $this->_columns); } /** @@ -3809,7 +3809,7 @@ class UpgradeDB_401_Test extends UpgradeDBTestCase public function idsThenAlphaKeyShouldExists() { $this->assertContains("\r\n3:identifiants puis clef alpha", - $this->query("select liste from variables where clef='mode_doublon'")->fetch()['liste']); + $this->query("select liste from variables where clef='mode_doublon'")->fetch()['liste']); } } @@ -3945,7 +3945,7 @@ class UpgradeDB_407_Test extends UpgradeDBTestCase public function adultsShouldBeSetToOneByDefault() { $this->assertEquals(0, - $this->query('select count(*) from session_activity_inscriptions where (adults=0 and children=0) ')->fetch()['count(*)']); + $this->query('select count(*) from session_activity_inscriptions where (adults=0 and children=0) ')->fetch()['count(*)']); } } @@ -3960,7 +3960,7 @@ class UpgradeDB_408_Test extends UpgradeDBTestCase public function tableVariablesShouldHaveFlushBeforeFullVariableInGroupe4() { $this->assertEquals(4, - $this->query("select * from variables where clef='flush_before_full'")->fetch()['groupe']); + $this->query("select * from variables where clef='flush_before_full'")->fetch()['groupe']); } } @@ -4109,9 +4109,9 @@ class UpgradeDB_414_Test extends UpgradeDBTestCase public function statusReportPushUrlShouldBeHttps() { $this->assertEquals('https://pola.afi-sa.net/smile.php', - current($this - ->query('select valeur from bib_admin_var where clef="STATUS_REPORT_PUSH_URL"') - ->fetch())); + current($this + ->query('select valeur from bib_admin_var where clef="STATUS_REPORT_PUSH_URL"') + ->fetch())); } } @@ -4282,7 +4282,7 @@ class UpgradeDB_423_Test extends UpgradeDBTestCase { Class_UserGroupCategorie::deleteBy(['libelle' => 'Accès aux lettres d\'informations']); Class_UserGroup::deleteBy(['libelle' => array_map(fn($fixture) => $fixture[0], - $this->datas())]); + $this->datas())]); } /** @test */ @@ -4307,7 +4307,7 @@ class UpgradeDB_423_Test extends UpgradeDBTestCase 'role_level' => $role, 'id_cat' => $parent_group->getId(), 'filters' => json_encode( - ['search_role_level' => $role]), + ['search_role_level' => $role]), ]); $this->assertTrue($group->hasRight(Class_UserGroup::RIGHT_GERER_LETTRESINFO)); } @@ -4545,8 +4545,8 @@ class UpgradeDB_428_Test extends UpgradeDBTestCase public function prepare() { $this->query('replace into bib_admin_var(clef, valeur) values(?, ?)', - ['PELLICULE_SETTINGS', - '{"Provider":["electre_rest_2"],"Login":["api_cat_login"],"Password":["?login@cat_api!"]}']); + ['PELLICULE_SETTINGS', + '{"Provider":["electre_rest_2"],"Login":["api_cat_login"],"Password":["?login@cat_api!"]}']); } /** @test */ @@ -4556,7 +4556,7 @@ class UpgradeDB_428_Test extends UpgradeDBTestCase ->fetch(); $this->assertEquals('{"Provider":["electre_ng"],"Login":["api_cat_login"],"Password":["?login@cat_api!"]}', - $row['valeur'] ?? ''); + $row['valeur'] ?? ''); } } @@ -4648,7 +4648,7 @@ class UpgradeDB_430_Test extends UpgradeDBTestCase 'IdField' => '', 'FilterField' => '', 'FilterValue' => '']], - JSON_PRETTY_PRINT); + JSON_PRETTY_PRINT); Class_CodifThesaurus::newInstance(['id_thesaurus' => 'TST1', 'libelle' => 'tstlib1', @@ -4688,10 +4688,10 @@ class UpgradeDB_430_Test extends UpgradeDBTestCase public function codifThesaurusIdTST3andTST30004CShouldHaveCodeUNIMARC() { $this->assertEquals(['TST3', 'TST30004'], - array_map(fn($thesaurus) => $thesaurus->getIdThesaurus(), - Class_CodifThesaurus::findAllBy(['code' => Class_CodifThesaurusFixed::CODE_UNIMARC_FACET, - 'id_thesaurus' => static::$_id_thesaurus, - 'order' => 'id_thesaurus']))); + array_map(fn($thesaurus) => $thesaurus->getIdThesaurus(), + Class_CodifThesaurus::findAllBy(['code' => Class_CodifThesaurusFixed::CODE_UNIMARC_FACET, + 'id_thesaurus' => static::$_id_thesaurus, + 'order' => 'id_thesaurus']))); } protected function _deleteThesaurusForTests() @@ -4719,7 +4719,7 @@ class UpgradeDB_431_Test extends UpgradeDBTestCase $this->_last_user_id = $this->lastInsertId(); $this->silentQuery('INSERT INTO user_groups (libelle, group_type, filters) VALUES ("Super admins dynamic", 1, ?)', - [json_encode(['search_role_level' => 7])]); + [json_encode(['search_role_level' => 7])]); $this->_last_user_group_id = $this->lastInsertId(); } @@ -4738,12 +4738,12 @@ class UpgradeDB_431_Test extends UpgradeDBTestCase { $rows = $this->query('select user_id from user_group_memberships where user_group_id =?', - [$this->_last_user_group_id]) + [$this->_last_user_group_id]) ->fetchAll(); $this->assertEquals([['user_id' => 1], ['user_id' => $this->_last_user_id]], - $rows); + $rows); } } @@ -4760,7 +4760,7 @@ class UpgradeDB_432_Test extends UpgradeDBTestCase public function columns() { return array_map(fn($column) => [$column], - $this->_columns); + $this->_columns); } /** @@ -4975,7 +4975,7 @@ class UpgradeDB_437_Test extends UpgradeDBTestCase 'NOTUPGRADABLE------1', 'NOTEXISTINGARTICLE------8', ], - explode(';', $row['notices'])); + explode(';', $row['notices'])); } protected function _createRecordWithClefAlpha(string $clef_alpha): int @@ -5237,14 +5237,14 @@ class UpgradeDB_446_Test extends UpgradeDBTestCase public function tableVariablesShouldHaveMaxItemsVariableInGroupe4() { $this->assertEquals(4, - $this->query("select * from variables where clef='max_items'")->fetch()['groupe']); + $this->query("select * from variables where clef='max_items'")->fetch()['groupe']); } /** @test */ public function tableVariablesShouldHaveMaxItemsVariableSetTo1000() { $this->assertEquals(1000, - $this->query("select * from variables where clef='max_items'")->fetch()['valeur']); + $this->query("select * from variables where clef='max_items'")->fetch()['valeur']); } } @@ -5543,14 +5543,14 @@ class UpgradeDB_454_Test extends UpgradeDBTestCase $this->assertIndex('notices', 'mots_notice', 'FULLTEXT'); $this->assertEquals('HPUBL0002 HSUPP0001 A5333', - Class_Notice::find($this->_first_inserted_record)->getFacettes()); + Class_Notice::find($this->_first_inserted_record)->getFacettes()); $this->assertEquals('Lfre G1 T1 B1 S27', - Class_Notice::find($this->_second_inserted_record)->getFacettes()); + Class_Notice::find($this->_second_inserted_record)->getFacettes()); $this->assertEquals('F_HPUBL0002 F_HSUPP0001 F_A5333', - Class_Notice::find($this->_first_inserted_record)->getFacets()); + Class_Notice::find($this->_first_inserted_record)->getFacets()); $this->assertEquals('F_Lfre F_G1 F_T1 F_B1 F_S27', - Class_Notice::find($this->_second_inserted_record)->getFacets()); + Class_Notice::find($this->_second_inserted_record)->getFacets()); $this->assertNotIndex('notices', 'mots_notice_2'); $this->assertNotIndex('notices', 'facettes'); @@ -5766,13 +5766,11 @@ class UpgradeDB_460_Test extends UpgradeDBTestCase } } + + + class UpgradeDB_461_Test extends UpgradeDBTestCase { - public function tearDown(): void - { - $this->query('delete from payfip where reference="1234767889" and id_op="toto";'); - parent::tearDown(); - } public function prepare() { @@ -5780,6 +5778,14 @@ class UpgradeDB_461_Test extends UpgradeDBTestCase $this->query("insert into payfip(id_op, bib_id,user_id, reference, amount,paid_on, result) values ('toto with bib',1, 336,'1234767889', 1634, '2023-06-01 12:00:28','C')"); } + + public function tearDown(): void + { + $this->query('delete from payfip where reference="1234767889" and id_op="toto";'); + parent::tearDown(); + } + + /** @test */ public function sigbStatusShouldBeSetForNonBibIdPayfip() { @@ -5841,8 +5847,8 @@ abstract class AbstractCafeyn_TestCase extends UpgradeDBTestCase if (!$this ->query('select count(*) from bib_admin_var where clef ="Cafeyn_ID"') ->fetch()['count(*)']) - $this - ->query('insert into bib_admin_var (valeur, clef) values ("", "Cafeyn_ID")'); + $this + ->query('insert into bib_admin_var (valeur, clef) values ("", "Cafeyn_ID")'); $this->_cafeyn_id = $this ->query('select valeur from bib_admin_var where clef ="Cafeyn_ID"') @@ -5867,9 +5873,9 @@ class UpgradeDB_462_Test_BatchEnabledTest extends AbstractCafeyn_TestCase public function cafeynAlbumsShouldBeDeleted() { $this->assertEquals(0, - $this - ->query('select count(*) from album where type_doc_id ="Cafeyn"') - ->fetch()['count(*)']); + $this + ->query('select count(*) from album where type_doc_id ="Cafeyn"') + ->fetch()['count(*)']); } /** @test @@ -5877,9 +5883,9 @@ class UpgradeDB_462_Test_BatchEnabledTest extends AbstractCafeyn_TestCase public function arteVodAlbumsShouldNotBeDeleted() { $this->assertEquals($this->_album_artevod_count + 1, - $this - ->query('select count(*) from album where type_doc_id ="ArteVod"') - ->fetch()['count(*)']); + $this + ->query('select count(*) from album where type_doc_id ="ArteVod"') + ->fetch()['count(*)']); } } @@ -5898,9 +5904,9 @@ class UpgradeDB_462_Test_BatchDisabledTest extends AbstractCafeyn_TestCase public function cafeynAlbumsShouldNotBeDeleted() { $this->assertEquals(2, - $this - ->query('select count(*) from album where type_doc_id ="Cafeyn" ') - ->fetch()['count(*)']); + $this + ->query('select count(*) from album where type_doc_id ="Cafeyn" ') + ->fetch()['count(*)']); } /** @test @@ -5908,9 +5914,9 @@ class UpgradeDB_462_Test_BatchDisabledTest extends AbstractCafeyn_TestCase public function arteVodAlbumsShouldNotBeDeleted() { $this->assertEquals($this->_album_artevod_count + 1, - $this - ->query('select count(*) from album where type_doc_id ="ArteVod" ') - ->fetch()['count(*)']); + $this + ->query('select count(*) from album where type_doc_id ="ArteVod" ') + ->fetch()['count(*)']); } } @@ -6055,8 +6061,8 @@ class UpgradeDB_466_Test extends UpgradeDBTestCase if (!$this ->query('select count(*) from bib_admin_var where clef ="Cafeyn_SSO_URL"') ->fetch()['count(*)']) - $this - ->query('insert into bib_admin_var (valeur, clef) values ("myoldurl", "Cafeyn_SSO_URL")'); + $this + ->query('insert into bib_admin_var (valeur, clef) values ("myoldurl", "Cafeyn_SSO_URL")'); } /** @test */ @@ -6229,14 +6235,14 @@ class UpgradeDB_470_Test extends UpgradeDBTestCase $this->id_customfield_values[] = $this->lastInsertId(); $cfg['modules'][3] = [ - 'division' => '2', - 'id_module' => 3, - 'type_module' => 'LIBRARY', - 'preferences' => ['titre' => 'Mes Bibliotheques', - 'libraries' => '', - 'nb_aff' => 2, - 'allow_link_on_title' => true, - 'default_filters' => ['custom_field_' . $this->_cf_restauration_id => ['restauration unique3']]]]; + 'division' => '2', + 'id_module' => 3, + 'type_module' => 'LIBRARY', + 'preferences' => ['titre' => 'Mes Bibliotheques', + 'libraries' => '', + 'nb_aff' => 2, + 'allow_link_on_title' => true, + 'default_filters' => ['custom_field_' . $this->_cf_restauration_id => ['restauration unique3']]]]; $data = $this->query('select id_profil, CFG_ACCUEIL from bib_admin_profil order by id_profil desc')->fetchAll(); $this->_id_profil = $data[0]['id_profil']; @@ -6462,14 +6468,14 @@ class UpgradeDB_472_Test extends UpgradeDBTestCase public function superAdminGroupShouldHaveAdminProfileRight() { $this->assertTrue(in_array(Class_UserGroup::RIGHT_ADMIN_PROFILE, - $this->_super_group->getRights())); + $this->_super_group->getRights())); } /** @test */ public function adminPortalGroupShouldHaveAdminProfileRight() { $this->assertTrue(in_array(Class_UserGroup::RIGHT_ADMIN_PROFILE, - $this->_admin_group->getRights())); + $this->_admin_group->getRights())); } } @@ -6487,6 +6493,7 @@ class UpgradeDB_473_Test extends UpgradeDBTestCase } } + class UpgradeDB_474_Test extends UpgradeDBTestCase { public function prepare() @@ -6517,6 +6524,7 @@ class UpgradeDB_474_Test extends UpgradeDBTestCase } } + class UpgradeDB_475_Test extends UpgradeDBTestCase { protected @@ -6583,3 +6591,425 @@ class UpgradeDB_475_Test extends UpgradeDBTestCase $this->assertNotColumn('activity', 'visible'); } } + + +class UpgradeDB_476_Test extends UpgradeDBTestCase +{ + + protected string $_bmi_id, + $_bda_id, + $_bdp_id, + $_three_id, + $_six_id, + $_five_id, + $_cdif1_id, + $_cdif2_id, + $_cdif3_id, + $_cdif4_id, + $_rec_one, + $_rec_two, + $_rec_three, + $_rec_four, + $_rec_five, + $_rec_six, + $_rec_seven, + $_rec_eight, + $_rec_nine, + $_cat_one, + $_cat_two, + $_profile_one; + + + public function prepare() { + $this + ->query('insert album (titre, annexes, type_doc_id) values ("Test Album 467", "CODIF1 CODIF2", 1)'); + + $this + ->query('delete from variables where clef=\'CODIFS_MIGRATED\''); + + $this + ->query('insert codif_type_doc (type_doc_id, annexes) values ("Test Typedoc 467", "CODIF1;CODIF2")'); + + $this->_bmi_id = $this->_insertAnnexe('BMI'); + $this->_bda_id = $this->_insertAnnexe('BDA'); + $this->_bdp_id = $this->_insertAnnexe('BDP'); + $this->_three_id = $this->_insertAnnexe('3'); + $this->_six_id = $this->_insertAnnexe('6'); + $this->_five_id = $this->_insertAnnexe((string) $this->_six_id); + $this->_cdif1_id = $this->_insertAnnexe('CODIF1'); + $this->_cdif2_id = $this->_insertAnnexe('CODIF2'); + $this->_cdif3_id = $this->_insertAnnexe('PLOP'); + $this->_cdif4_id = $this->_insertAnnexe('PLIP'); + $this->query('UPDATE codif_annexe SET code = ' . $this->_cdif3_id -1 + . ' WHERE id_annexe = ' . $this->_cdif3_id); + $this->query('UPDATE codif_annexe SET code = ' . $this->_cdif4_id -1 + . ' WHERE id_annexe = ' . $this->_cdif4_id); + + $this->query('UPDATE `codif_annexe` set `code` = "' . $this->_five_id . '" WHERE `id_annexe` = ' . $this->_six_id); + + $this->_rec_one = $this->_insertRecordFor(['T1', 'YBMI']); + $this->_rec_two = $this->_insertRecordFor(['T1', 'YBMI', 'B1', 'HNRNR0002']); + $this->_rec_three = $this->_insertRecordFor(['T1', 'YBDA', 'YBMI', 'B1', 'HNRNR0002', 'LYBMX']); + $this->_rec_four = $this->_insertRecordFor(['YBDA', 'T1', 'B1', 'HNRNR0002']); + $this->_rec_five = $this->_insertRecordFor(['T1', 'Y' . $this->_bdp_id, 'YBDP']); + $this->_rec_six = $this->_insertRecordFor(['T1', 'Y' . $this->_five_id, 'Y' . $this->_six_id]); + $this->_rec_seven = $this->_insertRecordFor(['Y' . $this->_cdif3_id -1]); + $this->_rec_eight = $this->_insertRecordFor(['Y' . $this->_cdif4_id -1]); + $this->_rec_nine = $this->_insertRecordFor(['Y' . $this->_cdif4_id -1, + 'Y' . $this->_cdif3_id -1]); + + $this->_cat_one = $this->_insertDomain('CODIF1;CODIF2'); + $this->_cat_two = $this->_insertDomain($this->_five_id . ';' . $this->_six_id); + + $this->_insertItem($this->_rec_one, 'BMI', '[341]'); + $this->_insertItem($this->_rec_two, 'BMI', '[345]'); + $this->_insertItem($this->_rec_three, 'BDA', '[342]'); + $this->_insertItem($this->_rec_three, 'BMI', '[343]'); + $this->_insertItem($this->_rec_four, 'BDA', '[346]'); + $this->_insertItem($this->_rec_five, '3', '[344]'); + $this->_insertItem($this->_rec_five, 'BDP', '[347]'); + $this->_insertItem($this->_rec_six, $this->_six_id, '[348]'); + $this->_insertItem($this->_rec_six, $this->_five_id, '[349]'); + $this->_insertItem($this->_rec_seven, $this->_cdif3_id -1, '[350]'); + $this->_insertItem($this->_rec_eight, $this->_cdif4_id -1, '[351]'); + $this->_insertItem($this->_rec_nine, $this->_cdif4_id -1, '[352]'); + $this->_insertItem($this->_rec_nine, $this->_cdif3_id -1, '[352]'); + + $this->_profile_one = $this->_insertProfile('CODIF1;CODIF2'); + + $this->silentQuery('ALTER TABLE `codif_annexe` DROP INDEX IF EXISTS `id_bib`;'); + } + + + protected function _insertProfile(string $annexes): int + { + $this->query('insert into bib_admin_profil (libelle, sel_annexe)' + . 'values ("Test profil 467", "' . $annexes . '")'); + + return $this->lastInsertId(); + } + + + protected function _insertDomain(string $annexes): int + { + $this->query('insert catalogue (libelle, annexe) values (' + . '"Test Catalogue 467", "' . $annexes . '")'); + + return $this->lastInsertId(); + } + + + protected function _insertRecordFor(array $facets): int + { + $this->query('insert into notices (titres, type_doc, facettes, facets) values (' . '"[UN TITRE POUR TESTS]", 1, "' . implode(' ', $facets) . '", " F_' . implode(' F_', $facets) . '")'); + + return $this->lastInsertId(); + } + + + protected function _insertItem(int $id_notice, + string $annexe, + string $id_origine): self + { + $this->query('insert into exemplaires ' + . '(id_notice, annexe, id_int_bib, id_bib, id_origine) values (' + . $id_notice . ', "' . $annexe . '", 1, 1, "' + . $id_origine . '");'); + + return $this; + } + + + protected function _insertAnnexe(string $code): int + { + $this->query('insert codif_annexe (code, id_origine) values ("' + . $code . '", "' . $code . '")'); + + return $this->lastInsertId(); + } + + + public function tearDown() : void + { + $this->query("DELETE FROM catalogue where libelle = 'Test Catalogue 467';"); + $this->query("DELETE FROM album where titre = 'Test Album 467';"); + $this->query("DELETE FROM codif_type_doc where type_doc_id = 'Test Typedoc 467';"); + $this->query("DELETE FROM bib_admin_profil where libelle = 'Test profil 467';"); + + $this->query("DELETE FROM codif_annexe where id_annexe IN (" + .implode(',', [$this->_bda_id, $this->_bdp_id, $this->_bmi_id, + $this->_three_id, $this->_six_id, $this->_five_id, + $this->_cdif2_id, $this->_cdif1_id, $this->_cdif3_id, + $this->_cdif4_id]) . ");"); + + $this->query("DELETE FROM notices where id_notice IN (" + .implode(',', [$this->_rec_one, $this->_rec_two, $this->_rec_three, + $this->_rec_four, $this->_rec_five, $this->_rec_six, + $this->_rec_seven, $this->_rec_eight, $this->_rec_nine]) + . ")"); + + $this->query("DELETE FROM exemplaires where id_notice IN (" + .implode(',', [$this->_rec_one, $this->_rec_two, $this->_rec_three, + $this->_rec_four, $this->_rec_five, $this->_rec_six, + $this->_rec_seven, $this->_rec_eight, $this->_rec_nine]) + . ")"); + + parent::tearDown(); + } + + + /** @test */ + public function profileOneShouldGetAnnexesIds() + { + $data = $this->query('SELECT `sel_annexe` FROM `bib_admin_profil` WHERE `id_profil` =' + . $this->_profile_one . ';')->fetch(); + $this->assertEquals($this->_cdif1_id . ';' . $this->_cdif2_id, $data['sel_annexe']); + } + + /** @test **/ + public function albumShouldGetAnnexesIds() { + $data = $this->query('SELECT `annexes` FROM `album` WHERE `titre` =' + . '\'Test Album 467\';')->fetch(); + $this->assertEquals($this->_cdif1_id . ' ' . $this->_cdif2_id, $data['annexes']); + } + + + /** @test **/ + public function cosmoVarCodifsMigratedValueShouldBe1() { + $data = $this->query('SELECT `valeur` FROM `variables` WHERE `clef` =' + . '\'CODIFS_MIGRATED\';')->fetch(); + $this->assertEquals(1, $data['valeur']); + } + + + /** @test **/ + public function domain1ShouldGetAnnexesIds() { + $data = $this->query('SELECT `annexe` FROM `catalogue` WHERE `id_catalogue` =' + . $this->_cat_one)->fetch(); + $this->assertEquals($this->_cdif1_id .';' . $this->_cdif2_id, $data['annexe']); + } + + + /** @test **/ + public function domain2ShouldGetAnnexesIds() { + $data = $this->query('SELECT `annexe` FROM `catalogue` WHERE `id_catalogue` =' + . $this->_cat_two)->fetch(); + $this->assertEquals($this->_six_id .';' . $this->_five_id, $data['annexe']); + } + + + /** @test **/ + public function typeDocShouldGetAnnexesIds() { + $data = $this->query('SELECT `annexes` FROM `codif_type_doc` WHERE `type_doc_id` =' + . '\'Test Typedoc 467\';')->fetch(); + $this->assertEquals($this->_cdif1_id .';' . $this->_cdif2_id, $data['annexes']); + } + + /** @test **/ + public function indexIdBibInTableCodifAnnexeShouldBeCreated() + { + $this->assertIndex('codif_annexe', 'id_bib'); + } + + + /** @test **/ + public function notice1FacettesYShouldBeY1() + { + $data = $this->query('SELECT `facettes`, `facets` FROM `notices` WHERE `id_notice` = ' + . $this->_rec_one)->fetch(); + $this->assertEquals('T1 Y' . $this->_bmi_id, $data['facettes']); + $this->assertEquals('F_T1 F_Y' . $this->_bmi_id, $data['facets']); + } + + + /** @test */ + public function notice2FacettesYShouldBeY1() + { + $data = $this->query('SELECT `facettes`, `facets` FROM `notices` WHERE `id_notice` = ' + . $this->_rec_two)->fetch(); + $this->assertEquals('T1 B1 HNRNR0002 Y' . $this->_bmi_id, $data['facettes']); + $this->assertEquals('F_T1 F_B1 F_HNRNR0002 F_Y' . $this->_bmi_id, $data['facets']); + } + + + /** @test */ + public function notice3FacettesYShouldBeY1And2() + { + $data = $this->query('SELECT `facettes`, `facets` FROM `notices` WHERE `id_notice` = ' + . $this->_rec_three)->fetch(); + $this->assertEquals('T1 B1 HNRNR0002 LYBMX Y' . $this->_bda_id + . ' Y' . $this->_bmi_id, $data['facettes']); + $this->assertEquals('F_T1 F_B1 F_HNRNR0002 F_LYBMX F_Y' + . $this->_bda_id . ' F_Y' . $this->_bmi_id, + $data['facets']); + } + + + /** @test */ + public function notice4FacettesYShouldBeY2() + { + $data = $this->query('SELECT `facettes`, `facets` FROM `notices` WHERE `id_notice` =' + . $this->_rec_four)->fetch(); + $this->assertEquals('T1 B1 HNRNR0002 Y' . $this->_bda_id, $data['facettes']); + $this->assertEquals('F_T1 F_B1 F_HNRNR0002 F_Y' . $this->_bda_id, $data['facets']); + } + + + /** @test */ + public function notice5FacetsAndFacettesShouldBeUpdated() + { + $data = $this->query('SELECT `facettes`, `facets` FROM `notices` WHERE `id_notice` = ' + . $this->_rec_five)->fetch(); + $this->assertEquals('T1 Y' . $this->_three_id . ' Y' . $this->_bdp_id, $data['facettes']); + $this->assertEquals('F_T1 F_Y' . $this->_three_id . ' F_Y' . $this->_bdp_id, $data['facets']); + } + + + /** @test */ + public function notice6FacetsAndFacettesShouldBeUpdated() + { + $data = $this->query('SELECT `facettes`, `facets` FROM `notices` WHERE `id_notice` = ' + . $this->_rec_six)->fetch(); + $this->assertEquals('T1 Y' . $this->_five_id . ' Y' . $this->_six_id, $data['facettes']); + $this->assertEquals('F_T1 F_Y' . $this->_five_id . ' F_Y' . $this->_six_id, $data['facets']); + } + + + /** @test */ + public function notice7FacetsAndFacettesShouldBeUpdated() + { + $data = $this->query('SELECT `facettes`, `facets` FROM `notices` WHERE `id_notice` = ' + . $this->_rec_seven)->fetch(); + $this->assertEquals(' Y' . $this->_cdif3_id, $data['facettes']); + $this->assertEquals(' F_Y' . $this->_cdif3_id, $data['facets']); + } + + + /** @test */ + public function notice8FacetsAndFacettesShouldBeUpdated() + { + $data = $this->query('SELECT `facettes`, `facets` FROM `notices` WHERE `id_notice` = ' + . $this->_rec_eight)->fetch(); + $this->assertEquals(' Y' . $this->_cdif4_id, $data['facettes']); + $this->assertEquals(' F_Y' . $this->_cdif4_id, $data['facets']); + } + + + /** @test */ + public function notice9FacetsAndFacettesShouldBeUpdated() + { + $data = $this->query('SELECT `facettes`, `facets` FROM `notices` WHERE `id_notice` = ' + . $this->_rec_nine)->fetch(); + $this->assertEquals(' Y' . $this->_cdif3_id . ' Y' . $this->_cdif4_id, $data['facettes']); + $this->assertEquals(' F_Y' . $this->_cdif3_id . ' F_Y' . $this->_cdif4_id, $data['facets']); + } + + + /** @test */ + public function item341AnnexeShouldBe1() + { + $data = $this->query('SELECT `annexe` FROM `exemplaires` WHERE `id_origine` = \'[341]\';') + ->fetch(); + $this->assertEquals($this->_bmi_id, $data['annexe']); + } + + + /** @test */ + public function item342AnnexeShouldBe2() + { + $data = $this->query('SELECT `annexe` FROM `exemplaires` WHERE `id_origine` = \'[342]\';') + ->fetch(); + $this->assertEquals($this->_bda_id, $data['annexe']); + } + + + /** @test */ + public function item343AnnexeShouldBe1() + { + $data = $this->query('SELECT `annexe` FROM `exemplaires` WHERE `id_origine` = \'[343]\';') + ->fetch(); + $this->assertEquals($this->_bmi_id, $data['annexe']); + } + + + /** @test */ + public function item344AnnexeShouldBe4() + { + $data = $this->query('SELECT `annexe` FROM `exemplaires` WHERE `id_origine` = \'[344]\';') + ->fetch(); + $this->assertEquals($this->_three_id, $data['annexe']); + } + + + /** @test */ + public function item345AnnexeShouldBe1() + { + $data = $this->query('SELECT `annexe` FROM `exemplaires` WHERE `id_origine` = \'[345]\';') + ->fetch(); + $this->assertEquals($this->_bmi_id, $data['annexe']); + } + + + /** @test */ + public function item346AnnexeShouldBe2() + { + $data = $this->query('SELECT `annexe` FROM `exemplaires` WHERE `id_origine` = \'[346]\';') + ->fetch(); + $this->assertEquals($this->_bda_id, $data['annexe']); + } + + + /** @test */ + public function item347AnnexeShouldBe3() + { + $data = $this->query('SELECT `annexe` FROM `exemplaires` WHERE `id_origine` = \'[347]\';') + ->fetch(); + $this->assertEquals($this->_bdp_id, $data['annexe']); + } + + + /** @test */ + public function item348AnnexeShouldBe6() + { + $data = $this->query('SELECT `annexe` FROM `exemplaires` WHERE `id_origine` = \'[348]\';') + ->fetch(); + $this->assertEquals($this->_five_id, $data['annexe']); + } + + + /** @test */ + public function item349AnnexeShouldBe5() + { + $data = $this->query('SELECT `annexe` FROM `exemplaires` WHERE `id_origine` = \'[349]\';') + ->fetch(); + $this->assertEquals($this->_six_id, $data['annexe']); + } + + + /** @test */ + public function item350AnnexeShouldBeCdif3Id() + { + $data = $this->query('SELECT `annexe` FROM `exemplaires` WHERE `id_origine` = \'[350]\';') + ->fetch(); + $this->assertEquals($this->_cdif3_id, $data['annexe']); + } + + + /** @test */ + public function item351AnnexeShouldBeCdif4Id() + { + $data = $this->query('SELECT `annexe` FROM `exemplaires` WHERE `id_origine` = \'[351]\';') + ->fetch(); + $this->assertEquals($this->_cdif4_id, $data['annexe']); + } + + + /** @test */ + public function item352AnnexeShouldBeCdif4Id() + { + $data = $this->query('SELECT `annexe` FROM `exemplaires` WHERE `id_origine` = \'[352]\';') + ->fetchAll(); + $this->assertEquals($this->_cdif3_id, $data[0]['annexe']); + $this->assertEquals($this->_cdif4_id, $data[1]['annexe']); + } +}