diff --git a/FEATURES/69586 b/FEATURES/69586 new file mode 100644 index 0000000000000000000000000000000000000000..587fcf5ded5b21d00f1d7e1d6f321b114231c1be --- /dev/null +++ b/FEATURES/69586 @@ -0,0 +1,10 @@ + '69586' => + ['Label' => $this->_('Inclure des articles dans les lettres d/'information'), + 'Desc' => $this->_('Bokeh permet d\'envoyer des articles dans les lettres d\'information.'), + 'Image' => '', + 'Video' => '', + 'Category' => $this->_('Rédaction'), + 'Right' => function($feature_description, $user) {return true;}, + 'Wiki' => 'http://wiki.bokeh-library-portal.org/index.php?title=Lettre_d\'information', + 'Test' => '', + 'Date' => '2018-01-10'], \ No newline at end of file diff --git a/FEATURES/80658 b/FEATURES/80658 new file mode 100644 index 0000000000000000000000000000000000000000..58d2b67bedd6bc1b612eba1707d1443759eb034c --- /dev/null +++ b/FEATURES/80658 @@ -0,0 +1,10 @@ + '80658' => + ['Label' => $this->_('Facettes dynamiques sur des sous-chaînes de champs unimarc'), + 'Desc' => $this->_('Vous pouvez créer des facettes sur des portions d\'un champ unimarc. Par exemple, sur un champ 993$w formatté comme ceci: 2018-05-04, vous pouvez créer trois facettes sur l\'année, le mois et le jour.')', + 'Image' => 'http://wiki.bokeh-library-portal.org/images/4/41/Dynamic_facet_public.png', + 'Video' => 'https://youtu.be/KYYN22dqhnM', + 'Category' => '', + 'Right' => function($feature_description, $user) {return true;}, + 'Wiki' => 'http://wiki.bokeh-library-portal.org/index.php?title=Facettes_dynamiques#A_partir_d.27une_partie_du_libell.C3.A9_d.27un_champ_unimarc', + 'Test' => '', + 'Date' => '2019-01-18'], \ No newline at end of file diff --git a/VERSIONS b/VERSIONS index c1e5fc5ff7e611869a3d06a020537ff3198cb5f1..7d06069b3e1aaaceefea322628bca7c429bd8eb7 100644 --- a/VERSIONS +++ b/VERSIONS @@ -1,3 +1,31 @@ +28/01/2019 - v7.12.56 + + - ticket #85532 : Administration : Les tickets d'assistance au statut "Réaliser à tester" sont comptabilisés dans le menu haut "Assistance" + + - ticket #84896 : SIGB Nanook : activation de la réinitialisation des mots de passe par courriel + + +21/01/2019 - v7.12.55 + + - ticket #83545 : Administration, contrôle des URLS : corrections de la prise en charge des URLs contenant des caractères spéciaux + + - ticket #84158 : Boite agenda : correction de l'affichage des articles avec des jours récurrents sélectionnés. + + - ticket #84810 : Intégration Cosmogramme : augmentation de la taille maximale des code-barres. + + - ticket #84064 : Boîte bibliothèque / ouvertures: lorsqu'une journée est fermée dans une plage exceptionnelle, affiche explicitement "fermé" pour cette journée + + +10/01/2019 - v7.12.54 + + - ticket #82189 : Connecteur LeKiosk : correction de la mise à jour lors du moissonage + + - ticket #78084 : Administration des albums : correction du chargement d'une feuille de style incorrecte lors de l'ajout de médias + + - ticket #82201 : Intégrations : optimisation de l'indexation des ressources numériques + + + 08/01/2019 - v7.12.53 - ticket #84476 : SIGB Orphee correction authentification avec WS configuré en authentification SIGB uniquement diff --git a/VERSIONS_HOTLINE/82189 b/VERSIONS_HOTLINE/82189 deleted file mode 100644 index 82a581d2734219dc32d414cdaf5354250bb2ea57..0000000000000000000000000000000000000000 --- a/VERSIONS_HOTLINE/82189 +++ /dev/null @@ -1 +0,0 @@ - - ticket #82189 : Connecteur LeKiosk : correction de la mise à jour lors du moissonage \ No newline at end of file diff --git a/VERSIONS_WIP/69586 b/VERSIONS_WIP/69586 new file mode 100644 index 0000000000000000000000000000000000000000..416f74d0a379e4ed6d19dd888f5237dfb9731943 --- /dev/null +++ b/VERSIONS_WIP/69586 @@ -0,0 +1 @@ + - ticket #69586 : Newsletter : Ajout de la possibilité d'inclure des articles dans les newsletters \ No newline at end of file diff --git a/VERSIONS_WIP/80658 b/VERSIONS_WIP/80658 new file mode 100644 index 0000000000000000000000000000000000000000..dbe62c644a6b5db7889d79412b970fa3d8d9c81b --- /dev/null +++ b/VERSIONS_WIP/80658 @@ -0,0 +1 @@ + - ticket #80658 : Facettes dynamiques : possibilité de créer des facettes dynamiques sur des dates \ No newline at end of file diff --git a/VERSIONS_WIP/80876 b/VERSIONS_WIP/80876 new file mode 100644 index 0000000000000000000000000000000000000000..f85e7b4d3140e6933723a4f3fcc5b78accaf50c0 --- /dev/null +++ b/VERSIONS_WIP/80876 @@ -0,0 +1 @@ + - ticket #80876 : Abonnés : Ajout de la possibilité d'utiliser la fonction mot de passe oublié même si l'usager ne s'est encore jamais connecté sur Bokeh \ No newline at end of file diff --git a/VERSIONS_WIP/81435 b/VERSIONS_WIP/81435 new file mode 100644 index 0000000000000000000000000000000000000000..3483d7bd18773b2d40cb30f6a85cdb3e516b6aff --- /dev/null +++ b/VERSIONS_WIP/81435 @@ -0,0 +1 @@ + - ticket #81435 : Catalogue : Affichage basique d'une notice autorité \ No newline at end of file diff --git a/VERSIONS_WIP/83983 b/VERSIONS_WIP/83983 new file mode 100644 index 0000000000000000000000000000000000000000..094937f9dbaad92618373de01bc1e851ceee5f30 --- /dev/null +++ b/VERSIONS_WIP/83983 @@ -0,0 +1 @@ + - ticket #83983 : Amélioration de l'ergonomie de la navigation dans l'administration des bibliothèques \ No newline at end of file diff --git a/VERSIONS_WIP/84280 b/VERSIONS_WIP/84280 new file mode 100644 index 0000000000000000000000000000000000000000..ebf0032507a1389012b9c77a47423c633d174ff1 --- /dev/null +++ b/VERSIONS_WIP/84280 @@ -0,0 +1 @@ + - ticket #84280 : Cosmogramme : correction de la détection des fichiers en attente composés avec une date \ No newline at end of file diff --git a/VERSIONS_WIP/85632 b/VERSIONS_WIP/85632 new file mode 100644 index 0000000000000000000000000000000000000000..ed0d8247f4f1e170c4b1739d6873dae3e59cd9d3 --- /dev/null +++ b/VERSIONS_WIP/85632 @@ -0,0 +1 @@ + - ticket #85632 : Administration : Variables : ajout de la colonne niveau d'accès et ouverture de certaines variables au rôle administrateur. \ No newline at end of file diff --git a/VERSIONS_WIP/85637 b/VERSIONS_WIP/85637 new file mode 100644 index 0000000000000000000000000000000000000000..d63c0dd11416b403bcf907d26ad26189e60c5bd1 --- /dev/null +++ b/VERSIONS_WIP/85637 @@ -0,0 +1,2 @@ + - ticket #85637 : Administration : maintenance des entrées de menu gauche et ajout de liens vers la documentation. + \ No newline at end of file diff --git a/VERSIONS_WIP/85748 b/VERSIONS_WIP/85748 new file mode 100644 index 0000000000000000000000000000000000000000..53172da69119f890321be460fcf7ae34245573cd --- /dev/null +++ b/VERSIONS_WIP/85748 @@ -0,0 +1,2 @@ + - ticket #85748 : Administration : activation des fonctionnalités de la version 8.0 Suricate Semantic. + \ No newline at end of file diff --git a/VERSIONS_WIP/85822 b/VERSIONS_WIP/85822 new file mode 100644 index 0000000000000000000000000000000000000000..c5dc251f781b12282eac462ec6ad9c02f2864608 --- /dev/null +++ b/VERSIONS_WIP/85822 @@ -0,0 +1 @@ + - ticket #85822 : Maintenance : Retrait d'un lien obsolète vers les composants Flash non supportés \ No newline at end of file diff --git a/VERSIONS_WIP/86010 b/VERSIONS_WIP/86010 new file mode 100644 index 0000000000000000000000000000000000000000..2989d7b513d94b4084b1d7531e8ed057ccfb13b3 --- /dev/null +++ b/VERSIONS_WIP/86010 @@ -0,0 +1,2 @@ + - ticket #86010 : Administration : activation des fonctionnalités de la version 8.0 . + \ No newline at end of file diff --git a/application/modules/admin/controllers/BibController.php b/application/modules/admin/controllers/BibController.php index 57a89d4a0b00c5816a7d1ac708ad72fe05de20d8..a3dd5d2edfa709b1f49d53a2ae43b8dbceab7f18 100644 --- a/application/modules/admin/controllers/BibController.php +++ b/application/modules/admin/controllers/BibController.php @@ -51,18 +51,6 @@ class Admin_BibController extends ZendAfi_Controller_Action { } - public function localisationsAction() { - $cls_loc = new Class_Localisation(); - $id_bib = (int)$this->_request->getParam('id_bib'); - $this->view->id_bib = $id_bib; - if (!$bib=Class_Bib::find($id_bib)) - return $this->_redirect('admin/bib/index'); - $this->view->nom_bib = $bib->getLibelle(); - $this->view->localisations = $bib->getLocalisations(); - $this->view->titre = $this->view->_("Localisations de la bibliothèque: %s", - $this->view->nom_bib); - } - protected function _checkPost($localisation) { $this->view->localisation = $localisation; @@ -186,19 +174,6 @@ class Admin_BibController extends ZendAfi_Controller_Action { } - public function plansAction() { - $cls_loc = new Class_Localisation(); - $id_bib = (int)$this->_request->getParam('id_bib'); - if (!$bib= Class_Bib::find($id_bib)) - return $this->_redirect('admin/'); - - $this->view->id_bib = $id_bib; - $this->view->nom_bib = $bib->getLibelle(); - $this->view->plans = $bib->getPlans(); - $this->view->titre = $this->view->_('Plans de la bibliothèque: %s', $this->view->nom_bib); - } - - public function addplanAction() { if (!$bib = $this->getBib()) return; diff --git a/application/modules/admin/controllers/OuverturesController.php b/application/modules/admin/controllers/OuverturesController.php index d89e451598c0aa1742ae1e7201d81320bbe3ba75..6bc5361db7e1e5048570502c36ef3b878ff3f643 100644 --- a/application/modules/admin/controllers/OuverturesController.php +++ b/application/modules/admin/controllers/OuverturesController.php @@ -65,12 +65,20 @@ class Admin_OuverturesController extends ZendAfi_Controller_Action { } + public function indexAction() { + $this->_forward('list'); + } + + + public function listAction() { parent::indexAction(); if ($this->_response->isRedirect()) return; $this->view->multimedia = $this->_is_multimedia; + $this->view->model_name = 'library'; + $this->view->library = $this->_library; $form = $this->_newHolidaysForm() diff --git a/application/modules/admin/controllers/UploadController.php b/application/modules/admin/controllers/UploadController.php index f7f06234165dcf513d6b9d9c3d8b63ade50a55c3..8aaf562b3e0e140f077fa34d3dd010acaeb7f06a 100644 --- a/application/modules/admin/controllers/UploadController.php +++ b/application/modules/admin/controllers/UploadController.php @@ -46,8 +46,7 @@ $(document).ready(function () { });"); $this->view->headLink() - ->appendStylesheet(URL_CSS . 'global.css') - ->appendStylesheet(URL_ADMIN_JS . 'multi_upload/fileuploader.css'); + ->appendStylesheet(URL_ADMIN_JS . 'multi_upload/fileuploader.css'); $this->_helper->getHelper('viewRenderer')->setLayoutScript('empty.phtml'); } diff --git a/application/modules/admin/views/scripts/index/adminvar.phtml b/application/modules/admin/views/scripts/index/adminvar.phtml index 13abaf7ce2c4e314602da6aba3977f0e3fb3d4b1..838f634030075945026f90b894ce82151958e456 100644 --- a/application/modules/admin/views/scripts/index/adminvar.phtml +++ b/application/modules/admin/views/scripts/index/adminvar.phtml @@ -1,41 +1,45 @@ <?php -Class_ScriptLoader::getInstance()->addSearchInputToContent($this->_('Filtrer les variables')); -?> +Class_ScriptLoader::getInstance() + ->addSearchInputToContent($this->_('Filtrer les variables')) + ->addFontAwesome(); -<table id="adminvars"> - <thead> - <tr class="soustitre"> - <th><?php echo $this->_('Clef'); ?></th> - <th><?php echo $this->_('Valeur'); ?></th> - <th><?php echo $this->_('action'); ?></th> - </tr> - </thead> - <tbody> - <?php - $ligne = 0; - foreach($this->vars as $var) { - $ligne ++ ; - $edit_url = $this->url(['controller' => 'index', - 'action' => 'adminvaredit', - 'cle' => $var->getClef()]); - ?> - <tr data-adminvar= "<?php echo $var->getClef(); ?>" class="<?php echo ($ligne & 1) ? "first" : "second";?>"> - <td style="vertical-align:top;" > - <?php echo $var->getDescription();?> - <br><sub><a data-popup="true" href="<?php echo $edit_url; ?>"> - <?php echo $var->getClef();?></a></sub> - </td> - <td> - <?php - echo ($renderer = $var->getRenderer()) - ? $renderer($var->getValeur(), $this) - : $this->adminVar($var); - ?> - </td> - <td style="width:2%;text-align:center"> - <a data-popup="true" href="<?php echo $edit_url; ?>"><?php echo $this->boutonIco("type=edit");?></a> - </td> - </tr> - <?php } ?> -</tbody> -</table> +$description = new Class_TableDescription('adminvars'); +$description + ->addColumn($this->_('Variable'), + ['attribute' => 'id', + 'callback' => function($var) + { + $private = $var->getMeta()->isPrivate(); + + return $this->tag('div', $var->getDescription()) + . $this->tag('sub', str_replace('_', ' ', $var->getId())) + . $this->tag('div', + $this->tag('i', + ' ' + . $this->tag('span', $private ? $this->_('Privée') : $this->_('Publique')), + ['class' => 'fa fa-' . ($private ? 'lock': 'unlock')])) +; + }, + 'options' => ['row_params' => function ($var) + { + return ['data-adminvar' => $var->getId()]; + }]]) + + ->addColumn($this->_('Valeur'), function($var) + { + return ($renderer = $var->getRenderer()) + ? $renderer($var->getValeur(), $this) + : $this->adminVar($var); + }) + + ->addRowAction(['label' => function($var) + { + return $this->_('Modifier la variable %s', $var->getId()); + }, + 'icon' => 'edit', + 'url' => '/admin/index/adminvaredit/cle/%s', + 'anchorOptions' => ['data-popup' => 'true'] + ]) + ; + +echo $this->renderTable($description, $this->vars); diff --git a/application/modules/admin/views/scripts/ouvertures/index.phtml b/application/modules/admin/views/scripts/ouvertures/list.phtml similarity index 100% rename from application/modules/admin/views/scripts/ouvertures/index.phtml rename to application/modules/admin/views/scripts/ouvertures/list.phtml diff --git a/application/modules/opac/controllers/RechercheController.php b/application/modules/opac/controllers/RechercheController.php index 3bf843fb0e70c519d645eb56f98d1e5e06c3a6ee..a3f3eebdf500f9f49891aa6ed749b2285a693716 100644 --- a/application/modules/opac/controllers/RechercheController.php +++ b/application/modules/opac/controllers/RechercheController.php @@ -301,6 +301,9 @@ class RechercheController extends ZendAfi_Controller_Action { public function viewnoticeAction() { + if ($authority_record = $this->_authorityFromParams()) + return $this->_redirect('/opac/recherche/viewnotice/id/' . $authority_record->getId()); + $id_notice = (int)$this->_getParam('id'); $clef_alpha = (string)$this->_getParam('clef'); @@ -401,6 +404,29 @@ class RechercheController extends ZendAfi_Controller_Action { } + protected function _authorityFromParams() { + if ((!$authority_id = $this->_getParam('authority_id')) + || (!$thesaurus_id = $this->_getParam('thesaurus_id'))) + return; + + $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; + } + + + protected function _recordWithThesaurusFacet($thesaurus_id, $item) { + if (!$record = $item->getNotice()) + return; + + return in_array(Class_CodifThesaurus::CODE_FACETTE . $thesaurus_id, $record->getFacetCodes()) + ? $record + : null; + } + + public function jsonRecordAction() { $this->_helper->getHelper('viewRenderer')->setNoRender(); diff --git a/build.sh b/build.sh index 40d8dc061e4a42ee16eebdfe7430b80d360657b6..c9c40756f8cf9f8486422c86a15ccd1a0760bbf2 100755 --- a/build.sh +++ b/build.sh @@ -24,4 +24,8 @@ sed -i "s/integration_pwd=root/integration_pwd=$DBPASS/g" config.php sed -i "s/integration_base=opac3/integration_base=$DBNAME/g" config.php cd .. -phpunit -c tests/phpunit.xml --exclude-group no-ci && phpunit -c tests/phpunit_db.xml --exclude-group no-ci && phpunit -c tests/phpunit_js.xml --exclude-group no-ci && cd cosmogramme/tests && phpunit --exclude-group no-ci && cd ../cosmozend/tests && phpunit --exclude-group no-ci +phpunit -c tests/phpunit.xml --list-suites && phpunit -c tests/phpunit.xml --exclude-group no-ci \ + && phpunit -c tests/phpunit_db.xml --list-suites && phpunit -c tests/phpunit_db.xml --exclude-group no-ci \ + && phpunit -c tests/phpunit_js.xml --list-suites && phpunit -c tests/phpunit_js.xml --exclude-group no-ci \ + && cd cosmogramme/tests && phpunit --list-suites && phpunit --exclude-group no-ci \ + && cd ../cosmozend/tests && phpunit --list-suites && phpunit --exclude-group no-ci diff --git a/cosmogramme/cosmozend/application/modules/cosmo/controllers/FacetsController.php b/cosmogramme/cosmozend/application/modules/cosmo/controllers/FacetsController.php index 83f599228d802de64d8977fae24a2d8fd518226a..ec4a844d076aff436fdff24e3022775f0dd8b0ee 100644 --- a/cosmogramme/cosmozend/application/modules/cosmo/controllers/FacetsController.php +++ b/cosmogramme/cosmozend/application/modules/cosmo/controllers/FacetsController.php @@ -20,93 +20,9 @@ */ -class Cosmo_FacetsController extends Zend_Controller_Action { - use Trait_Translator; - public function preDispatch() { - $this->cosmoPath = $this->view->cosmoPath = new CosmoPaths(); - } - - - public function indexAction() { - $this->view->models = Class_CodifThesaurus::findAllBy(['rules not' => null, - 'order' => 'libelle']); - $this->view->currentId = $this->_getParam('id'); - } - - - public function addAction() { - $this->view->model = Class_CodifThesaurus::newInstance([ - 'libelle_facette' => '** nouvelle facette **', - 'rules' => json_encode(['label' => $this->_getParam('rules')])]); - } - - - public function validateAction() { - if (!$this->_request->isPost()) { - $this->_gotoIndex(); - return; - } - - if (!$model = Class_CodifThesaurus::find($this->_getParam('id'))) - $model = Class_CodifThesaurus::newInstance(); - - $model - ->setLibelle($this->_getParam('libelle_facette')) - ->setLibelleFacette($this->_getParam('libelle_facette')) - ->setRules(json_encode(['label' => $this->_getParam('rules')])); - - if (!$model->isValid()) { - $this->view->model = $model; - $this->view->errors = $model->getErrors(); - $this->render('add'); - return; - } - - if (!$model->getIdThesaurus()) { - $libelle = preg_replace('/[^a-zA-Z0-9]/', '', $this->_getParam('libelle_facette')); - - $id_thesaurus = $this->generateNewIdThesaurusForLabel($libelle); - $model->setIdThesaurus($id_thesaurus); - $model->setCode($id_thesaurus); - } - - $model->save(); - $this->_gotoIndex($model->getId()); - } - - - protected function generateNewIdThesaurusForLabel($label) { - $id = substr(strtoupper($label), 0, 4); - - if (strlen($id) == 4 && !Class_CodifThesaurus::findFirstBy(['id_thesaurus' => $id])) - return $id; - - $label = substr(strtoupper($label), 0, 3); - $suffixes = array_merge(range(0, 9), range('a', 'z')); - while(!empty($suffixes)) { - $suffix = strtoupper(array_shift($suffixes));; - $id = sprintf("%'".$suffix."-4s", $label); - if (!Class_CodifThesaurus::findFirstBy(['id_thesaurus' => $id])) - return $id; - } - } - - - public function deleteAction() { - if ($model = Class_CodifThesaurus::find($this->_getParam('id'))) - $model->delete(); - $this->_gotoIndex(); - } - - - protected function _gotoIndex($id=null) { - $this->_redirect($this->view->url([ - 'module' => 'cosmo', - 'controller' => 'facets', - 'action' => 'index', - 'id' => $id - ], null, true), - ['prependBase' => false]); - } +class Cosmo_FacetsController extends ZendAfi_Controller_Action { + public function getPlugins() { + return ['ZendAfi_Controller_Plugin_ResourceDefinition_DynamicFacet', + 'ZendAfi_Controller_Plugin_Manager_DynamicFacet']; + } } -?> diff --git a/cosmogramme/cosmozend/application/modules/cosmo/controllers/IntegrationController.php b/cosmogramme/cosmozend/application/modules/cosmo/controllers/IntegrationController.php index 318457c846946ae6e21df8f26ebfb01c5384c8e0..4fc7dfbcddccf3796a8f80eaeb674c7bd2c026df 100644 --- a/cosmogramme/cosmozend/application/modules/cosmo/controllers/IntegrationController.php +++ b/cosmogramme/cosmozend/application/modules/cosmo/controllers/IntegrationController.php @@ -20,43 +20,43 @@ */ -class Cosmo_IntegrationController extends Zend_Controller_Action{ - use Trait_Translator; +class Cosmo_IntegrationController extends ZendAfi_Controller_Action{ - public function preDispatch() { - $this->cosmoPath = $this->view->cosmoPath = new CosmoPaths(); - } + public function preDispatch() { + parent::preDispatch(); + $this->cosmoPath = $this->view->cosmoPath = new CosmoPaths(); + } - public function controlAction() { - if (!$bib = Class_IntBib::find($this->_getParam('id', 0))) - $bib = Class_IntBib::newInstance(['nom_court' => 'Bibliothèque inconnue']); + public function controlAction() { + if (!$bib = Class_IntBib::find($this->_getParam('id', 0))) + $bib = Class_IntBib::newInstance(['nom_court' => 'Bibliothèque inconnue']); - $this->view->bib = $bib; - $this->view->integrations = $bib->getIntegrations(); - } + $this->view->bib = $bib; + $this->view->integrations = $bib->getIntegrations(); + } - public function testAction() { + public function testAction() { if ($layout = Zend_Layout::getMvcInstance()) $layout->disableLayout(); - if (!($type = $this->_getParam('type')) - || !($options = $this->_getParam('options'))) { - $this->view->response = 'Paramètres insuffisants'; - return; - } + if (!($type = $this->_getParam('type')) + || !($options = $this->_getParam('options'))) { + $this->view->response = 'Paramètres insuffisants'; + return; + } - if (!$service_name = Class_IntBib::detectService($type)) { - $this->view->response = 'Service de type ' . $type . ' inconnu'; - return; - } + if (!$service_name = Class_IntBib::detectService($type)) { + $this->view->response = 'Service de type ' . $type . ' inconnu'; + return; + } - $service = call_user_func([$service_name, 'getService'], $options); - $this->view->response = $service->test(); - if (!$this->view->response) - $this->view->response = 'Impossible de contacter le service'; - } + $service = call_user_func([$service_name, 'getService'], $options); + $this->view->response = $service->test(); + if (!$this->view->response) + $this->view->response = 'Impossible de contacter le service'; + } public function generateAction() { @@ -78,4 +78,50 @@ class Cosmo_IntegrationController extends Zend_Controller_Action{ $this->render('generate-log'); } + + + public function waitingFilesAction() { + $this->view->titre = $this->_('Fichiers en attente d\'intégration'); + $this->view->files = (new Class_Cosmogramme_Integration_WaitingFiles())->getCollection(); + } + + + public function waitingFilesDeleteAction() { + if (!$item_path = $this->_getParam('id')) { + $this->_helper->notify($this->_('La suppression n\'a pas fonctionné car il n\'y a pas de chemin à supprimer.')); + return $this->_redirectClose($this->_getReferer()); + } + + Class_FileManager::beOpenBar(); + + if(!$item = Class_FileManager::find($item_path)) { + $this->_helper->notify($this->_('La suppression n\'a pas fonctionné car le chemin est invalide.')); + return $this->_redirectClose($this->_getReferer()); + } + + $success = Class_FileManager::delete($item); + $message = $success + ? $this->_('"%s" supprimé.', $item->getPath()) + : $this->_('Impossible de supprimer "%s".', $item->getPath()); + + $this->_helper->notify($message); + return $this->_redirectClose($this->_getReferer()); + } + + + public function waitingFilesDownloadAction() { + if (!$item_path = $this->_getParam('id')) { + $this->_helper->notify($this->_('Le téléchargement n\'a pas fonctionné car il n\'y a pas de chemin à télécharger.')); + return $this->_redirectClose($this->_getReferer()); + } + + Class_FileManager::beOpenBar(); + + if(!$item = Class_FileManager::find($item_path)) { + $this->_helper->notify($this->_('Le téléchargement n\'a pas fonctionné car le chemin est invalide.')); + return $this->_redirectClose($this->_getReferer()); + } + + $this->_helper->fileManagerDownload($item); + } } \ No newline at end of file diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/facets/add.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/facets/add.phtml index d5705fe1380d93f8f930ca3d4d23b75a66c9214b..f9d4cb1251f5b7e8920f9e7887cb9b52d074bcb5 100644 --- a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/facets/add.phtml +++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/facets/add.phtml @@ -1,19 +1,3 @@ -<?php $model = $this->model; ?> -<h1>Codification des facettes dynamiques</h1> -<div class="liste"> - <?php if ($this->errors) { ?> - <ul style="color:red;font-weight:bolder;"> - <?php foreach ($this->errors as $error) { ?> - <li><?php echo $this->escape($error);?></li> - <?php } ?> - </ul> - <?php } ?> - <?php echo $this->cosmoFacets($this->model, true); ?> -</div> -<br/><br/> - <?php -echo $this->cosmoButton('Retour', - $this->url(['module' => 'cosmo', 'controller' => 'facets'], - null, true)); -?> +echo $this->tag('h1', $this->titre); +echo $this->renderForm($this->form); diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/facets/edit.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/facets/edit.phtml new file mode 100644 index 0000000000000000000000000000000000000000..f9d4cb1251f5b7e8920f9e7887cb9b52d074bcb5 --- /dev/null +++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/facets/edit.phtml @@ -0,0 +1,3 @@ +<?php +echo $this->tag('h1', $this->titre); +echo $this->renderForm($this->form); diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/facets/index.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/facets/index.phtml index 0023585f7d9481754ae3206e69fb5d5ba9f8eaf4..d4f57fbf8891e53a4ba85f7ed01eec471b2d835d 100644 --- a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/facets/index.phtml +++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/facets/index.phtml @@ -1,29 +1,14 @@ -<h1>Facettes dynamiques</h1> -<div class="liste"> - <?php - foreach($this->models as $model) { - $img = 'plus.gif'; - $display = false; - if ($model->getId() == $this->currentId) { - $img = 'moins.gif'; - $display = true; - } - ?> - <div class="liste_img"> - <?php echo $this->tagImg($this->cosmoPath->getCosmoBaseUrl() . 'images/'.$img, - ['id' => 'Ifacet' . $model->getId(), - 'style' => 'cursor:pointer', - 'onclick' => 'contracter_bloc(\'facet'.$model->getId().'\')']);?> - </div> - <div class="liste_titre"><?php echo $model->getLibelleFacette();?></div> - <?php echo $this->cosmoFacets($model, $display); ?> - <?php } ?> -</div> - -<br/><br/> <?php -echo $this->cosmoButton('Ajouter une facette dynamique', - $this->url(['module' => 'cosmo', - 'controller' => 'facets', - 'action' => 'add'], null, true)); -?> +echo $this->tag('h1', $this->titre); +echo $this->Button_New((new Class_Entity()) + ->setText($this->_('Ajouter une facette dynamique'))); + +$description = (new Class_TableDescription('facets')) + ->addColumn($this->_('Libellé'), 'libelle') + ->addRowAction(function($batch) + { + return $this->renderPluginsActions($batch); + }) + ; + +echo $this->renderTable($description, $this->thesauris); diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/integration/waiting-files.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/integration/waiting-files.phtml new file mode 100644 index 0000000000000000000000000000000000000000..d06e88f744b8521cd72a4d8eff33567242a72fa7 --- /dev/null +++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/integration/waiting-files.phtml @@ -0,0 +1,8 @@ +<?php +echo + $this->tag('h1', $this->titre) + . ($this->files + ? $this->renderTable((new Class_TableDescription_CosmoWaitingFiles('waiting-files')) + ->setView($this) + ->read(), $this->files) + : $this->tagNotice($this->_('Il n\'y a aucun fichier en attente d\'intégration'))); \ No newline at end of file diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/module.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/module.phtml index 54eb659a32b3608e6a75ad39cd79aba4c8d3e5a6..0c8c66939f567b1d41a047ff9d1701c2b67b90f6 100644 --- a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/module.phtml +++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/module.phtml @@ -26,8 +26,9 @@ echo $this->render($this->actionScript); $html = ob_get_contents(); ob_end_clean(); -$cosmo_base_url = (new CosmoPaths())->getCosmoBaseUrl(); - +$cosmo_path = new CosmoPaths(); +$base_url = $cosmo_path->getBaseUrl(); +$cosmo_base_url = $cosmo_path->getCosmoBaseUrl(); $cosmo_image_url = $cosmo_base_url . 'images/'; $scripts = Class_ScriptLoader::newInstance() @@ -40,7 +41,8 @@ $scripts = Class_ScriptLoader::newInstance() $cosmo_base_url . 'css/form.css', $cosmo_base_url . 'css/notices.css', $cosmo_base_url . 'css/nuage_tags.css']) - ->addInlineScript('var sUrlImg = "' . $cosmo_image_url . '"') + ->addInlineScript('var sUrlImg = "' . $cosmo_base_url . 'images/"') + ->addInlineScript('var imagesUrl = "' . $base_url . '/public/admin/images/"') ->addScript($cosmo_base_url . 'java_script/main.js'); Class_Admin_Skin::current()->renderScriptsOn($scripts); $script_loader = Class_ScriptLoader::getInstance(); diff --git a/cosmogramme/cosmozend/index.php b/cosmogramme/cosmozend/index.php index 410afdb6544a5a417f4ec9ba5a7e644c06b6399b..e6f94c2a1a604c883621380d69cb5823505024b6 100644 --- a/cosmogramme/cosmozend/index.php +++ b/cosmogramme/cosmozend/index.php @@ -32,9 +32,8 @@ set_include_path( $cosmozendPath . PATH_SEPARATOR . $cosmozendPath . '/application' . PATH_SEPARATOR . get_include_path()); -// pretending I am under Bokeh's root -chdir('../..'); - +// change dir to Bokeh's root +chdir($cosmo_path->getBasePath()); Zend_Session::start(); diff --git a/cosmogramme/cosmozend/tests/CosmoControllerTestCase.php b/cosmogramme/cosmozend/tests/CosmoControllerTestCase.php index 7dd9690fae9bf9aefd18a964b083902257f967a9..d9331fa8a8dbcabdb22e46772fbe58b11e815353 100644 --- a/cosmogramme/cosmozend/tests/CosmoControllerTestCase.php +++ b/cosmogramme/cosmozend/tests/CosmoControllerTestCase.php @@ -21,38 +21,40 @@ abstract class CosmoControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase { - use Storm_Test_THelpers; + use Storm_Test_THelpers; - public $bootstrap = 'bootstrap_frontcontroller.php'; + public $bootstrap = 'bootstrap_frontcontroller.php'; protected $_storm_default_to_volatile = true; - public function setUp() { - parent::setUp(); - Storm_Model_Abstract::unsetLoaders(); - Storm_Cache::setDefaultZendCache(null); + public function setUp() { + parent::setUp(); + Storm_Model_Abstract::unsetLoaders(); + Storm_Cache::setDefaultZendCache(null); if ($this->_storm_default_to_volatile) Storm_Model_Loader::defaultToVolatile(); $this->fixture('Class_Profil', ['id' => 1, 'libelle' => 'Home']); - } + } - public function tearDown() { + public function tearDown() { if ($this->_storm_default_to_volatile) Storm_Model_Loader::defaultToDb(); - Storm_Model_Abstract::unsetLoaders(); - } + Storm_Model_Abstract::unsetLoaders(); + Class_FileManager::reset(); + Class_FileManager_FileSystem::reset(); + } - public function postDispatch($url, $data) { - $this->getRequest() - ->setMethod('POST') - ->setPost($data); - return $this->dispatch($url, true); - } + public function postDispatch($url, $data) { + $this->getRequest() + ->setMethod('POST') + ->setPost($data); + return $this->dispatch($url, true); + } public function assertRedirectTo($url, $message = '') { @@ -66,27 +68,57 @@ abstract class CosmoControllerTestCase extends Zend_Test_PHPUnit_ControllerTestC } - public function dispatch($url = null, $throw_exceptions = false) { - // redirector should not exit - $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector'); - $redirector->setExit(false); - - // json helper should not exit - $json = Zend_Controller_Action_HelperBroker::getStaticHelper('json'); - $json->suppressExit = true; - - $request = $this->getRequest(); - if (null !== $url) { - $request->setRequestUri($url); - } - $request->setPathInfo(null); - - $this->frontController - ->setRequest($request) - ->setResponse($this->getResponse()) - ->throwExceptions($throw_exceptions) - ->returnResponse(false); - $this->frontController->dispatch(); - } + public function dispatch($url = null, $throw_exceptions = true) { + // redirector should not exit + $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector'); + $redirector->setExit(false); + + // json helper should not exit + $json = Zend_Controller_Action_HelperBroker::getStaticHelper('json'); + $json->suppressExit = true; + + $request = $this->getRequest(); + if (null !== $url) { + $request->setRequestUri($url); + } + $request->setPathInfo(null); + + $this->frontController + ->setRequest($request) + ->setResponse($this->getResponse()) + ->throwExceptions($throw_exceptions) + ->returnResponse(false); + $this->frontController->dispatch(); + } + + + public function assertFlashMessengerContentContains($value, $message = '') { + $messages = $this->_getFlashMessengerNotifications(); + foreach($messages as $flash_message) { + if (false!==strpos($flash_message[ZendAfi_Controller_Action_Helper_FlashMessenger::NOTIFICATION]['message'], + $value)) + return; + } + + $content = print_r($messages, true); + $this->fail("Flash messenger does not contains: \n".$value."\nbut:\n".$content."\n".$message); + } + + + protected function _getFlashMessengerNotifications() { + $messages = $this->_getFlashMessengerMessages(); + return array_filter($messages, + function($data) + { + return is_array($data) + && isset($data[ZendAfi_Controller_Action_Helper_FlashMessenger::NOTIFICATION]); + }); + } + + + protected function _getFlashMessengerMessages() { + $session = new Zend_Session_Namespace('FlashMessenger'); + $messages = $session->__get('default'); + return $messages ? $messages : []; + } } -?> \ No newline at end of file diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php index 8f0b4313a41a869b0efb18d2b66174ccaaf0181a..bdcfdc9d61191bd3893c37c9ed287e954b00e074 100644 --- a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php +++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php @@ -1146,4 +1146,169 @@ class Cosmo_DataProfileControllerMultiValuesTest extends Cosmo_DataProfileContro $this->assertXPathContentContains('//script', 'values:{"1_label":["am","bm","","em","mm","","","","","","",""],"1_zone":["BDA","BDJ","LFA","LFJ","LDA","LDJ","LCDA","LCDJ","PATIMP","PATMS","PERIP","PATINC"]}', $this->_response->getBody()); } +} + + + + +abstract class Cosmo_DataProfileControllerAuthorityTestCase + extends Cosmo_DataProfileControllerTestCase { + + public function setUp() { + parent::setUp(); + + $attributs = [[Class_IntProfilDonnees::PROFILE_INDEX_SYSTEMS_FIELDS + => [['rule' => 'ISO', + 'system' => 'rameau', + 'default_type' => 'a', + 'thesaurus' => '3']]]]; + + $this->fixture('Class_IntProfilDonnees', + ['id' => 654, + 'libelle' => 'Authorities', + 'type_fichier' => Class_IntProfilDonnees::FT_AUTHORITY, + 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'accents' => Class_IntProfilDonnees::ENCODING_UTF8, + 'attributs' => serialize($attributs)]); + + $this->fixture('Class_CodifThesaurus', + ['id' => 5, + 'libelle' => 'Mots-clés TESS', + 'rule_zone' => '609', + 'rule_label_field' => 'a', + 'rule_id_field' => '9', + 'id_thesaurus' => 'MOTS']); + } +} + + + + +class Cosmo_DataProfileControllerAuthorityEditTest + extends Cosmo_DataProfileControllerAuthorityTestCase { + + public function setUp() { + parent::setUp(); + $this->dispatch('cosmo/data-profile/edit/id/654', true); + } + + + /** @test */ + public function fieldsetIndexationShouldBePresent() { + $this->assertXPathContentContains('//fieldset//legend', 'Indexation'); + } + + + /** @test */ + public function indexSystemsMultiInputRootShouldBePresent() { + $this->assertXPath('//div[@id="multi_inputs_index_systems"]'); + } + + + /** @test */ + public function indexSystemsMultiInputShouldBeInitialized() { + $this->assertXPathContentContains('//script', '$("#multi_inputs_index_systems").multi_inputs('); + } + + + /** @test */ + public function multiInputRuleShouldBePresent() { + $this->assertXPathContentContains('//script', '"name":"index_system_rule"'); + } + + + /** @test */ + public function ruleValueShouldBePresent() { + $this->assertXPathContentContains('//script', '"index_system_rule":["ISO"]'); + } + + + /** @test */ + public function multiInputSystemLabelShouldBePresent() { + $this->assertXPathContentContains('//script', '"name":"index_system_label"'); + } + + + /** @test */ + public function systemLabelValueShouldBePresent() { + $this->assertXPathContentContains('//script', '"index_system_label":["rameau"]'); + } + + + /** @test */ + public function multiInputDefaultTypeShouldBePresent() { + $this->assertXPathContentContains('//script', '"name":"index_system_default_type"'); + } + + + /** @test */ + public function defaultTypeValueShouldBePresent() { + $this->assertXPathContentContains('//script', '"index_system_default_type":["a"]'); + } + + + /** @test */ + public function multiInputThesaurusIdShouldBePresent() { + $this->assertXPathContentContains('//script', '"name":"index_system_thesaurus"'); + } + + + /** @test */ + public function systemThesaurusValueShouldBePresent() { + $this->assertXPathContentContains('//script', '"index_system_thesaurus":["3"]'); + } + + + /** @test */ + public function multiInputShouldContainsTESSThesaurusOption() { + $this->assertXPathContentContains('//script', '"5":"Mots-cl\\u00e9s TESS (609$9)"'); + } +} + + + +class Cosmo_DataProfileControllerAuthorityEditPostTest + extends Cosmo_DataProfileControllerAuthorityTestCase { + + protected $_prefs; + + public function setUp() { + parent::setUp(); + $this->postDispatch('cosmo/data-profile/edit/id/654', + ['libelle' => 'Authorities', + 'type_fichier' => Class_IntProfilDonnees::FT_AUTHORITY, + 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'accents' => Class_IntProfilDonnees::ENCODING_UTF8, + 'index_system_rule' => ['AFNOR'], + 'index_system_label' => ['TESS'], + 'index_system_default_type' => ['j'], + 'index_system_thesaurus' => ['5']]); + + Class_IntProfilDonnees::clearCache(); + $this->_prefs = Class_IntProfilDonnees::find(654)->getIndexSystemsPrefs()[0]; + } + + + /** @test */ + public function ruleShouldBeAFNOR() { + $this->assertEquals('AFNOR', $this->_prefs['rule']); + } + + + /** @test */ + public function systemShouldBeTESS() { + $this->assertEquals('TESS', $this->_prefs['system']); + } + + + /** @test */ + public function defaultTypeShouldBeJ() { + $this->assertEquals('j', $this->_prefs['default_type']); + } + + + /** @test */ + public function thesaurusShouldBe5() { + $this->assertEquals('5', $this->_prefs['thesaurus']); + } } \ No newline at end of file diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DynamicFacetsControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DynamicFacetsControllerTest.php index c1e3cd08033938ccd23790f327eabcf1e2b72cba..029e4d57336d4a32cf99b062dbe2e05cd6a0ed98 100644 --- a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DynamicFacetsControllerTest.php +++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DynamicFacetsControllerTest.php @@ -20,234 +20,351 @@ */ -abstract class Cosmo_DynamicFacetsControllerTestCase extends CosmoControllerTestCase { +class Cosmo_DynamicFacetsControllerIndexTest extends CosmoControllerTestCase { public function setUp() { - parent::setUp(); - $docu = $this->fixture('Class_CodifThesaurus', - ['id' => 3, - 'libelle' => 'Document', - 'libelle_facette' => 'Document', - 'id_thesaurus' => 'DOCU', - 'id_origine' => null, - 'code' => null, - 'rules' => '{"label":" 99$t "}']); - - } -} + parent::setUp(); + $this->fixture('Class_CodifThesaurus', + ['id' => 3, + 'libelle' => 'Document', + 'libelle_facette' => 'Document', + 'id_thesaurus' => 'DOCU', + 'id_origine' => null, + 'code' => 'DOCU', + 'rule_zone' => '345', + 'rule_label_field' => 't', + 'rule_id_field' => '9']); + $this->dispatch('/cosmo/facets/index', true); + } -class Cosmo_DynamicFacetsControllerIndexTest extends Cosmo_DynamicFacetsControllerTestCase { - public function setUp() { - parent::setUp(); - $this->dispatch('/cosmo/facets/index', true); + /** @test */ + public function titleShouldBeDynamicFacets() { + $this->assertXpathContentContains('//h1' , 'Facettes dynamiques'); - } + } /** @test */ - public function titleShouldBeDynamicFacets() { - $this->assertXpathContentContains('//h1' , 'Facettes dynamiques'); + public function addButtonShouldBePresent() { + $this->assertXpath('//button[contains(@data-url, "/cosmo/facets/add")]'); + } - } + + /** @test */ + public function documentShouldBeDisplayed() { + $this->assertXpathContentContains('//td', 'Document'); + } /** @test */ - public function addButtonShouldBePresent() { - $this->assertXpath('//input[contains(@onclick, "/cosmo/facets/add")]'); - } + public function documentEditLinkShouldBeDisplayed() { + $this->assertXpath('//td//a[contains(@href, "/facets/edit/id/3")]'); + } - /** @test */ - public function facetDocumentShouldBeDisplayed() { - $this->assertXpath('//form[contains(@action, "/cosmo/facets/validate/id/3")]'); - } + /** @test */ + public function documentDeleteLinkShouldBeDisplayed() { + $this->assertXpath('//td//a[contains(@href, "/facets/delete/id/3")]'); + } +} - /** @test */ - public function facetsRulesShouldBePresent() { - $this->assertXpathContentContains('//textarea[@name="rules"]', '99$t',$this->_response->getBody()); - } - /** @test */ - public function facetDeleteButtonShouldBePresent() { - $this->assertXpath('//input[contains(@onclick, "/cosmo/facets/delete/id/3")]'); - } -} +class Cosmo_DynamicFacetsControllerAddTest extends CosmoControllerTestCase { + public function setUp() { + parent::setUp(); + $this->dispatch('/cosmo/facets/add', true); + } + + + /** @test */ + public function titleShouldBePresent() { + $this->assertXpathContentContains('//h1', 'Ajouter une facette dynamique'); + } + + + /** @test */ + public function labelShouldDefaultToNouvelleFacette() { + $this->assertXpath('//input[@name="libelle"][@value="** nouvelle facette dynamique **"]'); + } + + + /** @test */ + public function zoneShouldBePresent() { + $this->assertXPath('//input[@name="rule_zone"]'); + } + /** @test */ + public function labelFieldShouldBePresent() { + $this->assertXPath('//select[@name="rule_label_field"]'); + } -class Cosmo_DynamicFacetsControllerValidateAddPostTest extends Cosmo_DynamicFacetsControllerTestCase { - public function setUp() { - parent::setUp(); - $this->postDispatch( - '/cosmo/facets/validate/id/3', - [ - 'libelle_facette' => 'New facet name', - 'rules' => '88$a'] - ); - $this->model = Class_CodifThesaurus::find(3); - } + /** @test */ + public function idFieldShouldBePresent() { + $this->assertXPath('//select[@name="rule_id_field"]'); + } - /** @test */ - public function labelShouldBeNewFaceName() { - $this->assertEquals('New facet name', $this->model->getLibelle()); - } + /** @test */ + public function labelForBokehShouldBePresent() { + $this->assertXPath('//input[@name="libelle_facette"][@value="** nouvelle facette dynamique **"]'); + } /** @test */ - public function idThesaurusShouldNotBeModifiedIfAlreadyExist() { - $this->assertEquals('DOCU', $this->model->getIdThesaurus()); - } + public function inputLabelStartPosShouldBeNumberWithValueOne() { + $this->assertXPath('//input[@name="rule_label_start_pos"][@type="number"][@min="1"][@value="1"]'); + } - /** @test */ - public function rulesShouldBeDollarXEqualsZeroSeven() { - $this->assertEquals('88$a', $this->model->getRulesLabel()); - } + /** @test */ + public function inputLabelLengthShouldBeNumberWithValueZero() { + $this->assertXPath('//input[@name="rule_label_length"][@type="number"][@min="0"][@value="0"]'); + } } +class Cosmo_DynamicFacetsControllerAddPostValidTest extends CosmoControllerTestCase { + protected $model; -class Cosmo_DynamicFacetsControllerValidatePostWithErrorsTest extends Cosmo_DynamicFacetsControllerTestCase { - public function setUp() { - parent::setUp(); - $this->postDispatch( - '/cosmo/facets/validate/id/3', - [ - 'libelle_facette' => '', - 'rules' => '33']); + public function setUp() { + parent::setUp(); - $this->model = Class_CodifThesaurus::find(3); - } + $this->postDispatch('/cosmo/facets/add', ['libelle' => 'New facet name', + 'rule_zone' => '609', + 'rule_label_field' => 'a', + 'rule_id_field' => '9', + 'rule_label_start_pos' => '2', + 'rule_label_length' => '4']); + Class_CodifThesaurus::clearCache(); + $this->model = Class_CodifThesaurus::findFirstBy(['libelle' => 'New facet name']); + } - public function errorsProvider() { - return [ - ['Vous devez définir le libellé'], - ['La règle n\'est pas de la forme 686$a']]; - } + /** @test */ + public function labelShouldBeNewFacetName() { + $this->assertEquals('New facet name', $this->model->getLibelle()); + } - /** - * @test - * @dataProvider errorsProvider - */ - public function errorShouldBePresent($message) { - $this->assertXpathContentContains('//li', $message, $this->_response->getBody()); - } + /** @test */ + public function idThesaurusShouldBeNEWF() { + $this->assertEquals('NEWF', $this->model->getIdThesaurus()); + } - /** @test */ - public function labelShouldNotBeSaved() { - $this->assertTrue($this->model->hasChangedAttribute('libelle')); - } + /** @test */ + public function zoneShouldBe609() { + $this->assertEquals('609', $this->model->getRuleZone()); + } - /** @test */ - public function rulesShouldNotBeSaved() { - $this->assertTrue($this->model->hasChangedAttribute('rules')); - } -} + /** @test */ + public function labelFieldShouldBeA() { + $this->assertEquals('a', $this->model->getRuleLabelField()); + } + /** @test */ + public function idFieldShouldBe9() { + $this->assertEquals('9', $this->model->getRuleIdField()); + } -class Cosmo_DynamicFacetsControllerValidateTest extends Cosmo_DynamicFacetsControllerTestCase { - /** @test */ - public function idThesaurusShouldBeDOC0() { - $this->postDispatch( - '/cosmo/facets/validate', - ['libelle_facette' => 'doc', - 'rules' => '33$2']); - $this->assertEquals('DOC0', - Class_CodifThesaurus::findFirstBy(['libelle'=>'doc'])->getIdThesaurus()); - } + /** @test */ + public function rulesLabelStartPosShouldBeTwo() { + $this->assertEquals('2', $this->model->getRulesAsArray()['rule_label_start_pos']); + } - /** @test */ - public function withExistingIdThesaurusDOCXNewIdThesaurusShouldBeDOC1() { - $this->fixture('Class_CodifThesaurus', - ['libelle' => 'doc that i love', - 'id_thesaurus' => 'DOC0', - 'rules' => '{"label":" 345$t "}']); + /** @test */ + public function rulesLabelLengthShouldBeFour() { + $this->assertEquals('4', $this->model->getRulesAsArray()['rule_label_length']); + } +} - $this->postDispatch( - '/cosmo/facets/validate', - ['libelle_facette' => 'doc', - 'rules' => '33$2']); - $this->assertEquals('DOC1', - Class_CodifThesaurus::findFirstBy(['libelle'=>'doc'])->getIdThesaurus()); - } + +class Cosmo_DynamicFacetsControllerValidateTest extends CosmoControllerTestCase { + /** @test */ + public function idThesaurusShouldBeDOC0() { + $this->postDispatch('/cosmo/facets/add', ['libelle' => 'doc', + 'rule_zone' => '033', + 'rule_label_field' => '8', + 'rule_label_start_pos' => '1', + 'rule_label_length' => '0']); + $this->assertEquals('DOC0', + Class_CodifThesaurus::findFirstBy(['libelle'=>'doc'])->getIdThesaurus()); + } /** @test */ - public function withExistingIdThesaurusDOCUNewIdThesaurusShouldBeDOC0() { - $this->fixture('Class_CodifThesaurus', - ['libelle' => 'doc that i love', - 'id_thesaurus' => 'DOCU', - 'rules' => '{"label":" 345$t "}']); + public function withExistingIdThesaurusDOCXNewIdThesaurusShouldBeDOC1() { + $this->fixture('Class_CodifThesaurus', + ['libelle' => 'doc that i love', + 'id_thesaurus' => 'DOC0', + 'rule_zone' => '345', + 'rule_label_field' => 't', + 'rule_label_start_pos' => '1', + 'rule_label_length' => '0']); + + $this->postDispatch('/cosmo/facets/add', ['libelle' => 'doc', + 'rule_zone' => '345', + 'rule_label_field' => '3', + 'rule_label_start_pos' => '1', + 'rule_label_length' => '0']); + + $this->assertEquals('DOC1', + Class_CodifThesaurus::findFirstBy(['libelle'=>'doc'])->getIdThesaurus()); + + } - $this->postDispatch( - '/cosmo/facets/validate', - ['libelle_facette' => 'docu', - 'rules' => '33$2']); - $this->assertEquals('DOC0', - Class_CodifThesaurus::findFirstBy(['libelle'=>'docu'])->getIdThesaurus()); + /** @test */ + public function withExistingIdThesaurusDOCUNewIdThesaurusShouldBeDOC0() { + $this->fixture('Class_CodifThesaurus', + ['libelle' => 'doc that i love', + 'id_thesaurus' => 'DOCU', + 'rule_zone' => '345', + 'rule_label_field' => 't', + 'rule_label_start_pos' => '1', + 'rule_label_length' => '0']); - } + $this->postDispatch('/cosmo/facets/add', ['libelle' => 'docu', + 'rule_zone' => '345', + 'rule_label_field' => '3', + 'rule_label_start_pos' => '1', + 'rule_label_length' => '0']); + $this->assertEquals('DOC0', + Class_CodifThesaurus::findFirstBy(['libelle'=>'docu'])->getIdThesaurus()); - /** @test */ - public function withSpecialCharsNewIdThesaurusShouldBeFourLetters() { - $this->postDispatch( - '/cosmo/facets/validate', - ['libelle_facette' => 'Année top 5', - 'rules' => '66$6']); + } - $this->assertEquals('ANNE', - Class_CodifThesaurus::findFirstBy(['libelle'=>'Année top 5'])->getIdThesaurus()); - } + /** @test */ + public function withSpecialCharsNewIdThesaurusShouldBeFourLetters() { + $this->postDispatch('/cosmo/facets/add', ['libelle' => 'Année top 5', + 'rule_zone' => '066', + 'rule_label_field' => '6', + 'rule_label_start_pos' => '1', + 'rule_label_length' => '0']); + + $this->assertEquals('ANNE', + Class_CodifThesaurus::findFirstBy(['libelle'=>'Année top 5'])->getIdThesaurus()); + } } +class Cosmo_DynamicFacetsControllerEditTest extends CosmoControllerTestCase { + public function setUp() { + parent::setUp(); + + $this->fixture('Class_CodifThesaurus', + ['id' => 3, + 'libelle' => 'Document', + 'libelle_facette' => 'Document', + 'id_thesaurus' => 'DOCU', + 'id_origine' => null, + 'code' => 'DOCU', + 'rule_zone' => '345', + 'rule_label_field' => 't', + 'rule_id_field' => '9']); + + $this->dispatch('/cosmo/facets/edit/id/3', true); + } + + + /** @test */ + public function titleShouldBePresent() { + $this->assertXpathContentContains('//h1', 'Modifier une facette dynamique'); + } + -class Cosmo_DynamicFacetsControllerAddTest extends Cosmo_DynamicFacetsControllerTestCase { - public function setUp() { - parent::setUp(); - $this->dispatch('/cosmo/facets/add', true); - } + /** @test */ + public function labelShouldBeDocument() { + $this->assertXpath('//input[@name="libelle"][@value="Document"]'); + } - /** @test */ - public function titleShouldBePresent() { - $this->assertXpathContentContains('//h1', 'Codification des facettes dynamiques'); - } + /** @test */ + public function zoneShouldBe345() { + $this->assertXPath('//input[@name="rule_zone"][@value="345"]'); + } - /** @test */ - public function formActionShouldGoToValidate() { - $this->assertXpath('//form[contains(@action, "/cosmo/facets/validate")]'); - } + /** @test */ + public function labelFieldShouldBeT() { + $this->assertXPath('//select[@name="rule_label_field"]//option[@value="t"][@selected]'); + } - /** @test */ - public function labelShouldDefaultToNouvelleFacette() { - $this->assertXpath('//input[@name="libelle_facette"][@value="** nouvelle facette **"]'); - } + /** @test */ + public function idFieldShouldBe9() { + $this->assertXPath('//select[@name="rule_id_field"]//option[@value="9"][@selected]'); + } + + + /** @test */ + public function idThesaurusShouldBeDocu() { + $this->assertXPath('//input[@name="id_thesaurus"][@value="DOCU"]'); + } } -?> \ No newline at end of file + +class Cosmo_DynamicFacetsControllerEditPostTest extends CosmoControllerTestCase { + public function setUp() { + parent::setUp(); + + $this->fixture('Class_CodifThesaurus', + ['id' => 3, + 'libelle' => 'Document', + 'libelle_facette' => 'Document', + 'id_thesaurus' => 'DOCU', + 'id_origine' => null, + 'code' => 'DOCU', + 'rule_zone' => '345', + 'rule_label_field' => 't', + 'rule_id_field' => '9', + 'rule_label_start_pos' => '1', + 'rule_label_length' => '0']); + + $this->postDispatch('/cosmo/facets/edit/id/3', + ['libelle' => 'Document', + 'libelle_facette' => 'Document', + 'rule_zone' => '609', + 'rule_label_field' => 'a', + 'rule_id_field' => '3', + 'rule_label_start_pos' => '1', + 'rule_label_length' => '0']); + } + + + /** @test */ + public function shouldRedirectToEdit() { + $this->assertRedirectTo('/cosmo/facets/edit/id/3'); + } + + + /** @test */ + public function shouldNotifySave() { + $this->assertFlashMessengerContentContains('Facette dynamique "Document" sauvegardée'); + } + + + /** @test */ + public function ruleZoneShouldBecome609() { + $this->assertEquals('609', Class_CodifThesaurus::find(3)->getRuleZone()); + } +} \ No newline at end of file diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/IntegrationControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/IntegrationControllerTest.php index 6ebfd9c32d69829b53c50796b9943ea7e3651027..eb6fde315fd409ff3a028d80b212280b4657bd75 100644 --- a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/IntegrationControllerTest.php +++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/IntegrationControllerTest.php @@ -595,4 +595,138 @@ class Cosmo_IntegrationControllerGenerateActionNanookPostTest public function shouldSayFinished() { $this->assertXPathContentContains('//h2', 'Traitement terminé'); } +} + + + +abstract class Cosmo_IntegrationControllerWaitingFilesTestCase extends CosmoControllerTestCase { + protected $_tot; + + public function setUp() { + parent::setUp(); + Class_CosmoVar::set('ftp_path', '/ccpl34'); + + $this->fixture('Class_IntMajAuto', + ['id' => 43, + 'int_bib' => $this->fixture('Class_IntBib', + ['id' => 1, + 'nom_court' => 'Lunel']), + 'libelle' => 'total', + 'profil_donnees' => $this->fixture('Class_IntProfilDonnees', + ['id' => 34, + 'libelle' => 'Unimarc KTM']), + 'type_operation' => Class_IntMajAuto::OP_FULL_IMPORT, + 'nom_fichier' => 'lunel/[DATE]_records_tot.mrc', + 'taille_min_import_total' => 0]); + + $lunel = $this->mock()->whenCalled('getPath') + ->answers('/ccpl34/lunel') + ->whenCalled('getName')->answers('lunel'); + + $this->_tot = $this->mock() + ->whenCalled('getParent')->answers($lunel) + ->whenCalled('isWritable')->answers(true) + ->whenCalled('getName')->answers('20190116220001_records_tot.mrc') + ->whenCalled('getMTime')->answers('2019-01-13 22:88:77') + ->whenCalled('getSize')->answers('42 Ko') + ->whenCalled('getFileSize')->answers(43986) + ->whenCalled('getId')->answers('/ccpl34/lunel/20190116220001_records_tot.mrc') + ->whenCalled('getModels')->answers([]) + ->whenCalled('isDir')->answers(false) + ->whenCalled('getPath')->answers('/ccpl34/lunel/') + ->whenCalled('readfile')->answers(true) + ->whenCalled('getProgrammed')->answers(Class_IntMajAuto::find(43)) + ; + + $this->_tot->whenCalled('setProgrammed')->answers($this->_tot); + + $file_system = $this + ->mock() + ->whenCalled('directoriesAt')->with('/ccpl34')->answers([$lunel]) + + ->whenCalled('filesAt')->with('/ccpl34/lunel')->answers([$this->_tot]) + + ->whenCalled('directoryAt')->with('ccpl34/lunel/20190116220001_records_tot.mrc') + ->answers(null) + + ->whenCalled('fileAt')->with('ccpl34/lunel/20190116220001_records_tot.mrc') + ->answers($this->_tot) + + ->whenCalled('delete')->with('/ccpl34/lunel/20190116220001_records_tot.mrc') + ->answers(true) + ; + + Class_FileManager::setFileSystem($file_system); + + Class_AdminVar::set('NOM_DOMAINE', 'http://localhost'); + } +} + + + +class Cosmo_IntegrationControllerWaitingFilesActionTest + extends Cosmo_IntegrationControllerWaitingFilesTestCase { + public function setUp() { + parent::setUp(); + $this->dispatch('/cosmo/integration/waiting-files'); + } + + + /** @test */ + public function titleShouldBeFichiersEnAttenteDIntegration() { + $this->assertXPathContentContains('//h1', 'Fichiers en attente d\'intégration'); + } + + + /** @test */ + public function tableShouldContainsLunelDirectory() { + $this->assertXPathContentContains('//td', 'lunel'); + } + + + /** @test */ + public function tableShouldContainsLibraryLunel() { + $this->assertXPathContentContains('//td', 'Lunel'); + } + + + /** @test */ + public function linkToDeleteRecordTotShouldBePresent() { + $this->assertXPath('//a[@href = "/cosmo/integration/waiting-files-delete?id=%2Fccpl34%2Flunel%2F20190116220001_records_tot.mrc"]'); + } + + + /** @test */ + public function linkToDownloadRecordTotShouldBePresent() { + $this->assertXPath('//a[@href = "/cosmo/integration/waiting-files-download?id=%2Fccpl34%2Flunel%2F20190116220001_records_tot.mrc"]'); + } +} + + + +class Cosmo_IntegrationControllerWaitingFilesDeleteTest + extends Cosmo_IntegrationControllerWaitingFilesTestCase { + + public function setUp() { + parent::setUp(); + $this->dispatch('/cosmo/integration/waiting-files-delete?id=%2Fccpl34%2Flunel%2F20190116220001_records_tot.mrc'); + } + + + /** @test */ + public function recordsTotShouldBeDeleted() { + $this->assertTrue(Class_FileManager::getFileSystem()->methodHasBeenCalled('delete')); + } +} + + + +class Cosmo_IntegrationControllerWaitingFilesDownloadTest + extends Cosmo_IntegrationControllerWaitingFilesTestCase { + + /** @test */ + public function totShouldBeRead() { + $this->dispatch('/cosmo/integration/waiting-files-download?id=%2Fccpl34%2Flunel%2F20190116220001_records_tot.mrc'); + $this->assertTrue($this->_tot->methodHasBeenCalled('readfile')); + } } \ No newline at end of file diff --git a/cosmogramme/cosmozend/tests/phpunit.xml b/cosmogramme/cosmozend/tests/phpunit.xml index 034c832a73fb3b01bf9c867289d0b705bd1171dd..1f0e8a8a7a656425058a31f72c3f627a4335b3e2 100644 --- a/cosmogramme/cosmozend/tests/phpunit.xml +++ b/cosmogramme/cosmozend/tests/phpunit.xml @@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA stopOnError="false" > <testsuites> - <testsuite name="ApplicationTestSuite"> + <testsuite name="Cosmozend"> <directory>./</directory> </testsuite> </testsuites> diff --git a/cosmogramme/php/_menu.php b/cosmogramme/php/_menu.php index 5cb66594acad9d2c0a151c5d156d7d4934e80200..b6c05c6a316cbc02ca11f8734a4a3eabce1e60ec 100644 --- a/cosmogramme/php/_menu.php +++ b/cosmogramme/php/_menu.php @@ -70,7 +70,7 @@ else ligneMenu("Contrôle des intégrations","integre_controle_integrations.php"); ligneMenu("Journal des intégrations","../cosmozend/cosmo/logs"); ligneMenu("Traitements en cours","integre_traitements_attente.php"); - ligneMenu("Fichiers en attente","integre_fichiers_attente.php"); + ligneMenu("Fichiers en attente","../cosmozend/cosmo/integration/waiting-files"); ligneMenu("Lancer les traitements","integre_traite_main.php",true); ?> <div class="menu_section">Analyse des données</div> diff --git a/cosmogramme/php/classes/classe_notice_integration.php b/cosmogramme/php/classes/classe_notice_integration.php index 7cee1bb1aab0d3b981726f8bf7ee843dc431c549..df5cd39447e4c52b05cb90d354b5f08eed63faa4 100644 --- a/cosmogramme/php/classes/classe_notice_integration.php +++ b/cosmogramme/php/classes/classe_notice_integration.php @@ -112,7 +112,7 @@ class notice_integration { switch($this->format) { case Class_IntProfilDonnees::FORMAT_UNIMARC: case Class_IntProfilDonnees::FORMAT_UNIMARC_XML: - $this->analyseur = new notice_unimarc(); + $this->analyseur = new notice_unimarc($id_bib); break; case Class_IntProfilDonnees::FORMAT_CG68_ARCHIVES: @@ -510,7 +510,7 @@ class notice_integration { 'other_terms'=> $this->indexation->getfulltext($this->notice['other_terms']), 'editeur' => $this->indexation->getfullText($this->notice['editeur']), 'collection' => $this->indexation->getfullText($this->notice['collection']), - 'matieres' => $this->indexation->getfullText($this->_getFulltextTopics()), + 'matieres' => $this->indexation->getfullText($this->_getFulltextSubjects()), 'dewey' => $this->indexation->getfullText($this->notice['full_dewey']), 'facettes' => $this->notice['facettes'], 'isbn' => $this->notice['isbn'], @@ -551,21 +551,21 @@ class notice_integration { } - protected function _getFulltextTopics() { + protected function _getFulltextSubjects() { if (!$this->notice['matieres']) return ; return array_merge($this->notice["matieres"], $this->notice["matieres_renvois"], - $this->_getCodifTopicsRenvois()); + $this->_getCodifSubjectsRenvois()); } - protected function _getCodifTopicsRenvois() { + protected function _getCodifSubjectsRenvois() { $see_also = []; - foreach($this->notice['matieres'] as $topic) { - if (($codif = $this->_getCodifTopic($topic)) + foreach($this->notice['matieres'] as $subject) { + if (($codif = $this->_getCodifSubject($subject)) && $codif->hasMotsRenvois()) $see_also[] = $codif->getMotsRenvois(); } @@ -856,7 +856,7 @@ class notice_integration { // Matieres if($this->notice["matieres"]) { foreach($this->notice["matieres"] as $matiere) { - if (!$codif_matiere = $this->_getCodifTopic($matiere)) continue; + if (!$codif_matiere = $this->_getCodifSubject($matiere)) continue; $facettes[]="M".$codif_matiere->getId(); } } @@ -921,8 +921,8 @@ class notice_integration { } - protected function _getCodifTopic($topic) { - return $this->getCodifProvider()->getTopic($topic); + protected function _getCodifSubject($subject) { + return $this->getCodifProvider()->getSubject($subject); } diff --git a/cosmogramme/php/classes/classe_unimarc.php b/cosmogramme/php/classes/classe_unimarc.php index 4915b3929f509bd0218895e15c8ad3d117e31c1b..c679459bf8e3953cea7b4cb04037e9ebe72761df 100644 --- a/cosmogramme/php/classes/classe_unimarc.php +++ b/cosmogramme/php/classes/classe_unimarc.php @@ -37,21 +37,23 @@ class notice_unimarc extends iso2709_record { '949', // Libermedia ]; - private $id_profil; // Id du profil de données pour le fichier chargé - private $profil_unimarc; // Instance du profil unimarc pour optimiser - private $type_doc_force; // Type de document forcé dans maj_auto - private $indexation; // Instance de la classe d'indexation - protected $profil; // Structure des valeurs du profil en cours - private $copyright; // Mots clefs pour les notices non libres de droits (801$b) - private $sigb; // Pour traitements specifiques - private $champs_forces; // Liste des champs forcés - private $ean345; // Reconnaissance des ean par la zone 345$b - private $regles_sections_genres; // Règles de reconnaissance des sections et des genres - private $id_genre_documentaire; // Identifiant pour le genre "documentaire" - private $controle_codes_barres; // Exception de filtrage des codes-barres - - - public function __construct() { + private $id_profil; // Id du profil de données pour le fichier chargé + private $profil_unimarc; // Instance du profil unimarc pour optimiser + private $type_doc_force; // Type de document forcé dans maj_auto + private $indexation; // Instance de la classe d'indexation + protected $profil; // Structure des valeurs du profil en cours + private $copyright; // Mots clefs pour les notices non libres de droits (801$b) + private $sigb; // Pour traitements specifiques + private $champs_forces; // Liste des champs forcés + private $ean345; // Reconnaissance des ean par la zone 345$b + private $regles_sections_genres; // Règles de reconnaissance des sections et des genres + private $id_genre_documentaire; // Identifiant pour le genre "documentaire" + private $controle_codes_barres; // Exception de filtrage des codes-barres + protected $_id_bib; // Bibliotheque d'intégration + + + public function __construct($id_bib=null) { + $this->_id_bib = $id_bib; $this->profil_unimarc = new profil_donnees(); $this->indexation = indexation::getInstance(); $data = getVariable('non_exportable'); @@ -815,7 +817,7 @@ class notice_unimarc extends iso2709_record { if ($this->controle_codes_barres == 1) return utf8_encode(addslashes($code_barres)); - $cab = substr(trim($code_barres), 0, 20); + $cab = trim($code_barres); if (is_numeric($code_barres)) return $cab; @@ -1266,28 +1268,10 @@ class notice_unimarc extends iso2709_record { } - protected function _createThesauriFromLabels($labels,$thesaurus) { - $thesauri=[]; - foreach($labels as $label) { - $thesauri[] = $thesaurus->getOrCreateChild(strtoupper($label), - $label); - } - return $thesauri; - } - protected function _findOtherThesauri() { - $thesauri = []; - - $thesauri_definitions = Class_CodifThesaurus::findAllBy(['rules not' => null]); - foreach($thesauri_definitions as $thesaurus) { - $labels = $thesaurus->withLabelRulesDo( - function($field, $subfield) { - return $this->get_subfield($field, $subfield); - }); - $thesauri=array_merge($thesauri,$this->_createThesauriFromLabels($labels,$thesaurus)); - } - return $thesauri; + return (new Class_Cosmogramme_Integration_Record_BibliographicDynamicFacets()) + ->thesauriOf($this, Class_IntBib::find($this->_id_bib)); } diff --git a/cosmogramme/php/integre_fichiers_attente.php b/cosmogramme/php/integre_fichiers_attente.php deleted file mode 100644 index 25a53e325eb27e8d2e303380a230b639f82e9b75..0000000000000000000000000000000000000000 --- a/cosmogramme/php/integre_fichiers_attente.php +++ /dev/null @@ -1,124 +0,0 @@ -<?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 - */ -//////////////////////////////////////////////////////////////////////////////////////////// -// AFFICHAGE DES FICHIERS EN ATTENTE -//////////////////////////////////////////////////////////////////////////////////////////// -include("_init_frame.php"); -require_once("classe_maj_auto.php"); -$cls_maj_auto=new maj_auto(); - -// ---------------------------------------------------------------- -// SUPPRESSION -// ---------------------------------------------------------------- -if($_REQUEST["action"] == "SUPPRIMER") -{ - unlink($_REQUEST["fichier"]); -} - -// ---------------------------------------------------------------- -// LISTE -// ---------------------------------------------------------------- -print('<h1>Fichiers en attente d\'intégration</h1>'); - -// Parser le repertoire ftp -$path=getVariable("ftp_path"); -if(strRight($path,1) != "/") $path.="/"; -$dir = opendir($path) or AfficherErreur("Impossible d'ouvrir le dossier des transferts (variable ftp_path) : " .$path); -while (($file = readdir($dir)) !== false) -{ - if(is_dir($path.$file) and $file !="test" and substr($file,0,1) != ".") $dossier[]["nom"]=$file; -} -closedir($dir); -if(!$dossier) AfficherErreur("Il n'y a aucun sous-dossier dans le dossier des transferts."); - -$nb_fic=0; -for($i=0; $i < count($dossier); $i++) -{ - $dir = opendir($path.$dossier[$i]["nom"]); - if($dir == false) continue; - while (($file = readdir($dir)) !== false) - { - if(is_file($path.$dossier[$i]["nom"]."/".$file)) {$dossier[$i]["fichiers"][]=$file; $nb_fic++; } - elseif(substr($file,0,4)=="site") - { - // Sous repertoires pergame - $dir_pergame = opendir($path.$dossier[$i]["nom"]."/".$file); - while (($file_pergame = readdir($dir_pergame)) !== false) - { - if($file_pergame=='test.txt') continue; - if(is_file($path.$dossier[$i]["nom"]."/".$file."/".$file_pergame)) {$dossier[$i]["fichiers"][]=$file."/".$file_pergame; $nb_fic++; } - } - closedir($dir_pergame); - } - } - closedir($dir); -} -if(!$nb_fic) quit("Il n'y a aucun fichier en attente d'intégration"); -else echo BR.'» NB : Vous pouver télécharger un fichier par un click droit sur son nom, puis enregistrer sous'.BR.BR; - -// Affichage -print('<div class="liste"><table>'); -print('<tr>'); -print('<th>Dossier</th>'); -print('<th>Fichier</th>'); -print('<th>Transféré le</th>'); -print('<th>Taille</th>'); -print('<th>Statut</th>'); -print('<th>Suppr.</th>'); -print('</tr>'); - -for($i=0; $i < count($dossier); $i++) -{ - if(! count($dossier[$i]["fichiers"])) continue; - $fic=0; - foreach($dossier[$i]["fichiers"] as $file) - { - $fichier=$path.$dossier[$i]["nom"]."/".$file; - $infos=stat($fichier); - $taille=number_format(($infos["size"] / 1024),0, ',', ' ')." ko"; - $date=date("d-m-Y", $infos["mtime"]); - if($fic > 0) $d=" "; else $d=$dossier[$i]["nom"]; - $suppr=rendUrlImg("suppression.gif", "integre_fichiers_attente.php","action=SUPPRIMER&fichier=".$fichier,"Supprimer ce fichier"); - $controle=$sql->fetchOne("Select count(*) from int_maj_auto where nom_fichier='". $dossier[$i]["nom"]."/".$file ."'"); - if($controle) $statut = '<font color="darkgreen">Programmé</font>'; else $statut = '<font color="red">non programmé</font>'; - - print('<tr>'); - print('<td>'.$d.'</td>'); - print('<td>'.'<a href="'.URL_BASE.getVariable("ftp_path").$dossier[$i]["nom"].'/'.$file.'">'.$file.'</a></td>'); - print('<td align="center">'.$date .'</td>'); - print('<td align="right">'.$taille.'</td>'); - print('<td>'.$statut.'</td>'); - print('<td align="center">'.$suppr.'</td>'); - print('</tr>'); - $fic++; - } -} -print('</div></table>'); -print('</body></html>'); - -function quit($msg) -{ - if($msg) print(BR.BR.'<h3 style="margin-left:30px">'.$msg.'</h3>'); - print('</body></html>'); - exit; -} - -?> \ No newline at end of file diff --git a/cosmogramme/sql/patch/patch_359.php b/cosmogramme/sql/patch/patch_359.php index c0965a34e838b6ab6cd73ab2cb40e38121632210..67b373232e44064a4d75bc7e38c88c14e05a1e12 100644 --- a/cosmogramme/sql/patch/patch_359.php +++ b/cosmogramme/sql/patch/patch_359.php @@ -1,2 +1,2 @@ <?php -(new Class_Migration_CleanSerialArticles())->run(); \ No newline at end of file +(new Class_Migration_CleanSerialArticles())->run(); diff --git a/cosmogramme/sql/patch/patch_362.php b/cosmogramme/sql/patch/patch_362.php index a56677501337231dfff02e9060a83454ecd7b6f0..df34b548f27d8fd2ca24dc1c5865c77bb54b1ec3 100644 --- a/cosmogramme/sql/patch/patch_362.php +++ b/cosmogramme/sql/patch/patch_362.php @@ -1,10 +1,5 @@ <?php $adapter = Zend_Db_Table_Abstract::getDefaultAdapter(); - try { - $adapter->query('alter table codif_auteur add column wikidata_id varchar(255)'); - $adapter->query('alter table codif_auteur add column youtube_channel_id varchar(255)'); - $adapter->query('alter table codif_auteur add column isni varchar(255)'); - $adapter->query('alter table codif_auteur add column ark varchar(255)'); - $adapter->query('alter table codif_auteur add index wikidata_id (wikidata_id)'); + $adapter->query('ALTER TABLE album ADD KEY date_maj (date_maj)'); } catch(Exception $e) {} diff --git a/cosmogramme/sql/patch/patch_363.php b/cosmogramme/sql/patch/patch_363.php new file mode 100644 index 0000000000000000000000000000000000000000..8098c63e90806f3daf532708ca4ab153c59c213f --- /dev/null +++ b/cosmogramme/sql/patch/patch_363.php @@ -0,0 +1,2 @@ +<?php +(new Class_Migration_DynamicFacets())->run(); diff --git a/cosmogramme/sql/patch/patch_364.php b/cosmogramme/sql/patch/patch_364.php new file mode 100644 index 0000000000000000000000000000000000000000..5726d7a178f346f9a10667b64dc047cad78908ef --- /dev/null +++ b/cosmogramme/sql/patch/patch_364.php @@ -0,0 +1,10 @@ +<?php +$adapter = Zend_Db_Table_Abstract::getDefaultAdapter(); + +try { + $adapter->query('ALTER TABLE newsletters ADD articles_ids varchar(255) NULL default NULL'); +} catch(Exception $e) {} + +try { + $adapter->query('ALTER TABLE newsletters ADD articles_categories_ids varchar(255) NULL default NULL'); +} catch(Exception $e) {} diff --git a/cosmogramme/sql/patch/patch_365.php b/cosmogramme/sql/patch/patch_365.php new file mode 100644 index 0000000000000000000000000000000000000000..2fe0a194df255756149cd40ddcf4470b28432b1c --- /dev/null +++ b/cosmogramme/sql/patch/patch_365.php @@ -0,0 +1,2 @@ +<?php +(new Class_Migration_BokehEight)->run(); \ No newline at end of file diff --git a/cosmogramme/sql/patch/patch_366.php b/cosmogramme/sql/patch/patch_366.php new file mode 100644 index 0000000000000000000000000000000000000000..a56677501337231dfff02e9060a83454ecd7b6f0 --- /dev/null +++ b/cosmogramme/sql/patch/patch_366.php @@ -0,0 +1,10 @@ +<?php +$adapter = Zend_Db_Table_Abstract::getDefaultAdapter(); + +try { + $adapter->query('alter table codif_auteur add column wikidata_id varchar(255)'); + $adapter->query('alter table codif_auteur add column youtube_channel_id varchar(255)'); + $adapter->query('alter table codif_auteur add column isni varchar(255)'); + $adapter->query('alter table codif_auteur add column ark varchar(255)'); + $adapter->query('alter table codif_auteur add index wikidata_id (wikidata_id)'); +} catch(Exception $e) {} diff --git a/cosmogramme/tests/php/classes/CdScriptIntegrationTest.php b/cosmogramme/tests/php/classes/CdScriptIntegrationTest.php index 2bf34a8fd62201f097152436fb9dc6d3cb36f8ad..0dbdc54effaab6a82d65201ba0154efc453a39bb 100644 --- a/cosmogramme/tests/php/classes/CdScriptIntegrationTest.php +++ b/cosmogramme/tests/php/classes/CdScriptIntegrationTest.php @@ -53,4 +53,24 @@ class CdScriptIntegrationLeKiosqueTest extends CdScriptIntegrationTestCase { public function resumeShouldContainsDecoMagazineAndRevue() { $this->assertEquals("Revue trimestrielle qui allie l'architecture à la décoration et se veut une publication de référence, d'information et d'orientation.", $this->_deco_magazine->getResume()); } -} \ No newline at end of file +} + + + +class CdScriptIntegrationStoryPlayrTest extends CdScriptIntegrationTestCase { + + protected $_record; + + + public function setUp() { + parent::setUp(); + $this->loadRecordsFromFile('unimarc_storyplayr'); + $this->_record = Class_Notice::find(1); + } + + + /** @test */ + public function barCodeShouldBeLonguerThan20Chars() { + $this->assertEquals('d2e2da3c-d88d-4c0e-b109-9c1e429b4b64', $this->_record->getFirstExemplaire()->getCodeBarres()); + } +} diff --git a/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php b/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php index a92c6c5b06207eaf2b64bd27c318de94b2ae4c8b..effbfc65605f2459116b6bbd8f849724855647c7 100644 --- a/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php +++ b/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php @@ -134,6 +134,43 @@ class KohaRecordIntegrationFacetPresseTest extends KohaRecordIntegrationTestCase public function setUp() { parent::setUp(); + $this->fixture('Class_CodifThesaurus', + ['id' => 1, + 'libelle' => 'Année de publication', + 'id_thesaurus' => 'ANNE', + 'id_origine' => null, + 'code' => 'annee', + 'rule_zone' => '995', + 'rule_label_field' => 'w', + 'rule_label_start_pos' => 1, + 'rule_label_length' => 4 + ]); + + + $this->fixture('Class_CodifThesaurus', + ['id' => 2, + 'libelle' => 'Mois de publication', + 'id_thesaurus' => 'MOIS', + 'id_origine' => null, + 'code' => 'mois', + 'rule_zone' => '995', + 'rule_label_field' => 'w', + 'rule_label_start_pos' => 6, + 'rule_label_length' => 2 + ]); + + $this->fixture('Class_CodifThesaurus', + ['id' => 3, + 'libelle' => 'Jour de publication', + 'id_thesaurus' => 'JOUR', + 'id_origine' => null, + 'code' => 'jour', + 'rule_zone' => '995', + 'rule_label_field' => 'w', + 'rule_label_start_pos' => 9, + 'rule_label_length' => 2 + ]); + Class_CosmoVar::setValueOf('mode_doublon', '1'); $this->loadNotice('unimarc_koha_okapi'); @@ -147,14 +184,52 @@ class KohaRecordIntegrationFacetPresseTest extends KohaRecordIntegrationTestCase /** @test */ - public function facettesShouldContainsT2() { - $this->assertEquals('Lfre T2 B1 YMEDSTMAR', + public function thesaurusAnne001ShouldHaveIdOrigine2014() { + $this->assertEquals('2014', + Class_CodifThesaurus::findFirstBy(['id_thesaurus' => 'ANNE0001'])->getIdOrigine()); + } + + + /** @test */ + public function thesaurusMois0001ShouldHaveIdOrigine09() { + $this->assertEquals('06', + Class_CodifThesaurus::findFirstBy(['id_thesaurus' => 'MOIS0001'])->getIdOrigine()); + } + + + /** @test */ + public function thesaurusJour0001ShouldHaveIdOrigine09() { + $this->assertEquals('03', + Class_CodifThesaurus::findFirstBy(['id_thesaurus' => 'JOUR0001'])->getIdOrigine()); + } + + + /** @test */ + public function thesaurusAnne001ShouldHaveLabel2014() { + $this->assertEquals('2014', + Class_CodifThesaurus::findFirstBy(['id_thesaurus' => 'ANNE0001'])->getLibelle()); + } + + + + /** @test */ + public function facettesShouldContainsT2AndHANNE0001AndHMOIS0001AndJOUR0001() { + $this->assertEquals('HANNE0001 HMOIS0001 HJOUR0001 Lfre T2 B1 YMEDSTMAR', Class_Notice::find(1) ->updateFacetsFromExemplaires() ->getFacettes()); } + /** @test */ + public function facettesForRecord25ShouldContainsT2AndHANNE0001AndHMOIS0001() { + $this->assertEquals('HANNE0001 HMOIS0007 HJOUR0006 Lfre T2 B1 YMEDSTMAR', + Class_Notice::find(25) + ->updateFacetsFromExemplaires() + ->getFacettes()); + } + + /** @test */ public function okapi983ShouldHaveT2Facette() { $okapi_983 = Class_Notice::findFirstBy(['tome_alpha' => '983']); @@ -183,7 +258,8 @@ class KohaRecordIntegrationVagabondWithThesaurusOn702DollarATest extends KohaRec 'id_thesaurus' => 'AUTH', 'id_origine' => null, 'code' => 'authors', - 'rules' => '{"label":"702$a"}']); + 'rule_zone' => '702', + 'rule_label_field' => 'a']); $marcel = $this->fixture('Class_CodifThesaurus', @@ -201,7 +277,8 @@ class KohaRecordIntegrationVagabondWithThesaurusOn702DollarATest extends KohaRec 'id_thesaurus' => 'DOCU', 'id_origine' => null, 'code' => 'document', - 'rules' => '{"label":" 99$t "}']); + 'rule_zone' => '099', + 'rule_label_field' => 't']); $this->fixture('Class_CodifThesaurus', ['id' => 4, @@ -209,7 +286,8 @@ class KohaRecordIntegrationVagabondWithThesaurusOn702DollarATest extends KohaRec 'id_thesaurus' => 'SUMM', 'id_origine' => null, 'code' => 'summary', - 'rules' => '{"label":" 200$g "}']); + 'rule_zone' => '200', + 'rule_label_field' => 'g']); $this->fixture('Class_CodifThesaurus', ['id' => 5, @@ -225,7 +303,8 @@ class KohaRecordIntegrationVagabondWithThesaurusOn702DollarATest extends KohaRec 'id_thesaurus' => 'TEST', 'id_origine' => null, 'code' => 'TEST', - 'rules' => '{"label":"610$a"}']); + 'rule_zone' => '610', + 'rule_label_field' => 'a']); $loader = $this->onLoaderOfModel('Class_CodifThesaurus'); $loader @@ -352,6 +431,7 @@ class KohaRecordIntegrationVagabondWithTooMany610aTest extends KohaRecordIntegra 'code' => 'TEST', 'rules' => '{"label":"610$a"}']); + $this->fixture('Class_CodifThesaurus', ['id_thesaurus' => 'TEST9999', 'id_origine' => 'RIME', diff --git a/cosmogramme/tests/php/classes/unimarc_storyplayr.txt b/cosmogramme/tests/php/classes/unimarc_storyplayr.txt new file mode 100644 index 0000000000000000000000000000000000000000..3e5a159698b97e2b702dfdf01da1b41f50e008ea --- /dev/null +++ b/cosmogramme/tests/php/classes/unimarc_storyplayr.txt @@ -0,0 +1,51 @@ +01092nqm1 2200313 i 450 001003700000100002900037101000800066200006400074210003100138330005500169608001400224608001300238608001800251608001400269608001200283608001800295608001100313608002200324608001900346608001500365608001600380608002900396700001800425700001800443801001500461856010600476856013800582995005800720d2e2da3c-d88d-4c0e-b109-9c1e429b4b64 ad |0fre|01 ||||ba afre aAlice's Adventures in Wonderland - A Most Unusual Tea Party cFlowerpot Children's press aAlice is a CURIOUS girl who has many adventures... aAdventure aClassics aEarly readers aEncounter aEnglish aMagical world aRabbit aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aLewis Carroll aGeorge Bridge bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/d2e2da3c-d88d-4c0e-b109-9c1e429b4b64/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/alice-s-adventures-in-wonderland-a-most-unusual-tea-party/playr astoryplayrbstofd2e2da3c-d88d-4c0e-b109-9c1e429b4b6401369nqm1 2200361 i 450 001003700000100002900037101000800066200001100074210001300085330028400098608001500382608001200397608001700409608001000426608002100436608001100457608000900468608001400477608002200491608001900513608001500532608001600547608002900563608001500592608001700607608002300624700001800647700002900665801001500694856010600709856013400815995005800949D2DA8F36-601B-41DC-8CF0-2110C5D37284 ad |0fre|01 ||||ba afre aAnisia cKilowatt aAnisia, vient de quitter sa grand-mère et son village en Angola pour venir en France avec ses parents et son petit frère. +Tout est nouveau, tout est différent quand on change de pays... +Heureusement, en allant à l?école, Anisia va rencontrer Mariette et sa nouvelle maîtresse. a5 ans et + aAfrique aDéménagement aEcole aEcriture cursive aFrance aPeur aProblèmes aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aPauline Comis aMarion Le Hir de Fallois bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/D2DA8F36-601B-41DC-8CF0-2110C5D37284/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/anisia/playr/narration/15fe8914-a036-462f-a58a-783a97f02adc astoryplayrbstofD2DA8F36-601B-41DC-8CF0-2110C5D3728401433nqm1 2200433 i 450 001003700000100002900037101000800066200002000074210001400094330025800108608001400366608001200380608000900392608000800401608001400409608000800423608001300431608001400444608001200458608001500470608001300485608001700498608001700515608001100532608001400543608002000557608001700577608001500594608002200609608001900631608001500650608001600665608002900681700001400710801001500724856010600739856009600845995005800941311092ad-f11e-42ba-95ee-609a6074140e ad |0fre|01 ||||ba afre aA blossom story cVipo Land aIndians send little blossom boats floating down the Ganges for good luck and to make their wishes come true. These vessels are often richly decorated with blossoms, incense sticks, coins, food, and lit candles. + +© 2010 VIPO Land Inc all rights reserved. aAdventure aAnimals aBird aCat aDiscovery aDog aElephant aEncounter aEnglish aFriendship aLearning aMiddle grade aMisadventure aRescue aTraveling aVipo in english aWild Animals akamishibaï aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aIdo Angel bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/311092ad-f11e-42ba-95ee-609a6074140e/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/a-blossom-story/playr astoryplayrbstof311092ad-f11e-42ba-95ee-609a6074140e01884nqm1 2200397 i 450 0010037000001000029000371010008000662000018000742100025000923300689001176080018008066080015008246080027008396080017008666080012008836080012008956080013009076080012009206080019009326080011009516080010009626080022009726080019009946080015010136080016010286080029010446080015010736080017010886080023011057000020011287000018011488010015011668560106011818560141012879950058014284F57F220-8BBF-4846-A5EC-1E69373DF392 ad |0fre|01 ||||ba afre a38 perroquets cPoints de suspension aDevant le singe émerveillé, le boa prend la décision de se mesurer. +Le singe propose de l?aider : Plies-toi en deux puis en quatre, c?est simple, ta taille est égale à deux fois ta moitié ou à quatre fois la moitié de ta moitié. +Le boa n?est pas satisfait, il se sent entier et non pas moitié. +Entrent en scène l?éléphanteau plutôt débonnaire et le perroquet très sûr de lui. +Pour mesurer un boa, dit-il, il faut commencer par la queue. +Mais ne voyant plus la tête, le doute s?empare des trois animaux : et si le boa était déchiré ? +Alerté par des sensations bizarres, le boa vient rappeler à ses amis qu?il désire être mesuré et non vérifié. +Le perroquet a alors une idée lumineuse? a4 personnages a5 ans et + aA raconter à plusieurs aAlbums longs aAnimaux aCompter aEléphant aGrandir aGrands-parents aOiseau aSinge aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aSamuel Ribeyron aGrigori Oster bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/4F57F220-8BBF-4846-A5EC-1E69373DF392/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/38-perroquets/playr/narration/B4006333-3151-4A11-BB9A-AB2AB4BD4109 astoryplayrbstof4F57F220-8BBF-4846-A5EC-1E69373DF39201325nqm1 2200361 i 450 00100370000010000290003710100080006620000370007421000480011133001720015960800180033160800150034960800270036460800110039160800210040260800120042360800120043560800100044760800110045760800280046860800090049660800120050560800220051760800190053960800150055860800160057360800290058970000530061880100150067185601060068685601130079299500580090531230bd4-4e7c-46b7-a891-4035bfff83e1 ad |0fre|01 ||||ba afre aAmies jusqu?au bout des feuilles cFédération des oeuvres laïques de l'Ardèche aVivez l'aventure de Bouche Rouge, la châtaigne, et de Reinette, la pomme, qui, après un coup de vent, se retrouvent à la merci des humains ! Une rencontre automnale... a2 personnages a5 ans et + aA raconter à plusieurs aAmitié aAnimaux sauvages aAutomne aCuisine aForêt aManger aNature et environnement aPeur aSaisons aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aEcole publique de Vernosc-lès-Annonay & Juliet C bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/31230bd4-4e7c-46b7-a891-4035bfff83e1/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/amies-jusqu-au-bout-des-feuilles/playr astoryplayrbstof31230bd4-4e7c-46b7-a891-4035bfff83e101472nqm1 2200457 i 450 00100370000010000290003710100080006620000230007421000330009733001340013060800150026460800180027960800270029760800110032460800120033560800110034760800210035860800200037960800130039960800170041260800090042960800120043860800160045060800100046660800100047660800110048660800220049760800190051960800150053860800160055360800290056960800150059860800170061360800230063070000190065370000170067280100150068985601060070485601460081099500580095642d0e076-14e9-4178-946a-203bfa315ab6 ad |0fre|01 ||||ba afre a3 petites culottes cL'Atelier du Poisson Soluble aHorreur ! +Un matin, Jacquotte, Charlotte et la Grabote ne retrouvent plus leurs culottes ! +Un drame à vous donner les chocottes ! a3 ans et + a4 personnages aA raconter à plusieurs aAmitié aAnimaux aCochon aCollage, montage aConte-randonnée aCouleurs aFrère, soeur aLoup aMystère aMésaventure aQuête aRimes aTricot aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aSylvie Chausse aAnne Letuffe bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/42d0e076-14e9-4178-946a-203bfa315ab6/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/3-petites-culottes/playr/narration/52943f9b-6395-4e7a-a0ad-f0d98b0cd6c1 astoryplayrbstof42d0e076-14e9-4178-946a-203bfa315ab601300nqm1 2200337 i 450 00100370000010000290003710100080006620000300007421000140010433002480011860800150036660800110038160800120039260800120040460800110041660800100042760800220043760800190045960800150047860800160049360800290050960800150053860800170055360800230057070000170059370000200061080100150063085601060064585601530075199500580090454E91483-2A1D-40B3-8BA8-E5CBE1B44E66 ad |0fre|01 ||||ba afre aAdala et son petit violon cLirabelle aAdala aime beaucoup le violon. +Alors papa et maman lui ont offert un violon pour son anniversaire. +Un tout petit violon, à sa taille. +C?est une invitation au voyage. Un voyage musical et éducatif à la découverte d?un instrument : le violon. a5 ans et + aCadeau aFamille aMusique aPoésie aRimes aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aEvelyne Mary aStéphanie Joire bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/54E91483-2A1D-40B3-8BA8-E5CBE1B44E66/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/adala-et-son-petit-violon/playr/narration/d0b31ad4-e88b-46ef-b67d-553f20e72cc2 astoryplayrbstof54E91483-2A1D-40B3-8BA8-E5CBE1B44E6601558nqm1 2200433 i 450 001003700000100002900037101000800066200002600074210001700100330026900117608001500386608001800401608002700419608001200446608002000458608001400478608001500492608001100507608001500518608001100533608000900544608001000553608001200563608002100575608002200596608001900618608001500637608001600652608002900668608001500697608001700712608002300729700002500752700001900777801001500796856010600811856014900917995005801066AC4BF703-19F8-41FA-8A4C-2EB8C9E50797 ad |0fre|01 ||||ba afre aA l'heure du déjeuner cCallicéphale aLe crapaud à trois taches attend, immobile, au milieu de l'étang. C'est qu'il a faim. Une faim de loup ! Et ça, c'est énorme pour un crapaud. Quel mets assez raffiné sera digne de son palais délicat ? +Une histoire drôle où la chute ne laisse personne sur sa faim. a5 ans et + a6 personnages aA raconter à plusieurs aAnimaux aConte-randonnée aCrocodile aGrenouille aHumour aKamishibaï aManger aMare aQuête aReptile aTel est pris ... aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aFlorence Jenner-Metz aMarie Dorléans bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/AC4BF703-19F8-41FA-8A4C-2EB8C9E50797/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/a-l-heure-du-dejeuner/playr/narration/2C61EABE-6005-47AC-A58A-6E81ACFCDDAA astoryplayrbstofAC4BF703-19F8-41FA-8A4C-2EB8C9E5079701653nqm1 2200445 i 450 0010037000001000029000371010008000662000033000742100026001073300335001336080015004686080017004836080033005006080013005336080009005466080015005556080010005706080010005806080016005906080016006066080010006226080014006326080009006466080015006556080011006706080022006816080019007036080015007226080016007376080029007536080015007826080017007976080023008147000017008377000018008548010015008728560106008878560156009939950058011490ae5c48a-22b4-48d5-a3f0-94e73dcbef8d ad |0fre|01 ||||ba afre aAlice au pays des merveilles cMarie Comont éditions aAlice commence sérieusement à s'ennuyer assise auprès de sa soeur. + +Soudain un lapin blanc vêtu d'une redingote et tenant dans sa patte une montre à gousset passe près d'elle. Poussée par la curiosité, Alice le poursuit jusque dans son terrier où elle fait une chute vertigineuse pour finalement atterrir au Pays des Merveilles... a5 ans et + aAlbums longs aAlice au pays des merveilles aAventure aChat aClassiques aEnnui aLapin aLittérature aMésaventure aReine aRencontre aRêve aSurnaturel aVoyage aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aMarie Comont aLewis Carroll bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/0ae5c48a-22b4-48d5-a3f0-94e73dcbef8d/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/alice-au-pays-des-merveilles/playr/narration/B4033828-53E8-49F0-A872-40248133552B astoryplayrbstof0ae5c48a-22b4-48d5-a3f0-94e73dcbef8d01138nqm1 2200349 i 450 001003700000100002900037101000800066200001500074210003300089330006200122608001800184608001500202608001500217608001200232608001400244608001100258608000900269608001100278608002200289608001900311608001500330608001600345608002900361608001500390608001700405608002300422700002600445801001500471856010600486856013800592995005800730f5e78e1f-cd36-4b9a-9f60-8db53bd4977e ad |0fre|01 ||||ba afre aAlpha Bêta cL'Atelier du Poisson Soluble aAlpa Bêta, un abécédaire narratif, didactique et comique. a2 personnages a3 ans et + aAbécédaire aAnimaux aApprendre aHumour aMots aRenard aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aGuillaume Bracquemond bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/f5e78e1f-cd36-4b9a-9f60-8db53bd4977e/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/alpha-beta/playr/narration/11409297-8fc1-44ca-bfff-959ec75cee21 astoryplayrbstoff5e78e1f-cd36-4b9a-9f60-8db53bd4977e01248nqm1 2200349 i 450 00100370000010000290003710100080006620000320007421000250010633001390013160800150027060800120028560800120029760800200030960800130032960800130034260800280035560800100038360800220039360800190041560800150043460800160044960800290046560800150049460800170050960800230052670000190054980100150056885601060058385601510068999500580084017fcdd4f-0c1c-4515-a0cf-594f41b03550 ad |0fre|01 ||||ba afre a10 moutons 9 dinosaures ... cPoints de suspension aUn livre pour compter à rebours de 10 à 1, toutes sortes d?animaux qui, si nous n?y prenons pas garde, un jour pourraient disparaître. a3 ans et + aAnimaux aCompter aConte-randonnée aCouleurs aEcologie aNature et environnement aRimes aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aMaria Jalibert bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/17fcdd4f-0c1c-4515-a0cf-594f41b03550/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/10-moutons-9-dinosaures/playr/narration/d52b0094-8c51-4093-b437-ed88aed0de5d astoryplayrbstof17fcdd4f-0c1c-4515-a0cf-594f41b0355001332nqm1 2200337 i 450 0010037000001000029000371010008000662000027000742100014001013300294001156080015004096080009004246080010004336080016004436080010004596080010004696080010004796080022004896080019005116080015005306080016005456080029005616080015005906080017006056080023006227000020006458010015006658560106006808560150007869950058009362B885DB8-7DC3-42F7-889B-B214216CF659 ad |0fre|01 ||||ba afre aA la recherche de Maru cLirabelle aSuivons Takeru, un jeune garçon, en cette fin d'été au Japon. Chaleur, moiteur, pesanteur : un typhon approche alors que Takeru est parti à la recherche de son chien? +Kumiko Yamamoto a été sélectionnée pour l'exposition d'illustrateurs de la Foire du Livre pour Enfants de Bologne en 2003. a5 ans et + aAsie aChien aDisparition aJapon aPluie aQuête aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aKumiko Yamamoto bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/2B885DB8-7DC3-42F7-889B-B214216CF659/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/a-la-recherche-de-maru/playr/narration/191f301d-38e4-4c7f-9d90-38f2d3742812 astoryplayrbstof2B885DB8-7DC3-42F7-889B-B214216CF65901271nqm1 2200361 i 450 00100370000010000290003710100080006620000370007421000310011133001120014260800140025460800130026860800180028160800120029960800300031160800100034160800160035160800110036760800220037860800190040060800150041960800160043460800290045060800150047960800170049460800230051170000170053470000200055180100150057185601060058685601590069299500580085139a2946b-ee50-4856-a1ad-24b1161c2a7d ad |0fre|01 ||||ba afre a'Twas the Night Before Christmas cFlowerpot Children's press a?Twas the night before Christmas, +when all through the house +Not a creature was stirring, +not even a mouse aChristmas aClassics aEarly readers aEnglish aFamily Christmas Classics aNight aSanta Claus aWinter aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aCK Dreamaker aClement C.Moore bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/39a2946b-ee50-4856-a1ad-24b1161c2a7d/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/twas-the-night-before-christmas/playr/narration/1ae58c69-df67-494f-b4cb-271a52e31753 astoryplayrbstof39a2946b-ee50-4856-a1ad-24b1161c2a7d01374nqm1 2200385 i 450 0010037000001000029000371010008000662000028000742100013001023300222001156080015003376080010003526080009003626080009003716080012003806080013003926080010004056080010004156080014004256080022004396080019004616080015004806080016004956080029005116080015005406080017005556080023005727000026005957000016006217000021006378010015006588560106006738560151007799950058009304e0bd9da-2c4f-4d46-9252-f0a3a8d7cf47 ad |0fre|01 ||||ba afre aAlexandre a trop grandi cUtopique aMadame Chat vient d'avoir un bébé et Madame Lapin est en admiration devant ce tout-petit qu'elle trouve tellement mignon ! Alexandre observe sa maman prendre le bébé dans ses bras et il en éprouve beaucoup de peine... a3 ans et + aAmour aBébé aChat aGrandir aJalousie aLapin aMaman aTristesse aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aCaroline Lechevallier aDidier Jean aAmandine Alézard bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/4e0bd9da-2c4f-4d46-9252-f0a3a8d7cf47/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/alexandre-a-trop-grandi/playr/narration/2e21909d-99fe-492b-9d25-8903b86ee2b1 astoryplayrbstof4e0bd9da-2c4f-4d46-9252-f0a3a8d7cf4701314nqm1 2200373 i 450 00100370000010000290003710100080006620000260007421000330010033001570013360800150029060800100030560800090031560800190032460800120034360800180035560800160037360800100038960800220039960800220042160800190044360800150046260800160047760800290049360800150052260800170053760800230055470000160057770000190059380100150061285601060062785601490073399500580088209c29406-eeca-4cc6-96b7-c826f26dd954 ad |0fre|01 ||||ba afre aAngèle et le Cerisier cL'Atelier du Poisson Soluble a<p><span style="color: rgb(61, 61, 61);">Angèle est une vieille dame qui aime se raconter des histoires. Des histoires pour elle toute seule.</span></p> a5 ans et + aArbre aChat aCoups de coeur aEnfance aGrand-parents aImagination aVieux anarration récente aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aTeresa Lima aRaphaële Frier bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/09c29406-eeca-4cc6-96b7-c826f26dd954/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/angele-et-le-cerisier/playr/narration/c512bf7b-18b6-45a3-8042-2d70047e97e0 astoryplayrbstof09c29406-eeca-4cc6-96b7-c826f26dd95401271nqm1 2200361 i 450 0010037000001000029000371010008000662000033000742100013001073300194001206080015003146080017003296080026003466080023003726080016003956080011004116080009004226080011004316080011004426080009004536080011004626080022004736080019004956080015005146080016005296080029005457000021005747000026005958010015006218560106006368560109007429950058008513f1dc01d-0088-440d-8e44-37e41c01a680 ad |0fre|01 ||||ba afre aAlzabane l'oiseau de la Lune cAlzabane aAu temps des Origines, la Terre n'était encore qu'une vaste sphère bleutée et vaporeuse, gonflée d'air et zebrée de nuages aux mille couleurs. Elle n'était peuplée que d'oiseaux étranges... a7 ans et + aAlbums longs aComment c'était avant aCréatures étranges aDisparition aEspace aLune aOiseau aPoésie aRêve aVoyage aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aFernando Falcone aJean-Sébastien Blanck bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/3f1dc01d-0088-440d-8e44-37e41c01a680/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/alzabane-l-oiseau-de-la-lune/playr astoryplayrbstof3f1dc01d-0088-440d-8e44-37e41c01a68001379nqm1 2200397 i 450 00100370000010000290003710100080006620000100007421000130008433002430009760800150034060800330035560800130038860800090040160800150041060800330042560800100045860800160046860800160048460800200050060800090052060800150052960800110054460800220055560800190057760800150059660800160061160800290062770000190065670000230067570000180069880100150071685601060073185600860083799500580092330bd742f-c3d1-4773-993f-39affaf7d356 ad |0fre|01 ||||ba afre aAlice cAmaterra aAlice re?vassait dans un champ d?herbes folles lorsqu?un Lapin Blanc, fort bien ve?tu, passa en courant. Pre?s d?une haie, il marqua un arre?t, tira une montre de sa poche et regarda l?heure, avant de s?engouffrer dans un e?norme terrier. a7 ans et + aAlice au pays des merveilles aAventure aChat aClassiques aCollection Les grands textes aLapin aLittérature aMésaventure aPremiers romans aRêve aSurnaturel aVoyage aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aSylvie Misslin aSébastien Mourrain aLewis Carroll bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/30bd742f-c3d1-4773-993f-39affaf7d356/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/alice/playr astoryplayrbstof30bd742f-c3d1-4773-993f-39affaf7d35601492nqm1 2200337 i 450 00100370000010000290003710100080006620000310007421000250010533004100013060800150054060800110055560800280056660800110059460800090060560800100061460800220062460800190064660800150066560800160068060800290069660800150072560800170074060800230075770000190078070000240079980100150082385601060083885601520094499500580109634395C06-BA98-4AB8-A852-A3CAF56DF161 ad |0fre|01 ||||ba afre aA quoi rêve un pissenlit ? cPoints de suspension aUn pissenlit dans la ville Entouré d?immenses murs gris Se sent tout petit, petit. Alors la nuit, Quand tout le monde dort il rêve d?être tournesol. Éloge poétique au gré des saisons et des ambitions de cette petite fleur bien souvent méprisée dont la beauté n?échappe pas aux enfants. Souvenez-vous du premier bouquet que vous a offert votre petit(e) et de l?irrésistible envie de souffler les aigrettes. a5 ans et + aFleurs aNature et environnement aPoésie aVent aVille aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aLydie Sabourin aAlice Brière-Haquet bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/34395C06-BA98-4AB8-A852-A3CAF56DF161/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/a-quoi-reve-un-pissenlit/playr/narration/0d4b2b32-5386-4a68-a132-c6f98e457d5c astoryplayrbstof34395C06-BA98-4AB8-A852-A3CAF56DF16101347nqm1 2200397 i 450 001003700000100002900037101000800066200001200074210003300086330020200119608001500321608001300336608001100349608001100360608001000371608001000381608000900391608001200400608001400412608001300426608001900439608001100458608002200469608001900491608001500510608001600525608002900541608001500570608001700585608002300602700001000625801001500635856010600650856013500756995005800891cf9550ce-29ed-4f19-93aa-943e84a5e26f ad |0fre|01 ||||ba afre aAu fait cL'Atelier du Poisson Soluble aAtraboule se demande ce qu'il va faire aujourd'hui. +Déjeuner chez sa cousine Louise ? +Aller chez le dentiste ? +Passer au bureau ? Repasser à la maison ? +Non, rien de tout ça. Il ira chasser l'ours. a5 ans et + aAventure aChasse aHumour aLapin aMagie aOurs aPoisson aRencontre aSorcière aTransformation aVoyage aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aFinzo bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/cf9550ce-29ed-4f19-93aa-943e84a5e26f/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/au-fait/playr/narration/8a77b0a5-71af-4747-8808-a9ddcbf44736 astoryplayrbstofcf9550ce-29ed-4f19-93aa-943e84a5e26f01181nqm1 2200373 i 450 00100370000010000290003710100080006620000200007421000140009433001380010860800120024660800090025860800080026760800140027560800080028960800140029760800120031160800150032360800130033860800170035160800140036860800200038260800150040260800220041760800190043960800150045860800160047360800290048970000140051880100150053285601060054785600960065399500580074922e61681-f54e-48d3-9a2c-f62634e3ec61 ad |0fre|01 ||||ba afre aAnimal Olympics cVipo Land aThe ?mythology? of ancient Greece tells lots of stories and legends about gods and heroes. + +© 2010 VIPO Land Inc all rights reserved. aAnimals aBird aCat aDiscovery aDog aEncounter aEnglish aFriendship aLearning aMiddle grade aTraveling aVipo in english akamishibaï aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aIdo Angel bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/22e61681-f54e-48d3-9a2c-f62634e3ec61/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/animal-olympics/playr astoryplayrbstof22e61681-f54e-48d3-9a2c-f62634e3ec6101291nqm1 2200397 i 450 001003700000100002900037101000800066200002400074210001400098330018800112608001200300608000900312608000800321608001400329608000800343608001400351608001200365608001500377608001300392608001700405608001700422608001100439608001400450608002000464608001500484608002200499608001900521608001500540608001600555608002900571700001400600801001500614856010600629856010000735995005800835c576096a-1a2b-4625-a990-e5d7f0a9f4d6 ad |0fre|01 ||||ba afre aA postcard for Vipo cVipo Land aNo country in the world grows more tulips than Holland. Particularly in spring, the country is awash with almost every colour you can image. + +© 2010 VIPO Land Inc all rights reserved. aAnimals aBird aCat aDiscovery aDog aEncounter aEnglish aFriendship aLearning aMiddle grade aMisadventure aRescue aTraveling aVipo in english akamishibaï aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aIdo Angel bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/c576096a-1a2b-4625-a990-e5d7f0a9f4d6/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/a-postcard-for-vipo/playr astoryplayrbstofc576096a-1a2b-4625-a990-e5d7f0a9f4d601317nqm1 2200373 i 450 0010037000001000029000371010008000662000020000742100025000943300176001196080015002956080012003106080024003226080021003466080013003676080014003806080011003946080012004056080028004176080010004456080022004556080019004776080015004966080016005116080029005276080015005566080017005716080023005887000012006118010015006238560106006388560141007449950058008850b170079-df13-4f83-ab6b-6b6273c870ca ad |0fre|01 ||||ba afre aAnimal féroce ? cPoints de suspension aQuel est l?animal le plus féroce ? +Le lion ? Non, non. +Le requin ?non, non, non ! +Alors ?? +Un livre pour comprendre que dans la vie, tout +est une question de point de vue. a3 ans et + aAnimaux aAnimaux de la ferme aAnimaux sauvages aCouleurs aDevinette aHumour aMystère aNature et environnement aPoule aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aDipacho bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/0b170079-df13-4f83-ab6b-6b6273c870ca/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/animal-feroce/playr/narration/14cdc789-8c06-4826-8c76-7946ac295f1f astoryplayrbstof0b170079-df13-4f83-ab6b-6b6273c870ca01318nqm1 2200301 i 450 001003700000100002900037101000800066200003700074210002300111330037900134608001500513608001200528608001200540608001000552608001600562608001400578608001200592608002200604608001900626608001500645608001600660608002900676700001900705801001500724856010600739856011300845995005800958b504fe48-b783-4adb-9540-2c973fd3e25d ad |0fre|01 ||||ba afre aAnnabelle et les cahiers volants cEditions du Jasmin a<p>Annabelle a un gros problème : tous les soirs, ses cahiers s?envolent !</p><p>Mais personne ne veut la croire, et surtout pas la maîtresse?</p><p>Pourquoi est-elle la seule à voir ses feuilles partir vers le ciel ?</p><p>Martine Delerm encourage le lecteur à se laisser porter par son imagination dans cette histoire illustrée avec légèreté et finesse.</p> a7 ans et + aAnimaux aDispute aEcole aImagination aNouveauté aTravail aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aMartine Delerm bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/b504fe48-b783-4adb-9540-2c973fd3e25d/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/annabelle-et-les-cahiers-volants/playr astoryplayrbstofb504fe48-b783-4adb-9540-2c973fd3e25d01102nqm1 2200301 i 450 001003700000100002900037101000800066200003500074210003100109330016100140608000900301608000800310608001800318608000900336608001800345608001800363608002200381608001900403608001500422608001600437608002900453700001600482700001400498801001500512856010600527856010900633995005800742a2d14069-f599-48c1-afbf-d68e5fcb8ee7 ad |0fre|01 ||||ba afre aA Sailor Went to Sea, Sea, Sea cFlowerpot Children's press aA sailor went to sea, sea, sea .. . so what did he see, see, see? Come aboard with a brave young sailor and his kitty cat for an adventure on the high seas! aBoat aCat aEarly readers aFish aNursery Rhyme aSea and ocean aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAsha Pearse aLucy Bell bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/a2d14069-f599-48c1-afbf-d68e5fcb8ee7/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/a-sailor-went-to-sea-sea-sea/playr astoryplayrbstofa2d14069-f599-48c1-afbf-d68e5fcb8ee701741nqm1 2200481 i 450 001003700000100002900037101000800066200003200074210001300106330038800119608001500507608001700522608001100539608001000550608001200560608001000572608001500582608001200597608001100609608001200620608001300632608001000645608000900655608001500664608000900679608002000688608000900708608001100717608002200728608001900750608001500769608001600784608002900800608001500829608001700844608002300861700002400884700001800908801001500926856010600941856015401047995005801201cd4a941b-12b5-4ac6-a707-ed7401198f32 ad |0fre|01 ||||ba afre aArgos le compagnon d'Ulysse cAmaterra aJe suis Argos, le chien d'Ulysse. Mon maître est parti à la guerre il y a bien longtemps. J'étais alors un jeune chien, agile, rapide, prompt à courser lièvres et cerfs. La guerre est finie, et Ulysse n'est pas rentré. Je veille sur Télémaque, son fils, et Pénélope, sa femme. Quelles épreuves retiennent mon maître loin de nous ? Les années passent. Patient et fidèle, je l'attends. a7 ans et + aAlbums longs aAmitié aAmour aAnimaux aChien aClassiques aEnfance aEspoir aFamille aHistoire aJouer aMort aMythologie aNuit aPremiers romans aRêve aUlysse aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aIsabelle Wlodarczyk aAlice Beniero bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/cd4a941b-12b5-4ac6-a707-ed7401198f32/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/argos-le-compagnon-dulysse/playr/narration/68795507-2f26-4479-88e9-53b864f182f8 astoryplayrbstofcd4a941b-12b5-4ac6-a707-ed7401198f3201245nqm1 2200385 i 450 001003700000100002900037101000800066200002100074210003300095330008200128608001500210608001200225608001400237608001200251608001000263608001600273608001000289608002800299608000900327608001200336608001000348608002200358608001900380608001500399608001600414608002900430608001500459608001700474608002300491700002200514801001500536856010600551856014400657995005800801bb269d56-a40d-47b3-9e16-2a8de6bafc41 ad |0fre|01 ||||ba afre aAu fond des bois cL'Atelier du Poisson Soluble a<p>Il était une fois, dans la forêt sombre des contes, une enfant égarée.</p> a3 ans et + aAnimals aApprendre aEnfance aForêt aImagination aMaman aNature et environnement aOurs aParents aPerdu aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aAlessandro Lumare bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/bb269d56-a40d-47b3-9e16-2a8de6bafc41/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/au-fond-des-bois/playr/narration/4e239e3a-b6e7-4139-beae-741ac4981c41 astoryplayrbstofbb269d56-a40d-47b3-9e16-2a8de6bafc4101366nqm1 2200421 i 450 001003700000100002900037101000800066200001800074210002300092330016100115608001500276608001100291608001200302608001000314608001200324608001100336608001000347608001000357608001200367608001100379608001000390608001100400608002200411608002200433608001900455608001500474608001600489608002900505608001500534608001700549608002300566700001500589700002000604801001500624856010600639856014100745995005800886a1778583-780f-4653-8813-b93525933c3a ad |0fre|01 ||||ba afre aAlain et Alex cFanny Joly Numérik a<p>Alain et Alex sont deux voisins très différents l'un de l'autre jusqu'au jour où ils se rencontrent. Comment leur amitié va-t-elle changer leur vie ?</p> a3 ans et + aAmitié aAnimaux aEcole aEnfance aJardin aJouer aLapin aLecture aMaison aMaman aVoisin anarration récente aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aFanny Joly aMeinolf Nitsche bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/a1778583-780f-4653-8813-b93525933c3a/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/alain-et-alex/playr/narration/406e059b-fee4-4d86-83a3-534fded7f4f8 astoryplayrbstofa1778583-780f-4653-8813-b93525933c3a01140nqm1 2200301 i 450 001003700000100002900037101000800066200003300074210003100107330012000138608001800258608001200276608001800288608001000306608002200316608001900338608001500357608001600372608002900388608001500417608001700432608002300449700003100472801001500503856010600518856015600624995005800780096599b6-9242-49d3-bb8a-7c53667244f5 ad |0fre|01 ||||ba afre aAll the Pretty Little Horses cFlowerpot Children's press aHush-a-bye, don?t you cry, Go to sleep my little baby. When you wake, you shall have, All the pretty little horses. aEarly readers aEnglish aNursery Rhyme aSleep aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aFlowerpot Children's Press bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/096599b6-9242-49d3-bb8a-7c53667244f5/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/all-the-pretty-little-horses/playr/narration/1d772326-efa1-4491-92c2-ddc315136102 astoryplayrbstof096599b6-9242-49d3-bb8a-7c53667244f501097nqm1 2200301 i 450 001003700000100002900037101000800066200003100074210003100105330008000136608001200216608002900228608001500257608001400272608002200286608001900308608001500327608001600342608002900358608001500387608001700402608002300419700002000442801001500462856010600477856015400583995005800737979c58f5-2cf8-454f-bb46-84d23d1ca703 ad |0fre|01 ||||ba afre aAll Things Great and Small cFlowerpot Children's press aGod made the world so broad and grand, filled with blessings from His hand. aEnglish aMy First Book of Prayers aPre-school aReligious aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aLisa M Gardiner bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/979c58f5-2cf8-454f-bb46-84d23d1ca703/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/all-things-great-and-small/playr/narration/d710e7c0-ef11-424a-bb5c-8a991f2f68d2 astoryplayrbstof979c58f5-2cf8-454f-bb46-84d23d1ca70301263nqm1 2200313 i 450 001003700000100002900037101000800066200002600074210003100100330022900131608002700360608002000387608001800407608001200425608001400437608002200451608001900473608001500492608001600507608002900523608001500552608001700567608002300584700001400607801001500621856010600636856014900742995005800891278e13dd-1588-4ab2-a894-b5e9b7577a38 ad |0fre|01 ||||ba afre aA Coat of Many Colors cFlowerpot Children's press aJoseph was given a very special coat by his father, which made his brothers jealous?so jealous they sold him into slavery. See how Joseph forgave them, and when he became a ruler of the land, helped and blessed his brothers. a5 Minute Bible Stories aBrother, sister aEarly readers aEnglish aReligious aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aDhanya M. bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/278e13dd-1588-4ab2-a894-b5e9b7577a38/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/a-coat-of-many-colors/playr/narration/0454cec8-b0b4-4975-afaf-2b707fdc712a astoryplayrbstof278e13dd-1588-4ab2-a894-b5e9b7577a3801274nqm1 2200361 i 450 0010037000001000029000371010008000662000024000742100023000983300223001216080015003446080017003596080011003766080010003876080012003976080012004096080017004216080012004386080022004506080020004726080011004926080022005036080019005256080015005446080016005596080029005757000015006047000017006198010015006368560106006518560097007579950058008546e4bb807-89ee-4622-abc6-1757ea502faa ad |0fre|01 ||||ba afre aAttention, Marion ! cFanny Joly Numérik a<p>ROMAN POUR LES 10 ANS ET + + +Pour Marion, avoir un grand frère est une vraie plaie, surtout quand celui-ci lui vole son journal intime pour révéler ses secrets aux yeux de tous, et surtout à ceux du beau Félix...</p> a7 ans et + aAlbums longs aAmitié aAmour aDispute aFamille aFrère, soeur aMaladie aMarion et Charles aPremiers romans aSecret aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aFanny Joly aCatel Muller bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/6e4bb807-89ee-4622-abc6-1757ea502faa/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/attention-marion/playr astoryplayrbstof6e4bb807-89ee-4622-abc6-1757ea502faa01685nqm1 2200445 i 450 001003700000100002900037101000800066200002200074210002200096330038100118608001800499608001500517608002700532608000900559608001300568608002100581608002000602608001100622608001300633608002300646608001000669608001200679608001000691608001400701608001000715608001200725608002200737608001900759608001500778608001600793608002900809608001500838608001700853608002300870700002200893801001500915856010600930856014501036995005801181E0BA5323-3D73-451E-A8B9-EAF391BDEA9C ad |0fre|01 ||||ba afre aAkiko la curieuse cPicquier Jeunesse aAkiko est une petite fille japonaise qui vit au pied du mont Fuji. +Avide de curiosité et d'aventures, elle va, non sans une certaine appréhension, se lancer dans une aventure qui lui apprendra à ne pas faire demi-tour au premier obstacle venu, à défier les dangers, à maîtriser ses peurs. +Elle verra qu'au bout du chemin l'attendent une belle surprise et un immense honneur. a4 personnages a5 ans et + aA raconter à plusieurs aAsie aAventure aCollage, montage aConte-randonnée aContes aCouleurs aCréatures étranges aJapon aMystère aNeige aPrintemps aQuête aSaisons aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aAntoine Guilloppé bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/E0BA5323-3D73-451E-A8B9-EAF391BDEA9C/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/akiko-la-curieuse/playr/narration/03d42cd0-acd8-4818-a516-b54518334d7b astoryplayrbstofE0BA5323-3D73-451E-A8B9-EAF391BDEA9C01407nqm1 2200349 i 450 001003700000100002900037101000800066200002700074210003100101330031300132608001200445608001800457608001100475608001200486608001400498608001000512608001800522608002200540608001900562608001500581608001600596608002900612608001500641608001700656608002300673700001600696700001600712801001500728856010600743856015000849995005800999cd792ed7-f020-41d3-8b63-941f17e2c6f6 ad |0fre|01 ||||ba afre a5 very Little Pumpkins cFlowerpot Children's press aFive very little pumpkins are all heading out to play. It? s October 31st? It?s every pumpkin?s favorite day! Join five adorable little pumpkins on their romp through their neighborhood in this silly rhyming story that celebrates all that is fun about Halloween: great friends, costumes, neighbors and candy! aAnimals aEarly readers aEating aEnglish aHalloween aNight aNursery Rhyme aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aIvana Forgo aHolly Weane bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/cd792ed7-f020-41d3-8b63-941f17e2c6f6/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/5-very-little-pumpkins/playr/narration/cac77d85-1bee-44da-9a26-7f003aebff30 astoryplayrbstofcd792ed7-f020-41d3-8b63-941f17e2c6f601157nqm1 2200289 i 450 001003700000100002900037101000800066200002200074210003100096330023700127608002200364608001400386608001200400608001800412608001300430608001500443608002200458608001900480608001500499608001600514608002900530700003100559801001500590856010600605856009800711995005800809592d6286-c5a8-43aa-a2a2-edb03151937a ad |0fre|01 ||||ba afre a1st Book of Words cFlowerpot Children's press aThe 1st Book of Words series is an ideal learning tool for budding young minds. Every page is filled with vivid, close-up photos of familiar people, places and things, illustrating simple word concepts that expand vocabulary skills. a1st Book of Words a1st Words aEnglish aEveryday life aLearning aPre-school aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aFlowerpot Children's Press bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/592d6286-c5a8-43aa-a2a2-edb03151937a/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/1st-book-of-words/playr astoryplayrbstof592d6286-c5a8-43aa-a2a2-edb03151937a01567nqm1 2200445 i 450 001003700000100002900037101000800066200003300074210003100107330022600138608001500364608003200379608003300411608001200444608001300456608000900469608001500478608001000493608001600503608001600519608001000535608001400545608000900559608001500568608001100583608002200594608001900616608001500635608001600650608002900666608001500695608001700710608002300727700001800750700001600768801001500784856010600799856015800905995005801063c96d33a6-b5e4-43c0-9178-338bad63e53f ad |0fre|01 ||||ba afre aAlice au pays des merveilles cFlowerpot Children's press aC?est l?histoire d?une petite fille prénommée Alice, qui vivait il n?y a pas si longtemps de ca dans un lieu pas très loin d?ici. Alice a vécu des aventures incroyables dans un lieu qu?on appelle le Pays des Merveilles... a5 ans et + a5 minutes pour une histoire aAlice au pays des merveilles aAnimaux aAventure aChat aClassiques aLapin aLittérature aMésaventure aReine aRencontre aRêve aSurnaturel aVoyage aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aLewis Carroll aAsha Pearse bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/c96d33a6-b5e4-43c0-9178-338bad63e53f/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/alice-au-pays-des-merveilles-2/playr/narration/66e131f6-4cbc-489b-91fa-8cc88b89da9b astoryplayrbstofc96d33a6-b5e4-43c0-9178-338bad63e53f01282nqm1 2200301 i 450 001003700000100002900037101000800066200002300074210001600097330036000113608001500473608001200488608001000500608001500510608001100525608002200536608001900558608001500577608001600592608002900608700002000637700002500657700002000682801001500702856010600717856009900823995005800922fbed018c-2741-4499-a251-e39c852627bb ad |0fre|01 ||||ba afre aA table Lapingouin cHC Editions a<p>Comme tous les jours, Lapingouin n?a pas très faim. Trop fatigué, pas le temps, pas bon? Il a toujours une bonne excuse ! Alors, chaque repas est une occasion pour ses parents de lui rappeler que c?est important de bien manger pour être en bonne santé. Tout va changer quand il va apprendre ce que mange son supe héros pour avoir des super muscles.</p> a3 ans et + aFamille aLapin aLapingouin aManger aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aMasami Mizusawa aCarole-Anne Boisseau aGalaxie Vujanic bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/fbed018c-2741-4499-a251-e39c852627bb/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/a-table-lapingouin/playr astoryplayrbstoffbed018c-2741-4499-a251-e39c852627bb01578nqm1 2200457 i 450 0010037000001000029000371010008000662000059000742100018001333300204001516080015003556080014003706080014003846080014003986080011004126080026004236080012004496080012004616080012004736080012004856080009004976080013005066080010005196080011005296080012005406080012005526080022005646080019005866080015006056080016006206080029006366080015006656080017006806080023006977000021007207000020007418010015007618560106007768560180008829950058010624BA34D88-C4B2-4C73-8F4C-74DF0E5BA5B3 ad |0fre|01 ||||ba afre aAlice prépare une surprise - Alice prepares a surprise cZoom éditions aAlice a envie de préparer un gâteau pour sa maman. Elle rassemble tous les ingrédients et se dépêche de tout mélanger. +Mais tout ne se passe pas comme prévu. La surprise sera-t-elle vraiment réussie? a7 ans et + aApprendre aBilingual aBilingues aCadeau aCollection P'tit Bili aCompter aCooking aCuisine aEnglish aGift aLearning aMaman aMother aNumbers aRecette aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aClaudine Furlano aKatherine Arede bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/4BA34D88-C4B2-4C73-8F4C-74DF0E5BA5B3/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/alice-prepare-une-surprise-alice-prepares-a-surprise/playr/narration/9b8469f7-3496-460a-addd-3050d5c6d586 astoryplayrbstof4BA34D88-C4B2-4C73-8F4C-74DF0E5BA5B301839nqm1 2200445 i 450 001003700000100002900037101000800066200002700074210002300101330059600124608001500720608002700735608001700762608001000779608001200789608001200801608001000813608001100823608001300834608001200847608001600859608001100875608002000886608001400906608001200920608001400932608001200946608001600958608002200974608001900996608001501015608001601030608002901046700002101075700001501096801001501111856010601126856010301232995005801335025665db-35bf-4533-8345-7ad785b631e7 ad |0fre|01 ||||ba afre aAlerte aux chouquettes cFanny Joly Numérik aDepuis qu'il est tout petit, Roger Dupinfray ne rêve que de croissants, de chouquettes et d'éclairs au chocolat... Aucun doute possible sur sa vocation : il sera boulanger pâtissier. Après des débuts plus que prometteurs comme apprenti chez Patissard, le meilleur boulanger de la ville, Roger décide de voler de ses propres ailes et ouvre sa boutique : Au croissant de lune. Le succès ne se fait pas attendre, et toute la ville accourt. Mais un jour, madame Plück affirme que les chouquettes de Roger sont ensorcelées.. La preuve ? Son fils Billy est affublé d'un terrible et durable hoquet. a7 ans et + aA raconter à plusieurs aAlbums longs aAmour aConflit aMaladie aMaman aManger aMensonge aMéchant aMésaventure aMétier aPremiers romans aProblèmes aRecette aSucreries aTravail aVilain tour aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aChristophe Besse aFanny Joly bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/025665db-35bf-4533-8345-7ad785b631e7/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/alerte-aux-chouquettes/playr astoryplayrbstof025665db-35bf-4533-8345-7ad785b631e701403nqm1 2200349 i 450 001003700000100002900037101000800066200002300074210001400097330034000111608001500451608002100466608001400487608001200501608001000513608001100523608001100534608001000545608002200555608001900577608001500596608001600611608002900627608001500656608001700671608002300688700001700711801001500728856010600743856014600849995005800995537C2407-AD7E-4C54-93CB-A1397BA112F4 ad |0fre|01 ||||ba afre aA travers la vitre cLirabelle a« C?est un jour d?hiver. Dehors, la neige a recouvert la campagne. Dans la maison, la buée s?étale sur la grande vitre du salon. Qu?y a-t-il derrière la vitre ? » +Qui ne s?est jamais amusé enfant à dessiner sur les fenêtres embuées ? +C?est un jeu de cache-cache que nous offre Saori Kamino. Découvrons qui se cache derrière la vitre? a3 ans et + aAnimaux sauvages aDevinette aFamille aHiver aMaison aManger aNeige aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aSaori Kamino bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/537C2407-AD7E-4C54-93CB-A1397BA112F4/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/a-travers-la-vitre/playr/narration/1F986F48-3EF2-4281-977F-0BFDB97335EE astoryplayrbstof537C2407-AD7E-4C54-93CB-A1397BA112F401505nqm1 2200373 i 450 001003700000100002900037101000800066200001700074210002500091330037600116608001500492608001000507608001200517608001700529608001000546608002800556608001100584608001200595608001500607608002200622608001900644608001500663608001600678608002900694608001500723608001700738608002300755700001900778700001500797801001500812856010600827856014000933995005801073616dd3aa-df2f-4228-8474-88ce3437bd56 ad |0fre|01 ||||ba afre aAmour amours cPoints de suspension aUn texte poétique qui parle de l?amour, simple et si compliqué à la fois. Un texte qui parle des émotions qui nous traversent chaque jour de notre vie et que nous prenons rarement le temps de dire et d?écouter. Des émotions qui souvent nous submergent mais nous construisent petit à petit et nous permettent de grandir. Un livre pour ne pas oublier de dire « Je t?aime ». a5 ans et + aAmour aFamille aFrère, soeur aMaman aNature et environnement aPoésie aSaisons aSentiments aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aValérie Linder aAnne Bonin bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/616dd3aa-df2f-4228-8474-88ce3437bd56/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/amour-amours/playr/narration/6bd58f47-5703-4d68-988d-b3e7addd1a53 astoryplayrbstof616dd3aa-df2f-4228-8474-88ce3437bd5601492nqm1 2200409 i 450 0010037000001000029000371010008000662000042000742100018001163300308001346080015004426080014004576080014004716080014004856080026004996080012005256080012005376080011005496080009005606080018005696080019005876080013006066080017006196080010006366080009006466080010006556080022006656080019006876080015007066080016007216080029007377000021007668010015007878560106008028560116009089950058010243eb9f49a-5dac-4616-a46a-69cd4ad67e87 ad |0fre|01 ||||ba afre aAnne dans la ville - Anne in the city cZoom éditions aAnne passe le week-end à Lille, chez sa mamie. Au programme : promenade au musée puis récréation au parc. Mais Lille est une grande ville et Anne n?a pas l?habitude. Une intense circulation, une foule grouillante, des ingrédients suffisants pour qu?une petite fille s?y perde. mais où est passée Mamie ? a7 ans et + aApprendre aBilingual aBilingues aCollection P'tit Bili aEnglish aFamille aFamily aFear aGrand-parents aGrands-parents aLearning aMiddle grade aPerdu aPeur aVille aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aClaudine Furlano bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/3eb9f49a-5dac-4616-a46a-69cd4ad67e87/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/anne-dans-la-ville-anne-in-the-city/playr astoryplayrbstof3eb9f49a-5dac-4616-a46a-69cd4ad67e8701472nqm1 2200397 i 450 001003700000100002900037101000800066200002400074210003100098330033500129608002300464608001400487608001200501608000800513608001300521608001300534608001400547608001200561608001800573608001700591608001700608608001100625608001000636608001400646608002200660608001900682608001500701608001600716608002900732700001600761700001800777801001500795856010600810856010000916995005801016c17a9012-4b42-4e53-b62e-7924c0c1c7c5 ad |0fre|01 ||||ba afre aAlice in wonderland cFlowerpot Children's press aAlice was furiously swiping away the attacking cards when she heard a familiar voice... + +?Alice! Wake up!? shouted her sister. And Alice woke up. She was back by the river. As she sat up, she finished brushing away the leaves that had landed on her while she was sleeping. And she thought, ?That was a very strange sleep, indeed.? a5 Minute Storytime aAdventure aAnimals aCat aClassics aDreaming aEncounter aEnglish aMagical world aMiddle grade aMisadventure aRabbit aSleep aTraveling aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAsha Pearse aGeorge Bridge bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/c17a9012-4b42-4e53-b62e-7924c0c1c7c5/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/alice-in-wonderland/playr astoryplayrbstofc17a9012-4b42-4e53-b62e-7924c0c1c7c501281nqm1 2200313 i 450 0010037000001000029000371010008000662000030000742100031001043300237001356080022003726080014003946080012004086080013004206080015004336080022004486080019004706080015004896080016005046080029005206080015005496080017005646080023005817000031006048010015006358560106006508560153007569950058009097938cba0-7715-4c29-8401-b958ceb184f4 ad |0fre|01 ||||ba afre a1st Book of Words At Home cFlowerpot Children's press aThe 1st Book of Words series is an ideal learning tool for budding young minds. Every page is filled with vivid, close-up photos of familiar people, places and things, illustrating simple word concepts that expand vocabulary skills. a1st Book of Words a1st Words aEnglish aLearning aPre-school aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aFlowerpot Children's Press bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/7938cba0-7715-4c29-8401-b958ceb184f4/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/1st-book-of-words-at-home/playr/narration/94be1315-20ac-4167-adfc-60ef99b104d4 astoryplayrbstof7938cba0-7715-4c29-8401-b958ceb184f401126nqm1 2200361 i 450 0010037000001000029000371010008000662000021000742100033000953300023001286080015001516080027001666080012001936080011002056080010002166080011002266080009002376080012002466080011002586080022002696080019002916080015003106080016003256080029003416080015003706080017003856080023004027000019004258010015004448560106004598560141005659950058007060f2d8f64-4343-4354-b40c-557f7aef33f7 ad |0fre|01 ||||ba afre aAlors, ça mord ? cL'Atelier du Poisson Soluble aChuuuut ! ça mord. a3 ans et + aA raconter à plusieurs aAnimaux aHumour aLapin aManger aOurs aPoisson aPêcher aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aJean Gourounas bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/0f2d8f64-4343-4354-b40c-557f7aef33f7/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/alors-ca-mord/playr/narration/3f6831d5-6579-48ee-b0dd-55fd50b33cdd astoryplayrbstof0f2d8f64-4343-4354-b40c-557f7aef33f701276nqm1 2200361 i 450 0010037000001000029000371010008000662000035000742100016001093300153001256080015002786080012002936080021003056080019003266080011003456080009003566080011003656080022003766080022003986080019004206080015004396080016004546080029004706080015004996080017005146080023005317000012005547000017005668010015005838560106005988560152007049950058008560d7de222-6550-4c8b-bf97-79477e21bff6 ad |0fre|01 ||||ba afre aAntoine et le voyage intérieur cLa pimpante a<p>Antoine n?arrive pas à trouver le sommeil. Tante Eva l?accompagne dans un étonnant voyage du souffle et des sensations? de la tête aux pieds?</p> a5 ans et + aAnimaux aAnimaux sauvages aCoups de coeur aFourmi aRêve aVoyage anarration récente aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aCalouan aClaire Buron bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/0d7de222-6550-4c8b-bf97-79477e21bff6/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/antoine-voyage-interieur/playr/narration/eed81552-e969-4bb6-b1e9-9f482d8b646a astoryplayrbstof0d7de222-6550-4c8b-bf97-79477e21bff601554nqm1 2200397 i 450 00100370000010000290003710100080006620000090007421000250008333003870010860800150049560800120051060800140052260800090053660800100054560800210055560800200057660800130059660800210060960800110063060800110064160800220065260800190067460800150069360800160070860800290072460800150075360800170076860800230078570000180080870000210082680100150084785601060086285601300096899500580109820DFB927-2F5D-4046-A201-35DAE32CDE67 ad |0fre|01 ||||ba afre aAH ! cPoints de suspension aMonsieur René aime bien les tartines à la confiture, à la mayonnaise et au chocolat. +Un jour, il jette son papier d?emballage par terre. Passe un ver de terre qui aime aussi les tartines, surtout à la confiture mais pas le plastique cracra. Puis c?est le tour du chat qui aime bien les tartines à la mayonnaise mais pas le plastique cracra. +On suit le chemin du détritus jusqu?à ? a3 ans et + aAnimaux aApprendre aChat aChien aCollage, montage aConte-randonnée aEcologie aEcriture cursive aManger aOiseau aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aCécile Bonbon aStephane Servant bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/20DFB927-2F5D-4046-A201-35DAE32CDE67/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/ah/playr/narration/59916f55-c20c-49b3-b509-a25764407f1a astoryplayrbstof20DFB927-2F5D-4046-A201-35DAE32CDE6701633nqm1 2200445 i 450 00100370000010000290003710100080006620000300007421000180010433003460012260800150046860800140048360800190049760800110051660800120052760800110053960800170055060800090056760800110057660800170058760800110060460800120061560800090062760800140063660800130065060800140066360800220067760800190069960800150071860800160073360800290074960800150077860800170079360800230081070000230083380100150085685601060087185601520097799500580112986B20DD2-AE8B-4644-848E-A104BB55AD1C ad |0fre|01 ||||ba afre a1001 cre?pes pour la lune cZoom éditions aDans l'Egypte antique, sur les bords du Nil, une petite fille, Dasine, et son petit frère, Bakou, sont faits prisonniers par une sorcière cannibale. +Dasine parvient à s'enfuir seule dans le désert, où elle rencontre la Déesse Lune. +Cette dernière lui confie la recette des crêpes qui gaveront la sorcière et la mettront hors d'état de nuire. a7 ans et + aApprendre aConte revisité aContes aCuisine aDésert aFrère, soeur aLune aManger aMoyen-Orient aPrison aRecette aRuse aSauvetage aSorcière aSucreries aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aCatarina Michelini bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/86B20DD2-AE8B-4644-848E-A104BB55AD1C/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/1001-crepes-pour-la-lune/playr/narration/90d23102-cbd7-46da-bc7c-dd73873666ff astoryplayrbstof86B20DD2-AE8B-4644-848E-A104BB55AD1C01251nqm1 2200337 i 450 001003700000100002900037101000800066200003600074210003100110330019800141608001600339608001200355608001200367608001400379608001300393608001700406608001200423608001500435608001800450608002000468608002200488608001900510608001500529608001600544608002900560700003100589801001500620856010600635856011400741995005800855e285859e-adb5-40c0-a0bb-f85af6a40795 ad |0fre|01 ||||ba afre aAmerican Inventors & Innovators cFlowerpot Children's press aHow did Americans come up with such great ideas? In the pages of American Inventors & Innovators, you?ll find stories of how these things were made, and the people (and kids) who invented them! aDocumentary aEnglish aHistory aInvention aLearning aMiddle grade aScience aTechnology aUnited States aWorld of Wonder aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aFlowerpot Children's Press bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/e285859e-adb5-40c0-a0bb-f85af6a40795/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/american-inventors-and-innovators/playr astoryplayrbstofe285859e-adb5-40c0-a0bb-f85af6a4079501510nqm1 2200325 i 450 00100370000010000290003710100080006620000240007421000160009833005470011460800150066160800100067660800090068660800110069560800100070660800150071660800100073160800220074160800190076360800150078260800160079760800290081370000200084270000250086270000200088780100150090785601060092285600980102899500580112690f2f531-3325-4291-b642-ebdc7977bf8e ad |0fre|01 ||||ba afre aAu lit Lapingouin ! cHC Editions a<p>C?est l?heure pour Lapingouin de se coucher, mais il a tendance à trainer les nageoires pour y aller. Alors il fait tout pour gagner du temps, cherchant milles excuses, malgré les rappels de sa maman. À force de l?attendre, celle-ci s?endort dans son lit sans qu?il s?en rende compte. Occupé à chercher « Moudoux », son papa lui demande ce qu?il est en train de faire. Tout coi, il réfléchit et n?arrive pas à se souvenir ce que lui avait demandé de faire sa maman. Un traité illustratif d?une grande finesse tout en douceur.</p> a3 ans et + aAmour aChat aDormir aLapin aLapingouin aMaman aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aMasami Mizusawa aCarole-Anne Boisseau aGalaxie Vujanic bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/90f2f531-3325-4291-b642-ebdc7977bf8e/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/au-lit-lapingouin/playr astoryplayrbstof90f2f531-3325-4291-b642-ebdc7977bf8e01222nqm1 2200373 i 450 001003700000100002900037101000800066200001300074210003300087330009900120608001500219608001400234608000900248608002000257608001300277608001100290608001300301608001200314608001300326608002100339608002200360608001900382608001500401608001600416608002900432608001500461608001700476608002300493700001700516801001500533856010600548856013600654995005800790b75a5d16-025c-4c86-a46b-de275090f79c ad |0fre|01 ||||ba afre aAquarium cL'Atelier du Poisson Soluble aUn aquarium comme une cour de récréation où s'expriment, sans retenu, la cruauté et la vanité. a3 ans et + aApprendre aCaca aConte-randonnée aCouleurs aHumour aMoquerie aPoisson aPréjugés aTel est pris ... aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aYann Fastier bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/b75a5d16-025c-4c86-a46b-de275090f79c/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/aquarium/playr/narration/6eaa1371-a97f-4d3b-8084-81955d2a5da4 astoryplayrbstofb75a5d16-025c-4c86-a46b-de275090f79c01030nqm1 2200289 i 450 001003700000100002900037101000800066200002300074210003100097330011000128608001200238608001200250608001300262608001700275608001800292608002000310608002200330608001900352608001500371608001600386608002900402700003100431801001500462856010600477856009900583995005800682717eca92-fd30-4d1e-b2d3-91d47307e0d4 ad |0fre|01 ||||ba afre aAll Around America cFlowerpot Children's press aFrom the very beginning, America has been a land filled with adventure, unique people and amazing sights. aEnglish aHistory aLearning aMiddle grade aUnited States aWorld of Wonder aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aFlowerpot Children's Press bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/717eca92-fd30-4d1e-b2d3-91d47307e0d4/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/all-around-america/playr astoryplayrbstof717eca92-fd30-4d1e-b2d3-91d47307e0d401560nqm1 2200409 i 450 0010037000001000029000371010008000662000017000742100024000913300375001156080015004906080017005056080014005226080009005366080015005456080009005606080011005696080016005806080011005966080013006076080009006206080010006296080022006396080019006616080015006806080016006956080029007116080015007406080017007556080023007727000016007957000020008118010015008318560106008468560140009529950058010922B394153-16ED-4E44-8E42-55E2A1E9E88F ad |0fre|01 ||||ba afre aBombay Waouh cChemins de traverse aBombay Waouh ! Le cri du coeur garanti pour celui qui s?aventurera dans les rues de Bombay, ville des rencontres saugrenues et miraculeuses, sur les traces de personnages aussi attachants que doués pour se trouver dans des situations cocasses. +C?est une Bombay grouillante de fantaisie et de couleurs qui nous est ici contée, avec finesse, et qui nous invite au voyage. a5 ans et + aAlbums longs aApprendre aAsie aDécouverte aInde aManger aMésaventure aOiseau aReligion aRêve aVille aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aEric Bétend aRatna Moriniaux bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/2B394153-16ED-4E44-8E42-55E2A1E9E88F/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/bombay-waouh/playr/narration/b4dd7437-886c-465b-b990-450b68a03561 astoryplayrbstof2B394153-16ED-4E44-8E42-55E2A1E9E88F01006nqm1 2200301 i 450 001003700000100002900037101000800066200003000074210002200104330008000126608001200206608001800218608001200236608001200248608001300260608001100273608002200284608001900306608001500325608001600340608002900356700001700385700001700402801001500419856010600434856010600540995005800646fead7ed9-780a-493d-a9e5-cc8b070077a0 ad |0fre|01 ||||ba afre aCaillou learns to recycle cChouette Editions aThe children at Caillou's day care are curious about the new recycling bin. aCaillou aEarly readers aEcology aEnglish aLearning aSchool aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aEric Sévigny aKim Thompson bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/fead7ed9-780a-493d-a9e5-cc8b070077a0/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/caillou-learns-to-recycle/playr astoryplayrbstoffead7ed9-780a-493d-a9e5-cc8b070077a001085nqm1 2200301 i 450 00100370000010000290003710100080006620000280007421000220010233001650012460800120028960800180030160800120031960800110033160800100034260800110035260800220036360800190038560800150040460800160041960800290043570000190046470000170048380100150050085601060051585601040062199500580072500c0aee4-a4bf-4860-841a-25ebcae96904 ad |0fre|01 ||||ba afre aCaillou learns to skate cChouette Editions aCaillou is learning to skate. With a lot of tumbles, the help of a chair, and loads of encouragement from Mommy and Daddy, Caillou begins to get the hang of it. aCaillou aEarly readers aEnglish aFamily aSport aWinter aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aMarion Johnson aEric Sévigny bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/00c0aee4-a4bf-4860-841a-25ebcae96904/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/caillou-learns-to-skate/playr astoryplayrbstof00c0aee4-a4bf-4860-841a-25ebcae9690401504nqm1 2200409 i 450 00100370000010000290003710100080006620000180007421000190009233003240011160800150043560800120045060800100046260800120047260800110048460800090049560800120050460800100051660800110052660800120053760800160054960800090056560800220057460800190059660800150061560800160063060800290064660800150067560800170069060800230070770000220073070000220075280100150077485601060078985601410089599500580103638621f40-283d-4b94-aa70-053d7912d28d ad |0fre|01 ||||ba afre aBoule de Noël cÉditions Panda aMes maîtres ont décidé de m?offrir un cadeau. Un présent incroyablement gros ! Depuis le temps que je les endure, je le mérite bien. C?est un arbre à chat géant pour faire mes griffes. Il est parfait pour moi. Mais pourquoi s?entêtent-ils à suspendre des boules, et des lumières dedans? Ce cadeau est à moi. À MOI SEUL! a5 ans et + aAnimaux aArbre aBêtises aCadeau aChat aFamille aHiver aHumour aMonchou aMésaventure aNoël aLivre pour enfant aAlbum jeunesse astoryplayr astoryplay'r aHistoire pour s'endormir aAudio book aHistoire lue aHistoire à écouter aCaroline Therrien aGeneviève Després bStoryplayr 2Vignetteuhttps://www.storyplayr.com/api/library/38621f40-283d-4b94-aa70-053d7912d28d/thumbnail/large 2Ressourceuhttps://www.storyplayr.com/api/assa/login?target=/histoire/boule-de-noel/playr/narration/2ca17d1f-43e8-4bc5-a50e-b120723a6422 astoryplayrbstof38621f40-283d-4b94-aa70-053d7912d28d diff --git a/cosmogramme/tests/phpunit.xml b/cosmogramme/tests/phpunit.xml index ec0cd3a1c42c3638561b2e8e9d04b223bb80b372..eaf44c057c6bb9429ceff360e8cef3c94cc35eee 100644 --- a/cosmogramme/tests/phpunit.xml +++ b/cosmogramme/tests/phpunit.xml @@ -1,21 +1,21 @@ <?xml version="1.0" encoding="UTF-8"?> <phpunit - bootstrap="./bootstrap.php" - colors="false" - backupGlobals="false" - stopOnFailure="false" - stopOnError="false" - > - <testsuites> - <testsuite name="ApplicationTestSuite"> - <directory>./php/</directory> - </testsuite> - </testsuites> - <filter> - <whitelist> - <directory suffix=".php">../php/classes</directory> - <directory suffix=".php">../php/fonctions</directory> - </whitelist> - </filter> + bootstrap="./bootstrap.php" + colors="false" + backupGlobals="false" + stopOnFailure="false" + stopOnError="false" + > + <testsuites> + <testsuite name="Cosmogramme classes and fonctions"> + <directory>./php/</directory> + </testsuite> + </testsuites> + <filter> + <whitelist> + <directory suffix=".php">../php/classes</directory> + <directory suffix=".php">../php/fonctions</directory> + </whitelist> + </filter> </phpunit> diff --git a/library/Class/AdminVar.php b/library/Class/AdminVar.php index 29ee2239d41da48e565f05e00072e223f53d68c7..cf17b95e0f169a0d191db83c6b7baeeb1b9e1c9a 100644 --- a/library/Class/AdminVar.php +++ b/library/Class/AdminVar.php @@ -118,14 +118,14 @@ class Class_AdminVarLoader extends Storm_Model_Loader { if (null !== $this->all_vars) return $this->all_vars; - return $this->all_vars= + return $this->all_vars = [ 'avis' => $this->_getCommentVars(), 'modo' => $this->_getModerationVars(), 'stat' => $this->_getStatVars(), 'global' => $this->_getGlobalVars(), 'cosmogramme' => $this->_getCosmogrammeVars(), - 'catalogue' => $this->_getOAIVars(), + 'catalogue' => $this->_getCatalogVars(), 'newsletter' => $this->_getNewsletterVars(), 'cms' => $this->_getCmsVars(), 'album' => $this->_getAlbumVars(), @@ -152,10 +152,13 @@ class Class_AdminVarLoader extends Storm_Model_Loader { protected function _getStaticAlbumVars() { return ['ALBUMS_LIST_MODE' => Class_AdminVar_Meta::newOnOff($this->_('Le gestionnaire de contenu affiche les albums sous forme de liste paginée au lieu de d\'une arborescence. Cet affichage est adapté lorsque le nombre d\'albums devient trop important')), - 'ALBUM_MEDIA_NO_AUTOINDEX_TITLE' => Class_AdminVar_Meta::newOnOff($this->_('Ne pas créer de zone 464 pour les médias dont le titre n\'est pas saisi'))->bePrivate(), + 'ALBUM_MEDIA_NO_AUTOINDEX_TITLE' => Class_AdminVar_Meta::newOnOff($this->_('Bibliothèque numérique: ne pas créer de zone 464 pour les médias dont le titre n\'est pas saisi')), - 'BIBNUM' => Class_AdminVar_Meta::newOnOff($this->_('Activer ou désactiver la bibliothèque numérique'))->bePrivate(), - 'SITO_IN_ALBUMS' => Class_AdminVar_Meta::newOnOff($this->_('Gérer la sitothèque dans la bibliothèque numérique, nécessite l\'activation de la bibliothèque numérique'))->bePrivate(), + 'BIBNUM' => Class_AdminVar_Meta::newOnOff($this->_('Activer ou désactiver la bibliothèque numérique'))->enable(), + 'IMPORT_EAD' => Class_AdminVar_Meta::newOnOff($this->_('Activation de l\'import EAD')), + 'OAI_REPOSITORY' => Class_AdminVar_Meta::newOnOff($this->_('Activation de l\'import de dépôts OAI')), + 'OPDS' => Class_AdminVar_Meta::newOnOff($this->_('Activation de l\'import de catalogues OPDS'))->enable(), + 'SITO_IN_ALBUMS' => Class_AdminVar_Meta::newOnOff($this->_('Gérer la sitothèque dans la bibliothèque numérique, nécessite l\'activation de la bibliothèque numérique')), 'NUMILOG_URL' => Class_AdminVar_Meta::newDefault($this->_('Paramétrage <a href="http://forge.afi-sa.fr/projects/opac3/wiki/Ressources_externes_enrichissements#Numilog">Numilog</a>'))->bePrivate(), 'NUMILOG_OAI_URL' => Class_AdminVar_Meta::newDefault($this->_('Paramétrage <a href="http://forge.afi-sa.fr/projects/opac3/wiki/Ressources_externes_enrichissements#Numilog">Numilog</a>'))->bePrivate(), @@ -228,7 +231,7 @@ class Class_AdminVarLoader extends Storm_Model_Loader { 'ENABLE_BOOKMARKABLE_SEARCHES' => Class_AdminVar_Meta::newOnOff($this->_('Les utilisateurs peuvent enregister des recherches dans leurs favoris'), ['value' => 0]), 'ENABLE_BOOKMARKABLE_SEARCHES_NOTIFY' => Class_AdminVar_Meta::newOnOff($this->_('Les utilisateurs peuvent recevoir les nouveautés de leurs recherches favorites par email'), ['value' => 0]), Class_AdminVar_UserDoubleDetectOn::KEY => Class_AdminVar_Meta::newMultiInput($this->_('Champs servant à la détection des doublons. Champs possibles : %s', (new Class_AdminVar_UserDoubleDetectOn)->knownAsList()), - ['validate' => 'ZendAfi_Validate_UserDoubleDetectOn'])->bePrivate(), + ['validate' => 'ZendAfi_Validate_UserDoubleDetectOn']), ]; } @@ -259,9 +262,9 @@ class Class_AdminVarLoader extends Storm_Model_Loader { ['name' => 'site_url', 'label' => $this->_('Url de recherche')] ]]]), 'NOM_DOMAINE' => Class_AdminVar_Meta::newDefault($this->_('Nom de domaine principal de l\'OPAC, ex: monopac.macommune.fr')), - 'CUSTOM_SEARCH_FORM' => Class_AdminVar_Meta::newOnOff($this->_('Activer les formulaires de recherche configurables'))->bePrivate(), + 'CUSTOM_SEARCH_FORM' => Class_AdminVar_Meta::newOnOff($this->_('Activer les formulaires de recherche configurables'))->enable(), 'ENABLE_SEARCH_MULTIPLE_RECORD_SELECTION' => Class_AdminVar_Meta::newOnOff($this->_('Activer la sélection multiple de notices dans le résultat de recherche')), - 'AUTHOR_PAGE' => Class_AdminVar_Meta::newOnOff($this->_('Activer les fiches auteurs, tous les liens de recherche vers un auteur basculeront sur la fiche auteur')), + 'AUTHOR_PAGE' => Class_AdminVar_Meta::newOnOff($this->_('Activer les fiches auteurs, tous les liens de recherche vers un auteur basculeront sur la fiche auteur'))->enable(), ]; } @@ -283,7 +286,7 @@ class Class_AdminVarLoader extends Storm_Model_Loader { 'WORKFLOW_TEXT_MAIL_ARTICLE_PENDING' => Class_AdminVar_Meta::newDefault($this->_('Contenu de l\'email de notification d\'article en attente de validation. Termes substitués: TITRE_ARTICLE, URL_ARTICLE, AUTHOR_ARTICLE, SAVED_BY_ARTICLE, STATUS_ARTICLE, NEXT_STATUS_ARTICLE')), 'WORKFLOW_TEXT_MAIL_ARTICLE_REFUSED' => Class_AdminVar_Meta::newDefault($this->_('Contenu de l\'email de notification de refus d\'un article à valider. Termes substitués: TITRE_ARTICLE, URL_ARTICLE, AUTHOR_ARTICLE, SAVED_BY_ARTICLE')), 'WORKFLOW_TEXT_MAIL_ARTICLE_VALIDATED' => Class_AdminVar_Meta::newDefault($this->_('Contenu de l\'email de notification de validation d\'un article. Termes substitués: TITRE_ARTICLE, URL_ARTICLE, AUTHOR_ARTICLE, SAVED_BY_ARTICLE')), - + 'CUSTOM_GENRE_ICON' => Class_AdminVar_Meta::newOnOff($this->_('Activation de l\'interface de personnalisation des icones des genres')), ]; } @@ -305,9 +308,9 @@ class Class_AdminVarLoader extends Storm_Model_Loader { return [ 'DEFAULT_LANGUAGE' => Class_AdminVar_Meta::newDefault($this->_('Langue par défaut'))->bePrivate(), 'FORCE_HTTPS' => Class_AdminVar_Meta::newOnOff($this->_('Forcer l\'accès au site par le protocole HTTPS. Nécessite l\'installation et la configuration appropriée du serveur Web')), - 'LOGIN_THROUGH_SIGB_ONLY' => Class_AdminVar_Meta::newOnOff($this->_('Les abonnées peuvent se connecter uniquement via le webservice du SIGB.') + 'LOGIN_THROUGH_SIGB_ONLY' => Class_AdminVar_Meta::newOnOff($this->_('Les abonné.e.s peuvent se connecter uniquement via le webservice du SIGB.') . '<br/>' - . $this->_('De plus, à la connexion, l\'enregistrement des mots de passes des abonnés est désactivé.'))->bePrivate(), + . $this->_('De plus, à la connexion, l\'enregistrement des mots de passes des abonnés est désactivé.')), 'OAUTH_ACCEPT_HTTP' => Class_AdminVar_Meta::newOnOff($this->_('Autoriser l\'accès aux API OAUTH via HTTP (non sécurisé - déconseillé)'), ['value' => 0]), 'NB_AFFICH_AVIS_PAR_AUTEUR' => Class_AdminVar_Meta::newDefault($this->_('Nombre d\'avis maximum à afficher par utilisateur.')), 'REGISTER_OK' => Class_AdminVar_Meta::newEncodedData($this->_('Texte visible par l\'internaute après son inscription.')), @@ -324,7 +327,7 @@ class Class_AdminVarLoader extends Storm_Model_Loader { '<a href="' . Class_Url::baseUrl() . '/admin/index/clearcache" >Vider le cache</a>']))->bePrivate(), 'CACHE_DATE' => Class_AdminVar_Meta::newDefault($this->_('Date du dernier vidage manuel du cache'))->bePrivate(), - 'ACTIVITY' => Class_AdminVar_Meta::newOnOff($this->_('Activer ou désactiver le module d\'activité'))->bePrivate(), + 'ACTIVITY' => Class_AdminVar_Meta::newOnOff($this->_('Activer ou désactiver le module d\'activité')), 'BABELTHEQUE_JS' => Class_AdminVar_Meta::newDefault($this->_('URL du javascript Babelthèque à insérer dans l\'OPAC'))->bePrivate(), 'MULTIMEDIA_KEY' => Class_AdminVar_Meta::newDefault($this->_('Clé publique pour le cryptage des données AFI-Multimédia')), @@ -363,13 +366,16 @@ class Class_AdminVarLoader extends Storm_Model_Loader { 'BUID' => Class_AdminVar_Meta::newRawText($this->_('Identifiant unique (attention: la modification de cette variable impactera les outils de suivi de cette installation)'))->bePrivate(), 'STATUS_REPORT_PUSH_URL' => Class_AdminVar_Meta::newRawText($this->_('URL destinataire du rapport d\'état du système (0 pour désactiver)'), ['value' => 'http://pola.afi-sa.net/smile.php'])->bePrivate(), 'STATUS_REPORT_TAGS' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des tags à ajouter au rapport d\'état du système'))->bePrivate(), - 'FEATURES_TRACKING_ENABLE' => Class_AdminVar_Meta::newOnOff('Affiche les dernières modifications apportés au logiciel Bokeh', ['value' => 1])->bePrivate(), - 'INSPECTOR_GADGET_MARC_XML' => Class_AdminVar_Meta::newOnOff('Affiche le MARC XML de la notice dans Inspector Gadget')->bePrivate(), + 'FEATURES_TRACKING_ENABLE' => Class_AdminVar_Meta::newOnOff('Affiche les dernières modifications apportés au logiciel Bokeh', ['value' => 1]), + 'INSPECTOR_GADGET_MARC_XML' => Class_AdminVar_Meta::newOnOff('Affiche le MARC XML de la notice dans Inspector Gadget')->enable(), 'BUSINESS_EMAIL' => Class_AdminVar_Meta::newDefault($this->_('Email utilisé pour les demandes d\'accompagnement de mise en place ou d\'utilisation des fonctionnalités du logiciel'), ['value' => 'cial-bib@afi-sa.fr'])->bePrivate(), - 'CODIFICATION_BROWSER' => Class_AdminVar_Meta::newOnOff($this->_('Activer l\'outil de parcours des codifications')) - ->bePrivate(), + 'CODIFICATION_BROWSER' => Class_AdminVar_Meta::newOnOff($this->_('Activer l\'outil de parcours des codifications'))->enable(), 'TEMPLATING' => Class_AdminVar_Meta::newOnOff('Active l\'accès au magasin de thèmes', - ['value' => 0])->bePrivate() + ['value' => 0])->bePrivate(), + 'GENERATION_SITE' => Class_AdminVar_Meta::newOnOff($this->_('Activation de la génération de site.')), + 'CUSTOM_FIELDS_REPORT' => Class_AdminVar_Meta::newOnOff($this->_('Activation des rapports statistiques sur les champs personnalisés')), + 'WEBSERVICE_TEST' => Class_AdminVar_Meta::newOnOff($this->_('Activation des tests de webservices')), + 'IMPORT_AVIS_OPAC2' => Class_AdminVar_Meta::newOnOff($this->_('Activation de l\'import des avis de l\'opac2')), ]; } @@ -408,8 +414,9 @@ class Class_AdminVarLoader extends Storm_Model_Loader { } - protected function _getOAIVars() { + protected function _getCatalogVars() { return [ + 'IMPORT_THESAURUS' => Class_AdminVar_Meta::newOnOff($this->_('Activation de l\'import de thesaurus')), 'OAI_SERVER' => Class_AdminVar_Meta::newOnOff($this->_('Activation du serveur OAI: permet le moissonnage des domaines par d\'autres logiciels via OAI')), 'OAI_REPOSITORY_NAME' => Class_AdminVar_Meta::newDefault($this->_('Contenu de la balise "repositoryName" dans la réponse au verb Identify, si vide sera [NOM DU SERVEUR] Oai repository')), 'OAI_ADMIN_EMAIL' => Class_AdminVar_Meta::newDefault($this->_('Contenu de la balise "adminEmail" dans la réponse au verb Identify, si vide sera tiré de la variable cosmogramme "mail_admin"')),]; @@ -428,8 +435,7 @@ class Class_AdminVarLoader extends Storm_Model_Loader { ['value' => '500'])->bePrivate(), 'ALLOWED_FILES_EXTENSIONS_FOR_IMPORT' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des extensions de fichiers disponibles à l\'import.'), - ['value' => 'css;pdf;mp3;mp4;ogg;m4v;ico;gif;svg;jpg;jpeg;png;epub;geojson']) - ->bePrivate(), + ['value' => 'css;pdf;mp3;mp4;ogg;m4v;ico;gif;svg;jpg;jpeg;png;epub;geojson;xsl;txt;pdf']), 'RESIZABLE_DIMENSIONS' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des dimensions disponibles pour retailler les images lors de l\'import.'), ['value' => '800x600;1024x768;1280x1024;']), @@ -879,6 +885,51 @@ class Class_AdminVarLoader extends Storm_Model_Loader { } + public static function isImportThesaurusEnabled() { + return Class_AdminVar::isModuleEnabled('IMPORT_THESAURUS'); + } + + + public static function isImportEadEnabled() { + return Class_AdminVar::isModuleEnabled('IMPORT_EAD'); + } + + + public static function isOaiRepositoryEnabled() { + return Class_AdminVar::isModuleEnabled('OAI_REPOSITORY'); + } + + + public static function isOpdsEnabled() { + return Class_AdminVar::isModuleEnabled('OPDS'); + } + + + public static function isCustomGenreIconEnabled() { + return Class_AdminVar::isModuleEnabled('CUSTOM_GENRE_ICON'); + } + + + public static function isGenerationSiteEnabled() { + return Class_AdminVar::isModuleEnabled('GENERATION_SITE'); + } + + + public static function isCustomFieldsReportEnabled() { + return Class_AdminVar::isModuleEnabled('CUSTOM_FIELDS_REPORT'); + } + + + public static function isWebserviceTestEnabled() { + return Class_AdminVar::isModuleEnabled('WEBSERVICE_TEST'); + } + + + public static function isImportAvisOpac2Enabled() { + return Class_AdminVar::isModuleEnabled('IMPORT_AVIS_OPAC2'); + } + + public function getBabelthequeId() { $mathes = []; if (preg_match('/bw_([^\.]+)\.js/', (string)Class_AdminVar::get('BABELTHEQUE_JS'), $matches)) @@ -941,6 +992,11 @@ class Class_AdminVarLoader extends Storm_Model_Loader { } + public function isAuthorPageEnabled() { + return Class_AdminVar::isModuleEnabled('AUTHOR_PAGE'); + } + + public function shouldKeepLastSigbRecord() { return Class_AdminVar::isModuleEnabled('KEEP_LAST_SIGB_RECORD'); } diff --git a/library/Class/AdminVar/Meta.php b/library/Class/AdminVar/Meta.php index 6732d8a4d4c30af54f15cf4466aa2dc530d09c33..8cf86285c80532fcdb85dcbfbc1d8e4b251e514f 100644 --- a/library/Class/AdminVar/Meta.php +++ b/library/Class/AdminVar/Meta.php @@ -75,6 +75,11 @@ class Class_AdminVar_Meta { } + public function getRoleLevel() { + return $this->_attributes['role_level']; + } + + public function getType() { return $this->_type; } @@ -156,8 +161,27 @@ class Class_AdminVar_Meta { } + public function setValue($value) { + $this->_attributes['value'] = $value; + return $this; + } + + public function bePrivate() { $this->_attributes['role_level'] = ZendAfi_Acl_AdminControllerRoles::SUPER_ADMIN; return $this; } + + + public function isPrivate() { + return ZendAfi_Acl_AdminControllerRoles::SUPER_ADMIN == $this->getAttribute('role_level', null); + } + + + public function enable() { + if (! $this->isOnOff()) + return $this; + + return $this->setValue(1); + } } \ No newline at end of file diff --git a/library/Class/Album.php b/library/Class/Album.php index 00327be53a755aa1122ed5b7648c1cf989664eb6..0252f6b3066be0d103a49b6cb3c5eb1007f5a01f 100644 --- a/library/Class/Album.php +++ b/library/Class/Album.php @@ -54,7 +54,6 @@ */ class AlbumLoader extends Storm_Model_Loader { - use Trait_MemoryCleaner; @@ -82,6 +81,14 @@ class AlbumLoader extends Storm_Model_Loader { $page++; } } + + + public function findAllAfter($id, $date_maj, $limit=100) { + $where = "id > " . $id . " and date_maj >= '" . $date_maj . "'"; + return Class_Album::findAllBy(['where' => $where, + 'order' => 'id', + 'limit' => $limit]); + } } @@ -173,6 +180,8 @@ class Class_Album extends Storm_Model_Abstract { protected $path_flash; + protected $_date_maj_enabled = true; + public function __construct() { parent::__construct(); @@ -901,6 +910,13 @@ class Class_Album extends Storm_Model_Abstract { } + public function saveWithoutDateMaj() { + $this->_date_maj_enabled = false; + $this->save(); + $this->_date_maj_enabled = true; + } + + public function collectAuthors() { $authors = $this->_collect('authors', self::AUTHOR_FIELD); if(isset($authors['author'])) @@ -944,6 +960,9 @@ class Class_Album extends Storm_Model_Abstract { public function updateDateMaj() { + if (!$this->_date_maj_enabled) + return $this; + return $this->setDateMaj(date('Y-m-d H:i:s', self::getTimeSource()->time())); } diff --git a/library/Class/Article.php b/library/Class/Article.php index 802e1d56f88e99a342963ac078005998010fe7b4..b1d6011b76ce4d2cc28d59516227165ac37af410 100644 --- a/library/Class/Article.php +++ b/library/Class/Article.php @@ -368,12 +368,16 @@ class ArticleLoader extends Storm_Model_Loader { ->_orderAndLimit() ->_getSelect(); + $articles = Class_Article::getLoader()->findAll($select); - $articles = $this->_sortArticles( - $this->_filterByDay($this->_event_date, - $this->_filterByCustomFields( - Class_Article::getLoader()->findAll($select), - $this->_custom_fields))); + if ($this->_custom_fields) + $articles = $this->_filterByCustomFields($articles, + $this->_custom_fields); + + if ((new ZendAfi_Validate_DateFormat)->isValid($this->_event_date)) + $articles = $this->_filterByDay($this->_event_date, $articles); + + $articles = $this->_sortArticles($articles); if ( ($this->_sort_order == 'Selection') diff --git a/library/Class/Article/MailRenderer.php b/library/Class/Article/MailRenderer.php new file mode 100644 index 0000000000000000000000000000000000000000..04239b891861096eb7c74f5f43176ff699ad541d --- /dev/null +++ b/library/Class/Article/MailRenderer.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright (c) 2012-2019, 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_Article_MailRenderer { + use Trait_Translator; + + public function renderTextInto($article, &$data) { + if (!$article) + return; + + $data[] = '- ' . $article->getLabel(); + $data[] = strip_tags($article->getFullContent()); + $data[] = $this->_('Lien: ') . Class_Url::absolute(['controller' => 'cms', + 'action' => 'viewarticle', + 'id' => $article->getId()], null, true); + $data[] = "\n"; + } + + + public function renderHtml($article) { + if (!$article) + return ''; + + return '<div style="padding:5px">' . + '<h1>' . $article->getLabel() . '</h1>' . + '<div>' . $article->getFullContent() . '</div>' . + '<div style="clear:both"></div>'. + '</div>'; + } +} diff --git a/library/Class/Bib.php b/library/Class/Bib.php index 32a8e4217b26b18f090736e1b97f3304cf220cff..aa742310a53b563645884241bffe264dd0ef10e9 100644 --- a/library/Class/Bib.php +++ b/library/Class/Bib.php @@ -56,6 +56,13 @@ class BibLoader extends Storm_Model_Loader { } + public function findAllRedmineEnabled() { + return (new Storm_Model_Collection(Class_Bib::findAllBy(['order' => 'libelle']))) + ->select('isRedmineEnabled') + ->getArrayCopy(); + } + + public function getUserFriendlyBibs() { $all_bibs = Class_Bib::getLoader()->findAllBy(['order' => 'libelle']); $bibs_as_array = []; @@ -732,6 +739,11 @@ class Class_Bib extends Storm_Model_Abstract { } + public function isRedmineEnabled() { + return (bool)$this->getRedmineLoginOrKey(); + } + + public function isReceivedFile() { if (!$this->_isFileInRequest('photo')) return true; diff --git a/library/Class/CodifThesaurus.php b/library/Class/CodifThesaurus.php index c0157d406cac7902e3af60f8086c76257d839103..d132f694d3849a915fcb7a8926b0b2bcd6e1160a 100644 --- a/library/Class/CodifThesaurus.php +++ b/library/Class/CodifThesaurus.php @@ -30,8 +30,8 @@ class CodifThesaurusLoader extends Storm_Model_Loader { protected - $_fixed = [], - $_customfields_facet_prefix; + $_fixed = [], + $_customfields_facet_prefix; public function __construct($class) { parent::__construct($class); @@ -174,13 +174,27 @@ class CodifThesaurusLoader extends Storm_Model_Loader { public function addFacetForSigb($facet_name, $facet_rules, $comm_sigb) { - if (!Class_IntBib::findFirstBy(['comm_sigb' => $comm_sigb]) - || Class_CodifThesaurus::findFirstBy(['rules' => json_encode(['label' => $facet_rules])])) + if (!Class_IntBib::findFirstBy(['comm_sigb' => $comm_sigb])) + return; + + $parts = explode('$', trim($facet_rules)); + if (2 !== count($parts)) + return; + + $zone = $parts[0]; + $label_field = $parts[1]; + $rules = (new Class_CodifThesaurus_Rules()) + ->setZone($zone) + ->setLabelField($label_field); + + if (Class_CodifThesaurus::findFirstBy(['rules' => $rules->format()])) return ; - $thesaurus = Class_CodifThesaurus::newInstance(['libelle' => $facet_name, - 'libelle_facette' => $facet_name, - 'rules' => json_encode(['label' => $facet_rules])]); - $thesaurus->save(); + + Class_CodifThesaurus::newInstance(['libelle' => $facet_name, + 'libelle_facette' => $facet_name, + 'rule_zone' => $zone, + 'rule_label_field' => $label_field]) + ->save(); } @@ -460,6 +474,36 @@ class CodifThesaurusLoader extends Storm_Model_Loader { public function root() { return Class_CodifThesaurus::newInstance(); } + + + public function newIdThesaurusForLabel($label) { + $id = substr(strtoupper($label), 0, Class_CodifThesaurus::ID_KEY_LENGTH); + + if (strlen($id) == Class_CodifThesaurus::ID_KEY_LENGTH + && !Class_CodifThesaurus::findFirstBy(['id_thesaurus' => $id])) + return $id; + + $label = substr(strtoupper($label), 0, 3); + $suffixes = array_merge(range(0, 9), range('a', 'z')); + + while(!empty($suffixes)) { + $suffix = strtoupper(array_shift($suffixes)); + $id = sprintf("%'".$suffix."-4s", $label); + + if (!Class_CodifThesaurus::findFirstBy(['id_thesaurus' => $id])) + return $id; + } + } + + + public function withDynamicFacetsHavingIdFieldDo($closure) { + (new Storm_Model_Collection(Class_CodifThesaurus::findAllBy(['rules not' => null, + 'rules not' => '', + 'id_thesaurus not' => null, + 'order' => 'libelle']))) + ->select('hasRuleIdField') + ->eachDo($closure); + } } @@ -481,11 +525,106 @@ class Class_CodifThesaurus extends Storm_Model_Abstract { protected $_table_primary = 'id'; protected $_default_attribute_values = ['libelle' => '', 'libelle_facette' => '', - 'id_thesaurus' =>null, + 'id_thesaurus' => null, 'id_origine' => null, 'rules' => null, 'code' => null]; + protected $_rules; + + + public function __construct() { + parent::__construct(); + $this->_rules = new Class_CodifThesaurus_Rules(); + } + + + public function initializeAttributes($datas) { + parent::initializeAttributes($datas); + $this->_rules->initialize($this->getRules()); + return $this; + } + + + public function beforeSave() { + $this->setRules($this->_rules->format()); + } + + + public function getRuleZone() { + return $this->_rules->getZone(); + } + + + public function setRuleZone($zone) { + $this->_rules->setZone($zone); + return $this; + } + + + public function getRuleLabelField() { + return $this->_rules->getLabelField(); + } + + + public function setRuleLabelField($field) { + $this->_rules->setLabelField($field); + return $this; + } + + + public function getRuleIdField() { + return $this->_rules->getIdField(); + } + + + public function setRuleIdField($field) { + $this->_rules->setIdField($field); + return $this; + } + + + public function setRuleLabelStartPos($value) { + $this->_rules->setLabelStartPos($value); + return $this; + } + + + public function setRuleLabelLength($value) { + $this->_rules->setLabelLength($value); + return $this; + } + + + public function getRuleLabelLength() { + return $this->_rules->getLabelLength(); + } + + + public function getRuleLabelStartPos() { + return $this->_rules->getLabelStartPos(); + } + + + public function rulesTruncateLabels($labels) { + return $this->_rules->truncateLabels($labels); + } + + + public function getRulesAsArray() { + return ['rule_zone' => $this->_rules->getZone(), + 'rule_label_field' => $this->_rules->getLabelField(), + 'rule_id_field' => $this->_rules->getIdField(), + 'rule_label_start_pos' => $this->_rules->getLabelStartPos(), + 'rule_label_length' => $this->_rules->getLabelLength()]; + } + + + public function withLabelAndIdRulesDo($closure) { + return $this->_rules->withLabelAndIdDo($closure); + } + + public function getListeSuggestion($recherche, $mode, $limite_resultat, $theme) { return $this->getLoader()->suggestFrom($recherche, $mode, $limite_resultat, $theme); } @@ -529,6 +668,15 @@ class Class_CodifThesaurus extends Storm_Model_Abstract { } + public function getOrCreateChildren($labels) { + return array_map( + function($label) { + return $this->getOrCreateChild(strtoupper($label), $label); + }, + array_filter($labels)); + } + + public function getChild($id_origine) { return Class_CodifThesaurus::getLoader() ->findFirstBy(['code' => $this->getCode(), @@ -540,20 +688,7 @@ class Class_CodifThesaurus extends Storm_Model_Abstract { public function withLabelRulesDo($closure) { - $rules = json_decode($this->getRules()); - list($field, $subfield) = explode('$',$rules->label); - return $closure(sprintf('%03d', trim($field)), - trim($subfield)); - } - - - public function getRulesLabel() { - if(!$rules = $this->getRules()) - return ''; - - $json = json_decode($rules); - - return $json ? $json->label : ''; + return $this->_rules->withLabelFieldDo($closure); } @@ -561,13 +696,8 @@ class Class_CodifThesaurus extends Storm_Model_Abstract { $this->_validateIdThesaurus(); $this->checkAttribute('libelle', '' != $this->getLibelle(), $this->_('Vous devez définir le libellé')); - if (!$this->getRules()) - return true; - $this->check('' != $this->getRules(), $this->_('Vous devez définir au moins une règle')); - $regles = str_replace(' ', '', $this->getRulesLabel()); - $this->check(preg_match('/^[0-9]{1,3}\$[a-z0-9]$/', $regles), - $this->_('La règle n\'est pas de la forme 686$a')); + $this->check($this->_rules->isValid(), $this->_rules->getErrorMessage()); } @@ -697,4 +827,26 @@ class Class_CodifThesaurus extends Storm_Model_Abstract { ? 0 : $this->numberOfChildrens(); } + + + public function authoritiesIndexSystems() { + if (!$this->getRuleIdField()) + return []; + + $systems = []; + + foreach(Class_IntProfilDonnees::findAllOfTypeAuthority() as $profile) + $systems = $this->_addIndexSystemsFromPrefsInto($profile->getIndexSystemsPrefs(), $systems); + + return array_filter($systems); + } + + + protected function _addIndexSystemsFromPrefsInto($prefs, $systems) { + foreach(Class_Notice_AuthorityIndexSystem::collectionFromPrefs($prefs) + ->filterByThesaurus($this) as $system) + $systems[] = $system; + + return $systems; + } } \ No newline at end of file diff --git a/library/Class/CodifThesaurus/Rules.php b/library/Class/CodifThesaurus/Rules.php new file mode 100644 index 0000000000000000000000000000000000000000..4315312db7dfb5ff54a5d8133a695c59707545fb --- /dev/null +++ b/library/Class/CodifThesaurus/Rules.php @@ -0,0 +1,125 @@ +<?php +/** + * Copyright (c) 2012-2018, 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_CodifThesaurus_Rules extends Class_Entity { + use Trait_Translator; + + protected + $_attribs = ['LabelStartPos' => 1, + 'LabelLength' => 0], + $_persistent_attribs = ['Zone', + 'LabelField', + 'IdField', + 'LabelStartPos', + 'LabelLength']; + + + public function initialize($datas) { + if (!$rules = json_decode($datas, true)) + return; + + foreach($this->_persistent_attribs as $field) + if (isset($rules[$field])) + $this->_attribs[$field] = $rules[$field]; + } + + + public function format() { + return $this->isEmpty() + ? null + : json_encode($this->asArray()); + } + + + public function asArray() { + return array_filter($this->_attribs, + function($key) { return in_array($key, $this->_persistent_attribs); }, + ARRAY_FILTER_USE_KEY); + } + + + public function isValid() { + if ($this->isEmpty()) + return true; + + if (!preg_match('/^[0-9]{3}/', $this->getZone())) { + $this->setErrorMessage($this->_('La zone doit être composée de 3 chiffres (001, 015, etc..)')); + return false; + } + + if (!preg_match('/^[a-z0-9]$/', $this->getLabelField())) { + $this->setErrorMessage($this->_('Le champ du libellé doit être un caractère alphanumérique')); + return false; + } + + if ($this->getIdField() && !preg_match('/^[a-z0-9]$/', $this->getIdField())) { + $this->setErrorMessage($this->_('Le champ de l\'identifiant doit être un caractère alphanumérique')); + return false; + } + + return true; + } + + + public function isEmpty() { + return !$this->getZone() && !$this->getLabelField() && !$this->getIdField(); + } + + + public function withLabelFieldDo($closure) { + if ((!$zone = $this->getZone()) + || (!$field = $this->getLabelField())) + return; + + return $closure($this->getZonePadded(), trim($field)); + } + + + public function truncateLabels($labels) { + return array_filter( + array_map([$this, 'truncateLabel'], $labels), + [$this, 'isValidLabel']); + } + + + public function truncateLabel($label) { + return substr($label, + max(0, $this->getLabelStartPos()-1), + $this->getLabelLength()); + } + + + public function isValidLabel($label) { + return is_string($label) && $label > ''; + } + + + public function withLabelAndIdDo($closure) { + if (!$this->isEmpty()) + return $closure($this->getZonePadded(), trim($this->getLabelField()), trim($this->getIdField())); + } + + + public function getZonePadded() { + return sprintf('%03d', trim($this->getZone())); + } +} diff --git a/library/Class/Codification.php b/library/Class/Codification.php index 9c4fa781c75fcdadf7ceea91c18d7e789bb731d1..2f0482bb9df7963fe359025abb15ee42eda7de63 100644 --- a/library/Class/Codification.php +++ b/library/Class/Codification.php @@ -48,13 +48,14 @@ * X: * Y: annexe * Z: tag + * 5: données autorités * 8: urlg * 9: nouveauté */ class Class_Codification { use Trait_Singleton, Trait_Translator; const - CHAMPS = 'JAKEFCNMDGHPILOR8QW', + CHAMPS = 'JAKEFCNMDGHPILOR8QW5', CODE_COLLECTION = 'C', CODE_EDITEUR = 'W', CODE_IDENTIFIANT = 'I', @@ -64,9 +65,10 @@ class Class_Codification { CODE_NOTES = 'O', CODE_PRIX = 'Q', CODE_RESUME = 'R', + CODE_AVAILABILITY='V', + CODE_AUTHORITY_DATAS='5', CODE_URL = '8', - CODE_NOUVEAUTE = '9', - CODE_AVAILABILITY='V'; + CODE_NOUVEAUTE = '9'; protected @@ -144,7 +146,8 @@ class Class_Codification { Class_Codification::CODE_AVAILABILITY => [ $this->_("En rayon"), $this->_("En rayon")], Class_Codification::CODE_NOUVEAUTE => [ $this->_("Nouveauté"), $this->_("Nouveauté")], Class_Codification::CODE_PRIX => [ $this->_("Prix"), $this->_("Prix")], - Class_CodifEmplacement::CODE_FACETTE => [ $this->_('Emplacement'), $this->_('Emplacement')]]; + Class_CodifEmplacement::CODE_FACETTE => [ $this->_('Emplacement'), $this->_('Emplacement')], + Class_Codification::CODE_AUTHORITY_DATAS => [ $this->_('Autorité'), $this->_('Autorité')],]; $this->addThesauriToNomChamps(); $this->setFacetDisplayNames(); diff --git a/library/Class/CosmoVar.php b/library/Class/CosmoVar.php index 5dbbd818a50a91f29b56ef6fcf26064e50c51cb8..f38c637cad15b0325e64f9a12321b7ced41289ef 100644 --- a/library/Class/CosmoVar.php +++ b/library/Class/CosmoVar.php @@ -115,7 +115,14 @@ class Class_CosmoVar extends Storm_Model_Abstract { $_table_name = 'variables', $_table_primary = 'clef', $_loader_class = 'Class_CosmoVarLoader', - $_fixed_id = true; + $_fixed_id = true, + $_default_attribute_values = ['commentaire' => '', + 'type_champ' => 0, + 'liste' => '', + 'groupe' => 0, + 'ordre' => 0, + 'verrou' => '', + 'hidden' => 0]; public static function get($name) { diff --git a/library/Class/Cosmogramme/Integration/CodifProvider.php b/library/Class/Cosmogramme/Integration/CodifProvider.php index 2057fedd9c49d677755230757589af96499ea86a..4bf5db29a7d8bd41a9c52f044ed67ac1e691a057 100644 --- a/library/Class/Cosmogramme/Integration/CodifProvider.php +++ b/library/Class/Cosmogramme/Integration/CodifProvider.php @@ -39,7 +39,12 @@ class Class_Cosmogramme_Integration_CodifProvider { } - public function getTopic($label) { + public function getSubject($label) { + return $this->getOrCreateSubject($label); + } + + + public function getOrCreateSubject($label) { // limit to the maximum size of code_alpha column in db to avoid duplicates $code = substr($this->_indexation->alphaMaj($label), 0, 255); return $this->_getFrom($label, $code, 'Class_CodifMatiere'); diff --git a/library/Class/Cosmogramme/Integration/PhasePrepareIntegrations.php b/library/Class/Cosmogramme/Integration/PhasePrepareIntegrations.php index 602a1eef9ba61f9fac8ba6d788362510e298fd9a..2836fe1805b724936f63e1212e564cfc2a7bc999 100644 --- a/library/Class/Cosmogramme/Integration/PhasePrepareIntegrations.php +++ b/library/Class/Cosmogramme/Integration/PhasePrepareIntegrations.php @@ -84,21 +84,27 @@ class Class_Cosmogramme_Integration_PhasePrepareIntegrations extends Class_Cosmo public function _runOne($majauto) { $id_bib = $majauto->getIdBib(); - if (!$bib = Class_IntBib::find($id_bib)) + + if (!$bib = Class_IntBib::find($id_bib)) { + $majauto->delete(); return; + } $this->_log ->log('<tr><td class="blank"><span class="bib">' . $bib->getNomCourt($id_bib) .'</span></td>' .'<td class="blank">'.$majauto->getNomFichier().'</td><td class="blank">'); + if (false !== strpos($majauto->getNomFichier(), 'http://') + || false !== strpos($majauto->getNomFichier(), 'https://')) + return $this->_prepareUrl($majauto); + + if (false !== strpos($majauto->getNomFichier(), '[DATE]')) + return $this->_runPattern($majauto); + $ftpfile = $this->_getFtpFile($majauto->getNomFichier()); $id_upload = Class_CosmoVar::get('ID_upload') + 1; $newfile = 'integre' . $id_upload . '.pan'; - if (false !== strpos($majauto->getNomFichier(), 'http://')) { - return $this->_prepareUrl($majauto); - } - if (!$ftpfile || !$this->getFileSystem()->is_file($ftpfile)) { $this->_log->log($this->_('pas de transfert pour : %s', $ftpfile) . '</td>'); return $this; @@ -127,8 +133,65 @@ class Class_Cosmogramme_Integration_PhasePrepareIntegrations extends Class_Cosmo } + protected function _runPattern($majauto) { + $selector = function($file) use($majauto) { + if (!$majauto->isFileNameValid($file)) + return false; + + if (!$majauto->isFileSizeValid($file)) { + $this->_log + ->log(sprintf('<span class="rouge">%s</span></td>', + $this->_('Le fichier est trop petit : %s o -> taille minimum attendue : %s o', + $file->getFileSize(), + $majauto->getFileSizeLimit()))); + return false; + } + + return true; + }; + + $files = (new Class_Cosmogramme_Integration_WaitingFiles) + ->getCollection() + ->select($selector); + + if ($files->isEmpty()) { + $this->_log->log($this->_('pas de transfert pour : %s', $majauto->getNomFichier()) . '</td>'); + return $this; + } + + foreach($files as $file) + $this->_runOnePattern($majauto, $file); + + return $this; + } + + + protected function _runOnePattern($majauto, $file) { + $filesystem = $this->getFilesystem(); + $newfile = $this->_getNextIntegrationFileName(); + + if (true !== $filesystem->rename($file->getId(), $this->_integration_path . $newfile)) { + $this->_log + ->log(sprintf('<span class="rouge">%s</span></td>', + $this->_('impossible de transférer %s vers %s', $file->getId(), $newfile))); + + $this->_incrementData('traitement_erreurs'); + return; + } + + $this->_log + ->log(sprintf('<span class="vert">%s</span></td>', + $this->_('transfert de %s vers %s', $file->getId(), $newfile))); + + + $this->_newIntegration($newfile, $majauto); + Class_CosmoVar::setValueOf('ID_upload', Class_CosmoVar::get('ID_upload') + 1); + } + + protected function _prepareUrl($majauto) { $uri = $majauto->getNomFichier(); + if (Class_Cosmogramme_Integration::findFirstBy(['traite' => 'non', 'fichier' => $uri])) return $this; @@ -218,4 +281,9 @@ class Class_Cosmogramme_Integration_PhasePrepareIntegrations extends Class_Cosmo 'traite' => 'non']); $integration->save(); } + + + protected function _getNextIntegrationFileName() { + return 'integre' . (Class_CosmoVar::get('ID_upload') + 1) . '.pan'; + } } diff --git a/library/Class/Cosmogramme/Integration/PhasePseudoRecord.php b/library/Class/Cosmogramme/Integration/PhasePseudoRecord.php index 3f47f68b5248bc4c843911d7f736b120105638a7..e5040754c2fc215c8b0e6d0aaba2c597ded71469 100644 --- a/library/Class/Cosmogramme/Integration/PhasePseudoRecord.php +++ b/library/Class/Cosmogramme/Integration/PhasePseudoRecord.php @@ -24,7 +24,9 @@ abstract class Class_Cosmogramme_Integration_PhasePseudoRecord extends Class_Cosmogramme_Integration_PhaseAbstract { use Trait_MemoryCleaner; - protected $_model_id_field, $_memory_cleaner; + protected + $_model_id_field, + $_previous_page = []; /** @var Trait_Indexable */ protected $_model_name; @@ -53,6 +55,9 @@ abstract class Class_Cosmogramme_Integration_PhasePseudoRecord if ($this->isTimeOut()) return; + if ($this->_isPreviousPage($models)) + break; + $this->_runPage($models); $this->_cleanMemory(); } @@ -61,6 +66,16 @@ abstract class Class_Cosmogramme_Integration_PhasePseudoRecord } + protected function _isPreviousPage($page) { + if ($this->_previous_page + && !array_filter(array_diff($this->_previous_page, $page))) + return true; + + $this->_previous_page = $page; + return false; + } + + protected function _runPage($models) { $this->_log->log($this->_getData('nombre') . '<br>'); foreach($models as $model) { diff --git a/library/Class/Cosmogramme/Integration/PhasePseudoRecordAlbum.php b/library/Class/Cosmogramme/Integration/PhasePseudoRecordAlbum.php index 4a798cd03e7c0d376b00a98fbb48d2a68a9566a0..c616e66bbee291dc5680bc66bc4f914452c5b5e8 100644 --- a/library/Class/Cosmogramme/Integration/PhasePseudoRecordAlbum.php +++ b/library/Class/Cosmogramme/Integration/PhasePseudoRecordAlbum.php @@ -25,10 +25,39 @@ class Class_Cosmogramme_Integration_PhasePseudoRecordAlbum extends Class_Cosmogr protected $_label = 'Pseudo-notices : RESSOURCES NUMERIQUES'; protected $_model_name = 'Class_Album'; + protected $_last_update_date; /** @return array **/ protected function _previousPhaseIds() { return [0.4]; } + + + protected function _loadPage() { + $this->_cleanMemory(); + return Class_Album::findAllAfter($this->_getData('pointeur_reprise'), + $this->_getData('pointeur')); + } + + + protected function _runOne($model) { + parent::_runOne($model); + $this->_last_update_date = $model->getDateMaj(); + } + + + protected function _init($phase) { + parent::_init($phase); + $phase->setData('pointeur', + ($last_date = Class_CosmoVar::getValueOf('date_maj_albums')) + ? $last_date + : '0000-00-00 00:00:00'); + } + + + protected function _summarize() { + Class_CosmoVar::setValueOf('date_maj_albums', $this->getCurrentDateTime()); + parent::_summarize(); + } } diff --git a/library/Class/Cosmogramme/Integration/Record/Authority.php b/library/Class/Cosmogramme/Integration/Record/Authority.php index 1d596dd64dabc38288ca89114e374d323726ebdf..ce051f842a4aee4d88382a8e5fdf3a23bc031348 100644 --- a/library/Class/Cosmogramme/Integration/Record/Authority.php +++ b/library/Class/Cosmogramme/Integration/Record/Authority.php @@ -33,7 +33,7 @@ class Class_Cosmogramme_Integration_Record_Authority { $this->_integration = $integration; $this->_reader = new Class_NoticeUnimarc_Writer(); $this->_indexation = Class_Indexation::getInstance(); - $this->_authority_type = new Class_Cosmogramme_Integration_Record_AuthorityType(); + $this->_authority_type = new Class_Notice_AuthorityType(); } @@ -64,51 +64,41 @@ class Class_Cosmogramme_Integration_Record_Authority { } - protected function _rejectWith($message) { - return Class_Cosmogramme_Integration_Record_AuthorityResult::newRejectWith($message); - } + /** @param $relation Class_Notice_AuthorityRelation */ + public function createRelated($relation) { + if (!$relation) + return $this; + $rules = []; + if ($cataloging_rule = $this->_reader->get_subfield('152', 'a')) + $rules['a'] = $cataloging_rule[0]; + if ($index_system = $this->_reader->get_subfield('152', 'b')) + $rules['b'] = $index_system[0]; - protected function _encoding() { - return $this->_integration->getProfilDonnees()->getAccents(); - } - - - protected function _getFacets() { - $facets = []; + $marc = (new Class_Notice_AuthorityPartial) + ->newWith($relation->authorityType(), $relation->id(), $relation->label(), $rules) + ->render(); - $fields = Class_Cosmogramme_Integration_Record_AuthorityRelation::possibleFields(); - foreach($fields as $field) - $facets = array_merge($facets, $this->_facetsFromField($field)); + $record = $this->_save($relation->id(), + ['unimarc' => $marc, + 'type' => Class_Notice::TYPE_AUTHORITY, + 'type_doc' => $relation->authorityType(), + 'titres' => $this->_indexation->getFulltext($relation->label()), + 'alpha_titre' => $this->_indexation->codeAlphaTitre($relation->label())]); - return $facets; + $this->_saveCodifFor($relation->authorityType(), $relation->label()); + return $this; } - protected function _facetsFromField($field) { - $facets = []; - foreach($this->_reader->get_subfield($field) as $relation) - $facets[] = $this->_facetFromRelated($relation, $field); - - return array_filter($facets); + protected function _rejectWith($message) { + return Class_Cosmogramme_Integration_Record_AuthorityResult::newRejectWith($message); } - protected function _facetFromRelated($relation, $field) { - $relation = $this->_reader->decoupe_bloc_champ($relation); - $relation = new Class_Cosmogramme_Integration_Record_AuthorityRelation($relation, $field); - if (!$relation->isValid()) - return; - - $record = $this->_save($relation->id(), - ['type' => Class_Notice::TYPE_AUTHORITY, - 'type_doc' => $relation->authorityType(), - 'titres' => $this->_indexation->getFulltext($relation->label()), - 'alpha_titre' => $this->_indexation->codeAlphaTitre($relation->label())]); - - $this->_saveCodifFor($relation->authorityType(), $relation->label()); - - return $relation->facet(); + protected function _getFacets() { + return (new Class_Cosmogramme_Integration_Record_AuthorityFacets()) + ->getFacets($this->_reader, [$this, 'createRelated'], $this->_indexSystems()); } @@ -138,12 +128,13 @@ class Class_Cosmogramme_Integration_Record_Authority { protected function _update($item, $record) { - $item->setToDelete(false)->save(); if (!$existing_record = $item->getNotice()) return; - if (array_key_exists('unimarc', $record) - && '' != $record['unimarc']) + $item->setToDelete(false)->save(); + + if (($catalog_agency = $existing_record->get_subfield('801', 'b')) + && Class_Notice_AuthorityPartial::DEFAULT_AGENCY === $catalog_agency[0]) $existing_record->updateAttributes($record); $existing_record @@ -156,8 +147,8 @@ class Class_Cosmogramme_Integration_Record_Authority { protected function _saveCodifFor($type, $label) { - if ('j' == $type) - $this->getCodifProvider()->getTopic($label); + if (Class_Notice_AuthorityType::SUBJECT == $type) + $this->getCodifProvider()->getOrCreateSubject($label); } @@ -211,6 +202,17 @@ class Class_Cosmogramme_Integration_Record_Authority { } + protected function _encoding() { + return $this->_integration->getProfilDonnees()->getAccents(); + } + + + protected function _indexSystems() { + $prefs = $this->_integration->getProfilDonnees()->getIndexSystemsPrefs(); + return Class_Notice_AuthorityIndexSystem::collectionFromPrefs($prefs); + } + + protected function getCodifProvider() { if (null == $this->_codif_provider) $this->_codif_provider = (new Class_Cosmogramme_Integration_CodifProvider) diff --git a/library/Class/Cosmogramme/Integration/Record/AuthorityFacets.php b/library/Class/Cosmogramme/Integration/Record/AuthorityFacets.php new file mode 100644 index 0000000000000000000000000000000000000000..7e4e9ce8e01be664a253b7709761fb6b33b76a13 --- /dev/null +++ b/library/Class/Cosmogramme/Integration/Record/AuthorityFacets.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright (c) 2012-2018, 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_Integration_Record_AuthorityFacets { + protected + $_reader, + $_create_related_callback, + $_index_systems; + + + public function getFacets($reader, $create_related_callback, $index_systems) { + $this->_reader = $reader; + $this->_create_related_callback = $create_related_callback; + $this->_index_systems = $index_systems; + + return array_merge($this->_facetsFromFields(), + $this->_facetsFromIndexSystems()); + } + + + protected function _facetsFromFields() { + $facets = []; + foreach (Class_Notice_AuthorityRelation::possibleFields() as $field) + $facets = array_merge($facets, $this->_facetsFromField($field)); + + return $facets; + } + + + protected function _facetsFromField($field) { + $facets = []; + foreach($this->_reader->get_subfield($field) as $relation) + $facets[] = $this->_facetFromRelated($relation, $field); + + return array_filter($facets); + } + + + protected function _facetFromRelated($relation, $field) { + $relation = $this->_reader->decoupe_bloc_champ($relation); + $relation = new Class_Notice_AuthorityRelation($relation, $field); + if (!$relation->isValid()) + return; + + $this->_createRelated($relation); + + return $relation->getFacetCode(); + } + + + protected function _createRelated($relation) { + if (!$this->_create_related_callback) + return; + + call_user_func($this->_create_related_callback, $relation); + } + + + protected function _facetsFromIndexSystems() { + $rule = ($rules = $this->_reader->get_subfield('152', 'a')) ? reset($rules) : null; + $system = ($systems = $this->_reader->get_subfield('152', 'b')) ? reset($systems) : null; + + if (!$rule && !$system) + return []; + + $facets = []; + foreach ($this->_index_systems as $index_system) + $facets[] = $this->_facetsFromIndexSystem($index_system, $rule, $system); + + return array_filter($facets); + } + + + protected function _facetsFromIndexSystem($index_system, $rule, $system) { + return ($facet = $index_system->facetFor($rule, $system)) + ? $facet + : null; + } +} diff --git a/library/Class/Cosmogramme/Integration/Record/BibliographicDynamicFacets.php b/library/Class/Cosmogramme/Integration/Record/BibliographicDynamicFacets.php new file mode 100644 index 0000000000000000000000000000000000000000..4ec66244804ce7c620a28e228175685102c21122 --- /dev/null +++ b/library/Class/Cosmogramme/Integration/Record/BibliographicDynamicFacets.php @@ -0,0 +1,135 @@ +<?php +/** + * Copyright (c) 2012-2018, 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_Integration_Record_BibliographicDynamicFacets { + public function thesauriOf($reader, $int_bib) { + $thesauri = []; + + foreach (Class_CodifThesaurus::findAllBy(['rules not' => null]) as $thesaurus) + $thesauri = array_merge($thesauri, $this->_newFor($thesaurus, $int_bib)->thesauriOf($reader)); + + return $thesauri; + } + + + protected function _newFor($thesaurus, $int_bib) { + return $int_bib && ($index_systems = $thesaurus->authoritiesIndexSystems()) + ? new Class_Cosmogramme_Integration_Record_BibliographicDynamicFacets_Authority($thesaurus, $index_systems, $int_bib) + : new Class_Cosmogramme_Integration_Record_BibliographicDynamicFacets_Simple($thesaurus); + } +} + + + + +class Class_Cosmogramme_Integration_Record_BibliographicDynamicFacets_Simple { + protected $_thesaurus; + + public function __construct($thesaurus) { + $this->_thesaurus = $thesaurus; + } + + + public function thesauriOf($reader) { + $labels = $this->_thesaurus + ->withLabelRulesDo( + function($field, $subfield) use($reader) { + return $reader->get_subfield($field, $subfield); + }); + if ($this->_thesaurus->getRuleLabelLength()) + $labels = $this->_thesaurus->rulesTruncateLabels($labels); + + return $this->_thesaurus->getOrCreateChildren($labels); + } +} + + + + +class Class_Cosmogramme_Integration_Record_BibliographicDynamicFacets_Authority + extends Class_Cosmogramme_Integration_Record_BibliographicDynamicFacets_Simple { + + protected + $_index_systems, + $_int_bib, + $_reader; + + + public function __construct($thesaurus, $index_systems, $int_bib) { + parent::__construct($thesaurus); + $this->_index_systems = $index_systems; + $this->_int_bib = $int_bib; + } + + + public function thesauriOf($reader) { + $this->_reader = $reader; + + $closure = function($zone, $label, $id) { + return $this->_thesauriOfZone($zone, $label, $id); + }; + + return $this->_thesaurus->withLabelAndIdRulesDo($closure); + } + + + protected function _thesauriOfZone($zone, $label, $id) { + $children = []; + foreach($this->_reader->get_subfield($zone) as $marc_zone) + $children = $this->_thesauriOfMarcZone($marc_zone, $label, $id, $children); + + return $children; + } + + + protected function _thesauriOfMarcZone($marc_zone, $label, $id, $children) { + $datas = $this->_zoneDatas($marc_zone, $label, $id); + if (!$heading = $datas['heading']) + return $children; + + $children[] = $child = $this->_thesaurus->getOrCreateChild(strtoupper($heading), $heading); + + if (!$record_id = $datas['record_id']) + return $children; + + foreach($this->_index_systems as $system) + $system->ensureRecordForThesaurus($heading, $record_id, $this->_thesaurus, $this->_int_bib, $child); + + return $children; + } + + + protected function _zoneDatas($marc_zone, $label, $id) { + $values = ['heading' => null, 'record_id' => null]; + + $fields = $this->_reader->decoupe_bloc_champ($marc_zone); + foreach($fields as $field) { + if ($field['code'] == $label) + $values['heading'] = trim($field['valeur']); + + if ($field['code'] == $id) + $values['record_id'] = trim($field['valeur']); + } + + return $values; + } +} \ No newline at end of file diff --git a/library/Class/Cosmogramme/Integration/WaitingFiles.php b/library/Class/Cosmogramme/Integration/WaitingFiles.php new file mode 100644 index 0000000000000000000000000000000000000000..fd921d81b982ce85a140b31c82c4bd917f15744a --- /dev/null +++ b/library/Class/Cosmogramme/Integration/WaitingFiles.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright (c) 2012-2018, 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_Integration_WaitingFiles { + public function getCollection() { + Class_FileManager::beOpenBar(); + Class_FileManager_FileSystem::beUnlimited(); + + $files = []; + foreach(Class_FileManager::directories(Class_CosmoVar::get('ftp_path')) as $directory) + foreach(Class_FileManager::files($directory->getPath()) as $file) + $files[] = $file; + + usort($files, + function($a, $b) + { + if ($a->getFileMTime() === $b->getFileMTime()) + return 0; + + return $a->getFileMTime() > $b->getFileMTime() ? 1 : -1; + }); + + return new Storm_Collection($files); + } +} diff --git a/library/Class/Exemplaire.php b/library/Class/Exemplaire.php index ff22fc58a85d2dda4419b5dce43a5b7c4367f49d..bb800146d89f18c5f61adc5da0b27f91e6530f3a 100644 --- a/library/Class/Exemplaire.php +++ b/library/Class/Exemplaire.php @@ -50,6 +50,12 @@ class Class_ExemplaireLoader extends Storm_Model_Loader { return $matches->first(); } + + + public function findFirstAuthorityItemByOriginId($id) { + return Class_Exemplaire::findFirstBy(['type' => Class_Notice::TYPE_AUTHORITY, + 'id_origine' => $id]); + } } diff --git a/library/Class/FileManager.php b/library/Class/FileManager.php index 7cbb50b2c84276c5ace2018ddedb085e8dad44a0..89de300e1dfa799267b4295d40a1cda068157c24 100644 --- a/library/Class/FileManager.php +++ b/library/Class/FileManager.php @@ -37,6 +37,7 @@ class Class_FileManager extends Class_Entity { 'BrowserParam' => '', 'MTime' => '', 'Size' => '', + 'FileSize' => 0, 'Dir' => '', 'Dimensions' => '', 'Type' => '', @@ -571,4 +572,9 @@ class Class_FileManager extends Class_Entity { public function getContent() { return static::getFileSystem()->getContent($this->getRealpath()); } + + + public function readfile() { + return static::getFileSystem()->readfile($this->getRealpath()); + } } \ No newline at end of file diff --git a/library/Class/FileManager/FileSystem.php b/library/Class/FileManager/FileSystem.php index 7289df022db2dc50a48e8b8d18283eb06a328280..120d2a4d19418f350371ff1c2d7b6e78d2ae2b2d 100644 --- a/library/Class/FileManager/FileSystem.php +++ b/library/Class/FileManager/FileSystem.php @@ -26,12 +26,23 @@ class Class_FileManager_FileSystem { const LISTING_LIMIT = 200; + protected static $_limited = true; protected $_cached_paths = [], $_oversized = []; + public static function beUnlimited() { + static::$_limited = false; + } + + + public static function reset() { + static::$_limited = true; + } + + public function directoriesAt($path) { return $this->_filterEntriesAt($path, [$this, 'directoryAt']); } @@ -45,7 +56,7 @@ class Class_FileManager_FileSystem { protected function _filterEntriesAt($path, $callback = null) { $items = $this->_glob($path, true); - if(Class_FileManager_FileSystem::LISTING_LIMIT < count($items)) { + if (static::$_limited && Class_FileManager_FileSystem::LISTING_LIMIT < count($items)) { $this->_oversized[] = $path; $items = array_slice($items, 0, Class_FileManager_FileSystem::LISTING_LIMIT); } @@ -289,6 +300,8 @@ class Class_FileManager_FileSystem { $basename = $info['basename']; $path = implode('/', array_filter([$dirname, $basename])); + $size = filesize($path); + $mtime = filemtime($path); return (new Class_FileManager) ->setId($path) @@ -300,8 +313,10 @@ class Class_FileManager_FileSystem { ->setParentPath($dirname) ->setWritable($this->_isWritable($path)) ->setBrowserParam('browser') - ->setMTime($this->_ISOTime(filemtime($path))) - ->setSize($this->_humanFilesize(filesize($path))); + ->setMTime($this->_ISOTime($mtime)) + ->setFileMTime($mtime) + ->setSize($this->_humanFilesize($size)) + ->setFileSize($size); } @@ -373,4 +388,10 @@ class Class_FileManager_FileSystem { public function getContent($path) { return file_get_contents($path); } + + + public function readfile($path) { + ob_end_clean(); + return readfile($path); + } } \ No newline at end of file diff --git a/library/Class/Indexation/PseudoNotice.php b/library/Class/Indexation/PseudoNotice.php index 16f58ab1afb965985e0037199e278cdb6a3d4ed9..7d2670310671858c11e13738bd37d2443a4e5cc8 100644 --- a/library/Class/Indexation/PseudoNotice.php +++ b/library/Class/Indexation/PseudoNotice.php @@ -80,12 +80,16 @@ class Class_Indexation_PseudoNotice { if (!$this->_ensureItem()) return false; + $this->_updateLinkToRecord(); + $this->_index(); + return true; + } + + + protected function _updateLinkToRecord() { $this->_model ->updateAttributes([$this->_id_notice => $this->_notice->getId()]) ->save(); - - $this->_index(); - return true; } @@ -235,9 +239,6 @@ class Class_Indexation_PseudoNotice { $this->_notice->save(); $this->_indexItem(); - - $this->_model->setNotice($this->_notice) - ->save(); } @@ -437,6 +438,13 @@ class Class_Indexation_PseudoNotice_Album extends Class_Indexation_PseudoNotice{ } + protected function _updateLinkToRecord() { + $this->_model + ->setNoticeId($this->_notice->getId()) + ->saveWithoutDateMaj(); + } + + protected function _modelIdAcceptVisitor($visitor) {} diff --git a/library/Class/IntBib.php b/library/Class/IntBib.php index 07fc38b00cf2a43b7d489a309c31ac0359554993..64d848c9b15f5d41cbfc9936145500581a55f536 100644 --- a/library/Class/IntBib.php +++ b/library/Class/IntBib.php @@ -48,7 +48,7 @@ class IntBibLoader extends Storm_Model_Loader { } - public function isSingleNanook($patrons_closure = null) { + public function isSingleNanook() { return (new Class_IntBib_SingleNanook())->isSingle(Class_IntBib::findAll()); } @@ -58,6 +58,11 @@ class IntBibLoader extends Storm_Model_Loader { } + public function isSingleKoha() { + return (new Class_IntBib_SingleKoha())->isSingle(Class_IntBib::findAll()); + } + + public function findAllNanookWithPreRegistration() { $collection = new Storm_Model_Collection(Class_IntBib::findAll()); $combo = $collection @@ -109,6 +114,7 @@ class Class_IntBib extends Storm_Model_Abstract { const SIGB_PERGAME = 1; const SIGB_KOHA = 12; const SIGB_NANOOK = 13; + const SIGB_ORPHEE = 3; const TYPE = 'type'; const URL_SERVER = 'url_server'; @@ -308,6 +314,11 @@ class Class_IntBib extends Storm_Model_Abstract { } + public function isKoha() { + return static::SIGB_KOHA == $this->getSigb(); + } + + public function isCommKoha() { return Class_IntBib::COM_KOHA == $this->getCommSigb(); } diff --git a/library/Class/IntBib/SingleKoha.php b/library/Class/IntBib/SingleKoha.php new file mode 100644 index 0000000000000000000000000000000000000000..6fcdecf2c3337e9228948f8c0c7ab3c881ff73b5 --- /dev/null +++ b/library/Class/IntBib/SingleKoha.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright (c) 2012-2019, 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_SingleKoha extends Class_IntBib_SingleSigb { + protected function _isSigb($library) { + return $library->isKoha(); + } +} \ No newline at end of file diff --git a/library/Class/IntBib/SingleNanook.php b/library/Class/IntBib/SingleNanook.php index 22ff4c11b49917bc0b5bb83834a8464145b5877d..f3b6acdf30cb8ed0777a6f05a30c22c239dc071a 100644 --- a/library/Class/IntBib/SingleNanook.php +++ b/library/Class/IntBib/SingleNanook.php @@ -20,42 +20,8 @@ */ -class Class_Intbib_SingleNanook { - protected $_server = null; - - public function isSingle($models) { - if(!$models) - return false; - - $this->_server = null; - foreach($models as $library) { - if (!$this->_isLibraryNanook($library)) - return false; - } - return true; - } - - - public function isSinglePatrons($models) { - $aCollection = (new Storm_Model_Collection($models)) - ->select(function($model) - { - return $model->hasPatronImport(); - }); - - return $this->isSingle($aCollection->getArrayCopy()); - } - - - protected function _isLibraryNanook($library) { - if (!$library->isNanook()) - return false; - - if (null == $this->_server) { - $this->_server = $library->getUrlServer(); - return true; - } - - return $this->_server == $library->getUrlServer(); +class Class_IntBib_SingleNanook extends Class_IntBib_SingleSigb { + protected function _isSigb($library) { + return $library->isNanook(); } } \ No newline at end of file diff --git a/library/Class/IntBib/SingleSigb.php b/library/Class/IntBib/SingleSigb.php new file mode 100644 index 0000000000000000000000000000000000000000..2bffee507c9c350c33d355decebbeb9066cf89cd --- /dev/null +++ b/library/Class/IntBib/SingleSigb.php @@ -0,0 +1,65 @@ +<?php +/** + * Copyright (c) 2012-2019, 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 Class_IntBib_SingleSigb { + protected $_server = null; + + public function isSingle($models) { + if(!$models) + return false; + + $this->_server = null; + foreach($models as $library) { + if (!$this->_isSigbAndSameServer($library)) + return false; + } + return true; + } + + + public function isSinglePatrons($models) { + $aCollection = (new Storm_Model_Collection($models)) + ->select(function($model) + { + return $model->hasPatronImport(); + }); + + return $this->isSingle($aCollection->getArrayCopy()); + } + + + + protected function _isSigbAndSameServer($library) { + if (!$this->_isSigb($library)) + return false; + + if (null == $this->_server) { + $this->_server = $library->getUrlServer(); + return true; + } + + return $this->_server == $library->getUrlServer(); + } + + + abstract protected function _isSigb($library); +} \ No newline at end of file diff --git a/library/Class/IntMajAuto.php b/library/Class/IntMajAuto.php index 60cfe68fb2cb1d12df11e486ef5edb16548925b2..41df414e0f0b4a5045fd27d373e1d019002de3ff 100644 --- a/library/Class/IntMajAuto.php +++ b/library/Class/IntMajAuto.php @@ -20,6 +20,8 @@ */ class Class_IntMajAuto extends Storm_Model_Abstract { + use Trait_Translator; + const OP_PARTIAL_IMPORT = 0; const OP_ITEMS_DELETION = 1; const OP_FULL_IMPORT = 2; @@ -29,7 +31,87 @@ class Class_IntMajAuto extends Storm_Model_Abstract { protected $_table_primary = 'id_prog'; protected $_belongs_to = ['int_bib' => ['model' => 'Class_IntBib', - 'referenced_in' => 'id_bib']]; -} + 'referenced_in' => 'id_bib'], + 'profil_donnees' => ['model' => 'Class_IntProfilDonnees', + 'referenced_in' => 'profil']]; + + /** + * @param $file_manager Class_FileManager + * @return boolean + */ + public function isFileNameValid($file_manager) { + if ($file_manager->getId() == $this->getNomFichier()) + return true; + + if (false === strpos($this->getNomFichier(), '[DATE]')) + return false; + + $folder = ($parent = $file_manager->getParent()) ? $parent->getName() : ''; + + if (false !== strpos($this->getNomFichier(), '/[DATE]') + && false === strpos($this->getNomFichier(), $folder . '/[DATE]')) + return false; + + $parts = explode('[DATE]', $this->getNomFichier()); + + return ($suffix = end($parts)) + ? (substr($file_manager->getName(), -strlen($suffix)) == $suffix) + : false; + } + + + /** + * @param $file_manager Class_FileManager + * @return boolean + */ + public function isFileSizeValid($file_manager) { + return ($size_limit = $this->getFileSizeLimit()) + ? $file_manager->getFileSize() >= $size_limit + : true; + } + + + public function getFileSizeLimit() { + if (!$profil = $this->getProfilDonnees()) + return 0; -?> \ No newline at end of file + if (!$profil->isBiblioRecords()) + return 0; + + if (!$this->isTotal()) + return 0; + + return (int)$this->getTailleMinImportTotal() * 1024 * 1024; + } + + + public function isTotal() { + return static::OP_FULL_IMPORT == (int)$this->getTypeOperation(); + } + + + public function getLibraryLabel() { + return ($lib = $this->getIntBib()) + ? $lib->getLabel() + : ''; + } + + + public function getOperationLabel() { + $map = [static::OP_PARTIAL_IMPORT => $this->_('Import incrémentiel'), + static::OP_ITEMS_DELETION => $this->_('Suppression d\'exemplaires'), + static::OP_FULL_IMPORT => $this->_('Import total'), + static::OP_DELETE_PERGAME_HEADER => $this->_('Suppression fichier d\'en-tête Pergame')]; + + return array_key_exists($this->getTypeOperation(), $map) + ? $map[$this->getTypeOperation()] + : ''; + } + + + public function getDataProfileLabel() { + return ($profile = $this->getProfilDonnees()) + ? $profile->getLibelle() + : ''; + } +} diff --git a/library/Class/IntProfilDonnees.php b/library/Class/IntProfilDonnees.php index f7654f4491d973d9d66c4dc490ecd534f5f3b56f..066498d0b4a525b495315dabdcbce4205404a87d 100644 --- a/library/Class/IntProfilDonnees.php +++ b/library/Class/IntProfilDonnees.php @@ -87,14 +87,17 @@ class IntProfilDonneesLoader extends Storm_Model_Loader { public function getFormatsForType($type) { - if($this->isTypeCSV($type)) + if ($this->isTypeCSV($type)) return $this->getCSVFormats(); - if($type == Class_IntProfilDonnees::FT_RECORDS) - return $this->getRecordsFormats(); + if (Class_IntProfilDonnees::isRecordFileType($type)) + return Class_IntProfilDonnees::getRecordsFormats(); - if($type == Class_IntProfilDonnees::FT_PATRONS) - return $this->getPatronsFormats(); + if (Class_IntProfilDonnees::isPatronFileType($type)) + return Class_IntProfilDonnees::getPatronsFormats(); + + if (Class_IntProfilDonnees::isAuthorityFileType($type)) + return Class_IntProfilDonnees::getAuthorityFormats(); return $this->getFormats(); } @@ -138,6 +141,12 @@ class IntProfilDonneesLoader extends Storm_Model_Loader { } + public function getAuthorityFormats() { + return array_intersect_key($this->getFormats(), + [Class_IntProfilDonnees::FORMAT_UNIMARC => '']); + } + + public function isFormatCSV($format) { return in_array($format, [Class_IntProfilDonnees::FORMAT_CSV, Class_IntProfilDonnees::FORMAT_TABBED_ASCII, @@ -154,6 +163,12 @@ class IntProfilDonneesLoader extends Storm_Model_Loader { } + public function isFormatDublinCoreOrBiblionDemand($format) { + return in_array($format, [Class_IntProfilDonnees::FORMAT_DUBLIN_CORE, + Class_IntProfilDonnees::FORMAT_BIBLIONDEMAND]); + } + + public function getLoanFields() { return Class_CosmoVar::getList('champs_pret'); } @@ -223,6 +238,41 @@ class IntProfilDonneesLoader extends Storm_Model_Loader { return ['' => '', '#' => '$0'] + array_combine($keys, $values); } + + + public function isRecordFileType($type) { + return Class_IntProfilDonnees::FT_RECORDS === (int)$type; + } + + + public function isPatronFileType($type) { + return Class_IntProfilDonnees::FT_PATRONS === (int)$type; + } + + + public function isLoanFileType($type) { + return Class_IntProfilDonnees::FT_LOANS === (int)$type; + } + + + public function isHoldFileType($type) { + return Class_IntProfilDonnees::FT_HOLDS === (int)$type; + } + + + public function isBasketFileType($type) { + return Class_IntProfilDonnees::FT_BASKETS === (int)$type; + } + + + public function isAuthorityFileType($type) { + return Class_IntProfilDonnees::FT_AUTHORITY === (int)$type; + } + + + public function findAllOfTypeAuthority() { + return Class_IntProfilDonnees::findAllBy(['type_fichier' => Class_IntProfilDonnees::FT_AUTHORITY]); + } } @@ -237,11 +287,13 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract { FT_HOLDS = 3, FT_BASKETS = 4, FT_AUTHORITY = 5, + ENCODING_UTF8 = 0, ENCODING_ISO2709 = 1, ENCODING_WINDOWS_ANSI = 2, ENCODING_ASCII_DOS = 3, ENCODING_MARC21 = 4, + FORMAT_UNIMARC = 0, FORMAT_TABBED_ASCII = 1, FORMAT_SEMI_COLON_ASCII = 2, @@ -254,17 +306,20 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract { FORMAT_DUBLIN_CORE = 9, FORMAT_CG68_ARCHIVES = 10, FORMAT_BIBLIONDEMAND = 11, + SERIAL_FORMAT_NONE = 0, SERIAL_FORMAT_PERGAME = 1, SERIAL_FORMAT_ALOES_INDEXPRESS = 2, SERIAL_FORMAT_KOHA = 3, SERIAL_FORMAT_ORPHEE = 4, + NOVELTY_DATE_FORMAT_NONE = 0, NOVELTY_DATE_FORMAT_AAAA_MM_JJ = 1, NOVELTY_DATE_FORMAT_AAAAMMJJ = 2, NOVELTY_DATE_FORMAT_VALUES = 3, NOVELTY_DATE_FORMAT_JJ_MM_AAAA = 4, NOVELTY_DATE_FORMAT_SLASHED_JMAAAA = 5, + FIELD_TYPE_DOC_RECOGNITION = 'type_doc', FIELD_ITEM_ZONE = 'item_zone', FIELD_ITEM_TYPE_DOC = 'champ_type_doc', @@ -277,6 +332,7 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract { FIELD_ITEM_AVAILABILITY = 'champ_availability', FIELD_ITEM_URL = 'champ_url', FIELD_ITEM_ID_ORIGINE = 'champ_id_origine', + PROFILE_FIELDS = 'champs', PROFILE_DOC_TYPES = 'type_doc', PROFILE_NOVELTY = 'jours', @@ -287,10 +343,13 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract { PROFILE_ITEM_FIELDS = 'csv_item_fields', PROFILE_HOLD_FIELDS = 'holds', PROFILE_CART_FIELDS = 'carts', + PROFILE_INDEX_SYSTEMS_FIELDS = 'index_systems', + NOVELTY_ZONE = 'zone', NOVELTY_FIELD = 'champ', NOVELTY_FORMAT = 'format', NOVELTY_VALUES = 'valeurs', + XML_PATRON_FIELD = 'xml_balise_abonne', XML_PATRON_FIELDS = 'xml_champs_abonne'; @@ -671,11 +730,11 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract { 'attributs' => [['type_doc' => [[ 'code' => '0', 'label' => '', 'zone_995' => '' ], - [ 'code' => '1', 'label' => 'am;na', 'zone_995' => '' ], - [ 'code' => '2', 'label' => 'as', 'zone_995' => ''], - [ 'code' => '3', 'label' => 'i;j', 'zone_995' => ''], - [ 'code' => '4', 'label' => 'g','zone_995' => ''], - [ 'code' => '5', 'label' => 'l;m', 'zone_995' => ''], + [ 'code' => '1', 'label' => '', 'zone_995' => '' ], + [ 'code' => '2', 'label' => '', 'zone_995' => ''], + [ 'code' => '3', 'label' => '', 'zone_995' => ''], + [ 'code' => '4', 'label' => '','zone_995' => ''], + [ 'code' => '5', 'label' => '', 'zone_995' => ''], [ 'code' => '6', 'label' => '', 'zone_995' => '' ], [ 'code' => '7', 'label' => '', 'zone_995' => '' ], [ 'code' => '8', 'label' => '', 'zone_995' => ''], @@ -683,6 +742,7 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract { [ 'code' => '10', 'label' => '', 'zone_995' => 'kio'], [ 'code' => '11', 'label' => '', 'zone_995' => 'tou'], [ 'code' => '12', 'label' => '', 'zone_995' => 'art'], + [ 'code' => '13', 'label' => '', 'zone_995' => 'sto'], ], self::FIELD_ITEM_BARCODE => 'f', self::FIELD_ITEM_COTE => 'k', @@ -1020,6 +1080,11 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract { } + public function getIndexSystemsPrefs() { + return $this->getProfilePrefs()->getIndexSystemsPrefs(); + } + + public function getProfilePrefs() { if(!$this->_profile_prefs) $this->_profile_prefs = (new Class_ProfilePrefs())->setDatas($this->toArray()); @@ -1032,4 +1097,3 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract { return $this->getTypeFichier() > 9; } } -?> \ No newline at end of file diff --git a/library/Class/ListViewModeDescription/Thesauri.php b/library/Class/ListViewModeDescription/Thesauri.php index f3b71ba93517f4649aee499cd6d7430a6ac0597c..48a49f6dc509e1059d7b6ac56614a7421a33ab78 100644 --- a/library/Class/ListViewModeDescription/Thesauri.php +++ b/library/Class/ListViewModeDescription/Thesauri.php @@ -54,7 +54,7 @@ class Class_ListViewModeDescription_Thesauri extends Class_ListViewModeDescripti 'callback' => $list_view_mode->renderCategoryClosure()]) ->addColumn($this->_('Libellé facette'), 'libelle_facette') ->addColumn($this->_('Code facette'), 'facette_index') - ->addColumn($this->_('Règle'), 'rules_label'); + ->addColumn($this->_('Règle'), 'rules'); } @@ -65,7 +65,7 @@ class Class_ListViewModeDescription_Thesauri extends Class_ListViewModeDescripti ->addColumn($this->_('Libellé facette'), 'libelle_facette') ->addColumn($this->_('Code facette'), ['attribute' => 'facette_index', 'sort_attribute' => 'id_thesaurus']) - ->addColumn($this->_('Règle'), ['attribute' => 'rules_label', + ->addColumn($this->_('Règle'), ['attribute' => 'rules', 'sort_attribute' => 'rules']) ->setSorterServer() ; diff --git a/library/Class/Migration/BokehEight.php b/library/Class/Migration/BokehEight.php new file mode 100644 index 0000000000000000000000000000000000000000..c49a43665d4982b8eab091ef6a8545773685e597 --- /dev/null +++ b/library/Class/Migration/BokehEight.php @@ -0,0 +1,60 @@ +<?php +/** + * Copyright (c) 2012-2019, 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_BokehEight { + + use Trait_Translator; + + + public function run() { + Class_AdminVar::set('CODIFICATION_BROWSER', 1); + Class_AdminVar::set('INSPECTOR_GADGET_MARC_XML', 1); + Class_AdminVar::set('CUSTOM_SEARCH_FORM', 1); + Class_AdminVar::set('AUTHOR_PAGE', 1); + Class_AdminVar::set('OPDS', 1); + Class_AdminVar::set('BIBNUM', 1); + + $this + ->_manageLoginThroughSigbOnly() + ->_fixCosmoVarDateMajAlbums(); + } + + + protected function _manageLoginThroughSigbOnly() { + if (Class_IntBib::isSingleNanook() || Class_IntBib::isSingleKoha()) + Class_AdminVar::set('LOGIN_THROUGH_SIGB_ONLY', 1); + + return $this; + } + + + protected function _fixCosmoVarDateMajAlbums() { + if (!$model = Class_CosmoVar::find('date_maj_albums')) + $model = Class_CosmoVar::newInstance() + ->setClef('date_maj_albums'); + + $model + ->setCommentaire($this->_('Dernière date de mise à jour des albums.')) + ->setGroupe(6) + ->save(); + } +} \ No newline at end of file diff --git a/library/Class/Migration/DynamicFacets.php b/library/Class/Migration/DynamicFacets.php new file mode 100644 index 0000000000000000000000000000000000000000..6a82a4201cde3b480a935302fb3145c8045167f8 --- /dev/null +++ b/library/Class/Migration/DynamicFacets.php @@ -0,0 +1,60 @@ +<?php +/** + * Copyright (c) 2012-2018, 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_DynamicFacets { + protected $_sql; + + public function __construct() { + $this->_sql = Zend_Db_Table::getDefaultAdapter(); + } + + + public function run() { + $thesauri = $this->_sql + ->fetchAll('select id, rules from codif_thesaurus where rules is not null and rules != ""'); + + foreach($thesauri as $thesaurus) + $this->_runOne($thesaurus); + } + + + protected function _runOne($thesaurus) { + if (null === ($current = json_decode($thesaurus['rules'], true))) + return; + + if (!isset($current['label']) || !$current['label']) + return; + + $parts = explode('$', trim($current['label'])); + if (2 !== count($parts)) + return; + + if (!$new = (new Class_CodifThesaurus_Rules) + ->setZone(sprintf('%03d', trim($parts[0]))) + ->setLabelField(trim($parts[1])) + ->format()) + return; + + $this->_sql->query('update codif_thesaurus set rules=? where id=?', + [$new, $thesaurus['id']]); + } +} diff --git a/library/Class/Newsletter.php b/library/Class/Newsletter.php index ee3814bbe9be89fc4020c630886c21d53182c456..ca407e7229b8b3731c5876cb215e7ab9e4be616e 100644 --- a/library/Class/Newsletter.php +++ b/library/Class/Newsletter.php @@ -89,7 +89,9 @@ class Class_Newsletter extends Storm_Model_Abstract { protected $_notices_finder; protected $_recipent_size = 20; protected $_default_attribute_values = ['titre' => '', - 'draft' => 0]; + 'draft' => 0, + 'articles_ids' => '', + 'articles_categories_ids' => '']; public function describeAssociationsOn($associations) { @@ -136,11 +138,12 @@ class Class_Newsletter extends Storm_Model_Abstract { $template = new Class_Entity(); $notices = $this->getNotices(); + $articles = $this->getArticles(); $template ->setTitre($this->getTitre()) - ->setBodyText($this->_getBodyText($notices)) - ->setBodyHTML($this->_getBodyHTML($notices)) + ->setBodyText($this->_getBodyText($notices, $articles)) + ->setBodyHTML($this->_getBodyHTML($notices, $articles)) ->setExpediteur($this->getExpediteur()); return $template; @@ -214,10 +217,23 @@ class Class_Newsletter extends Storm_Model_Abstract { 'only_img' => false, 'aleatoire' => 0, 'tri' => 1); + return Class_Notice::getNoticesFromPreferences($preferences); } + public function getArticles() { + $articles = []; + + foreach (Class_ArticleCategorie::findAllBy(['id_cat' => $this->getArticlesCategoriesIds()]) as $categorie) + $articles = array_merge($articles, + $categorie->getArticles()); + + return array_merge($articles, + Class_Article::findAllBy(['id_article' => $this->getArticlesIds()])); + } + + protected function _htmlToText($html) { return strip_tags(preg_replace('/<br[^>]*>/i', "\n", $html)); } @@ -245,13 +261,17 @@ class Class_Newsletter extends Storm_Model_Abstract { } - protected function _getBodyText($records) { + protected function _getBodyText($records, $articles) { $lines = [$this->_htmlToText($this->getContenu())]; $renderer = new Class_Notice_MailRenderer(); foreach($records as $record) $renderer->renderTextInto($record, $lines); + $renderer = new Class_Article_MailRenderer(); + foreach($articles as $article) + $renderer->renderTextInto($article, $lines); + $lines[] = $this->_getUnsubscribeText(); return implode("\n", $lines); @@ -273,13 +293,17 @@ class Class_Newsletter extends Storm_Model_Abstract { * @param array $records * @return string */ - protected function _getBodyHTML($records) { + protected function _getBodyHTML($records, $articles) { $html = $this->getContenu(); $renderer = new Class_Notice_MailRenderer(); foreach($records as $record) $html .= $renderer->renderHtml($record); + $renderer = new Class_Article_MailRenderer(); + foreach($articles as $article) + $html .= $renderer->renderHtml($article); + $html .= $this->_getUnsubscribeHTML(); return $html; diff --git a/library/Class/Notice.php b/library/Class/Notice.php index f156db270989232b5a6f412c4791a6c34e6f3920..c916f81a44f229fe93becc38b16c8f43753b65fb 100644 --- a/library/Class/Notice.php +++ b/library/Class/Notice.php @@ -181,7 +181,8 @@ class Class_Notice extends Storm_Model_Abstract { $_matieres, $_editeur, $_langueCodes, - $_first_exemplaire; + $_first_exemplaire, + $_data_map; protected $_default_attribute_values = ['type_doc' => 0, 'annee' => null, @@ -214,6 +215,13 @@ class Class_Notice extends Storm_Model_Abstract { } + protected function _getDataMap() { + return $this->_data_map + ? $this->_data_map + : ($this->_data_map = Class_Notice_DataMap::forRecord($this)); + } + + public function initializeAttributes($datas) { parent::initializeAttributes($datas); if (isset($datas['unimarc'])) @@ -545,6 +553,13 @@ class Class_Notice extends Storm_Model_Abstract { } + public function setFacettes($string_or_array) { + return parent::setFacettes(is_array($string_or_array) + ? implode(' ', $string_or_array) + : $string_or_array); + } + + public function updateFacette($facettes) { $this->setFacettes(Class_Notice_Facettes::mergeFacettes($this->getFacettes(), $facettes)); return $this; @@ -673,47 +688,7 @@ class Class_Notice extends Storm_Model_Abstract { public function getChampNotice($champ, $facettes = '') { - if (in_array($champ, - [Class_CodifTags::CODE_FACETTE, - Class_CodifDewey::CODE_FACETTE, - Class_CodifPcdm4::CODE_FACETTE, - Class_CodifMatiere::CODE_FACETTE, - Class_TypeDoc::CODE_FACETTE, - Class_CodifGenre::CODE_FACETTE, - Class_CodifCentreInteret::CODE_FACETTE])) { - $ret = []; - $codification = Class_Codification::getInstance(); - $items = array_filter(explode(' ', trim($facettes))); - foreach ($items as $item) { - if (($item[0] != $champ) || (!$label = $codification->getLibelleFacette($item))) - continue; - - $ret[] = $this->getReboundFieldForFacet($item, - $label, - $this->_('Rechercher tous les documents ayant comme %s: %s', - $codification->getNomChamp($champ), - $label)); - } - return $ret; - } - - switch ($champ) { - case Class_CodifAuteur::CODE_FACETTE: return $this->getAuteursUnimarc(false, true); - case Class_Codification::CODE_TITRE: return $this->getZonesTitre(); - case Class_Codification::CODE_EDITEUR: return $this->getEditeurs(); - case Class_Codification::CODE_COLLECTION: return $this->getCollections(true); - case Class_Codification::CODE_NOTES: return $this->getNotes(); - case Class_Codification::CODE_COLLATION: return $this->getCollation(); - case Class_Codification::CODE_RESUME: return $this->getResume(); - case Class_Codification::CODE_URL: return $this->getUrls(); - case Class_Codification::CODE_ANNEE: return $this->getAnnee(); - case Class_Codification::CODE_PRIX: return $this->getPrix(); - case Class_CodifLangue::CODE_FACETTE: return $this->getLangues(); - case Class_Codification::CODE_IDENTIFIANT: return (new Class_Isbn($this->getIsbnOrEan()))->getAll()['isbn10']; - case Class_Codification::CODE_NOUVEAUTE: return $this->isNouveaute() ? $this->_('Oui'): $this->_('Non'); - } - - return []; + return $this->_getDataMap()->getRecordField($champ, $facettes); } @@ -721,23 +696,22 @@ class Class_Notice extends Storm_Model_Abstract { return (new Class_Notice_Urls($this))->asArray(); } + public function getPrix() { return $this->get_subfield("010", "d"); } + public function hasTome() { - if ($data = $this->get_subfield("461", "t") - && strlen($this->getClefChapeau())>1) - return true; - return false; + return ($this->get_subfield("461", "t") && strlen($this->getClefChapeau()) > 1); } + public function getNoticesMemeSeries() { if (!$this->hasTome()) return []; return $this->getLoader()->getAllNoticesByClefChapeau($this->getClefChapeau()); - } @@ -848,8 +822,7 @@ class Class_Notice extends Storm_Model_Abstract { public function getRecordTitle() { - $titres = $this->get_subfield('200', 'a'); - return $titres ? trim($titres[0]) : ''; + return $this->_getDataMap()->getMainTitle(); } @@ -985,7 +958,7 @@ class Class_Notice extends Storm_Model_Abstract { /** * @return array */ - protected function getZonesTitre() { + public function getZonesTitre() { $zones = Class_CosmoVar::get('unimarc_zone_titre'); $zones = array_filter(explode(';', trim($zones))); return $this->_getTitresDansZones($zones); diff --git a/library/Class/Notice/AuthorityIndexSystem.php b/library/Class/Notice/AuthorityIndexSystem.php new file mode 100644 index 0000000000000000000000000000000000000000..17759dceb6bdc14a9ecb649e4f2e0563f3f93fd5 --- /dev/null +++ b/library/Class/Notice/AuthorityIndexSystem.php @@ -0,0 +1,143 @@ +<?php +/** + * Copyright (c) 2012-2018, 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_Notice_AuthorityIndexSystem { + use Trait_TimeSource; + + const + FIELD_RULE = 'rule', + FIELD_SYSTEM = 'system', + FIELD_DEFAULT_TYPE = 'default_type', + FIELD_THESAURUS = 'thesaurus'; + + protected + $_rule, + $_system, + $_default_type, + $_thesaurus; + + public static function collectionFromPrefs($prefs) { + return new Class_Notice_AuthorityIndexSystemCollection(array_map(['Class_Notice_AuthorityIndexSystem', 'newFromPref'], + $prefs)); + } + + + public static function newFromPref($pref) { + return new static($pref[static::FIELD_RULE], + $pref[static::FIELD_SYSTEM], + $pref[static::FIELD_DEFAULT_TYPE], + $pref[static::FIELD_THESAURUS]); + } + + + public function __construct($rule, $system, $default_type, $thesaurus) { + $this->_rule = $rule; + $this->_system = $system; + $this->_default_type = $default_type; + $this->_thesaurus = $thesaurus; + } + + + public function facetFor($rule, $system) { + if (!$this->_thesaurus) + return; + + if (trim($rule) != trim($this->_rule)) + return; + + if (trim($system) != trim($this->_system)) + return; + + return ($model = Class_CodifThesaurus::find($this->_thesaurus)) + ? $model->getFacetCode() + : null; + } + + + public function isLinkedToThesaurus($thesaurus) { + return $this->_thesaurus && $thesaurus + && $this->_thesaurus == $thesaurus->getId(); + } + + + public function ensureRecordForThesaurus($heading, $id, $thesaurus, $int_bib, $child) { + if (!$thesaurus || !$int_bib || !$child) + return; + + $thesaurus_facet = $thesaurus->getFacetCode(); + foreach(Class_Exemplaire::findAllBy(['type' => Class_Notice::TYPE_AUTHORITY, + 'id_origine' => $id]) as $item) + if (in_array($thesaurus_facet, $item->getNotice()->getFacetCodes())) { + $item->getNotice()->updateFacette($child->getFacetCode())->save(); + return; + } + + $indexation = Class_Indexation::getInstance(); + + $rules = []; + if ($this->_rule) + $rules['a'] = $this->_rule; + if ($this->_system) + $rules['b'] = $this->_system; + + $marc = (new Class_Notice_AuthorityPartial) + ->newWith($this->_default_type, $id, $heading, $rules) + ->render(); + + $record = Class_Notice::newInstance(['unimarc' => $marc, + 'type' => Class_Notice::TYPE_AUTHORITY, + 'type_doc' => $this->_default_type, + 'titres' => $indexation->getFulltext($heading), + 'alpha_titre' => $indexation->codeAlphaTitre($heading), + 'date_maj' => $this->getTimeSource()->dateDayAndHours()]) + ->updateFacette($thesaurus_facet . ' ' . $child->getFacetCode()); + + if (!$record->save()) + return; + + Class_Exemplaire::newInstance(['type' => Class_Notice::TYPE_AUTHORITY, + 'id_origine' => $id, + 'id_int_bib' => $int_bib->getId(), + 'notice' => $record]) + ->save(); + } + + + public function asArray() { + return [static::FIELD_RULE => $this->_rule, + static::FIELD_SYSTEM => $this->_system, + static::FIELD_DEFAULT_TYPE => $this->_default_type, + static::FIELD_THESAURUS => $this->_thesaurus]; + } +} + + + + +class Class_Notice_AuthorityIndexSystemCollection extends Storm_Collection { + public function filterByThesaurus($thesaurus) { + return $this->select( + function($system) use($thesaurus) { + return $system->isLinkedToThesaurus($thesaurus); + }); + } +} \ No newline at end of file diff --git a/library/Class/Notice/AuthorityPartial.php b/library/Class/Notice/AuthorityPartial.php new file mode 100644 index 0000000000000000000000000000000000000000..75a70bf98619e0d2a1c41493a5a108a4dd43c92a --- /dev/null +++ b/library/Class/Notice/AuthorityPartial.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright (c) 2012-2018, 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_Notice_AuthorityPartial { + use Trait_TimeSource; + + const DEFAULT_AGENCY = 'Bokeh'; + + public function newWith($type, $id, $heading, $rules) { + $genaral_info = $this->getTimeSource()->dateFormat('Ymd') . 'afrey50 ba0'; + + return (new Class_NoticeUnimarc_Fluent()) + ->beAuthority() + ->type($type) + ->zoneWithContent('001', $id) + ->zoneWithChildren('100', ['a' => $genaral_info]) + ->zoneWithChildren('152', $rules) + ->zoneWithChildren((new Class_Notice_AuthorityType)->zoneForType('2', $type), + ['a' => $heading]) + ->zoneWithChildren('801', + ['a' => 'fr', + 'b' => static::DEFAULT_AGENCY, + 'c' => $this->getTimeSource()->dateFormat('Ymd')], + ' 3') + ; + } +} diff --git a/library/Class/Cosmogramme/Integration/Record/AuthorityRelation.php b/library/Class/Notice/AuthorityRelation.php similarity index 50% rename from library/Class/Cosmogramme/Integration/Record/AuthorityRelation.php rename to library/Class/Notice/AuthorityRelation.php index bfb23eb88b7738a1c1ef1aafd3bfe1758c01cc05..03e06fb0d50ceb740a28f91699e3eaea18e393c9 100644 --- a/library/Class/Cosmogramme/Integration/Record/AuthorityRelation.php +++ b/library/Class/Notice/AuthorityRelation.php @@ -19,8 +19,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -class Class_Cosmogramme_Integration_Record_AuthorityRelation { +class Class_Notice_AuthorityRelation { const + TYPE_GENERIC = 'g', + TYPE_SPECIFIC = 'h', + TYPE_OTHER = 'z', + + ZONE_REJECT = '4', + ZONE_LINK = '5', + FIELD_ID = '3', FIELD_TYPE = '5', FIELD_LABEL = 'a'; @@ -29,11 +36,39 @@ class Class_Cosmogramme_Integration_Record_AuthorityRelation { $_id, $_type = 'z', $_label, - $_authority_type; + $_authority_type, + $_field; + + + public static function allFor($record) { + $fields = static::possibleFields(); + $relations = []; + foreach($fields as $field) + $relations = array_merge($relations, static::_relationsIn($field, $record)); + + return $relations; + } + + + protected static function _relationsIn($field, $record) { + $relations = []; + foreach($record->get_subfield($field) as $relation) + $relations = static::_addRelationIn($record->decoupe_bloc_champ($relation), $field, $relations); + + return $relations; + } + + + protected static function _addRelationIn($datas, $field, $relations) { + $relation = new static($datas, $field); + $relations[] = $relation; + + return $relations; + } + public static function possibleFields() { - return (new Class_Cosmogramme_Integration_Record_AuthorityType) - ->variantsOf(['4', '5']); + return (new Class_Notice_AuthorityType)->variantsOf([static::ZONE_REJECT, static::ZONE_LINK]); } @@ -41,6 +76,8 @@ class Class_Cosmogramme_Integration_Record_AuthorityRelation { if (!$datas) return; + $this->_field = $field; + $map = [static::FIELD_ID => '_id', static::FIELD_TYPE => '_type', static::FIELD_LABEL => '_label']; @@ -49,8 +86,7 @@ class Class_Cosmogramme_Integration_Record_AuthorityRelation { if (array_key_exists($pair['code'], $map)) $this->{$map[$pair['code']]} = $pair['valeur']; - $this->_authority_type = (new Class_Cosmogramme_Integration_Record_AuthorityType) - ->codeFromField($field); + $this->_authority_type = (new Class_Notice_AuthorityType)->codeFromField($field); } @@ -69,7 +105,7 @@ class Class_Cosmogramme_Integration_Record_AuthorityRelation { } - public function facet() { + public function getFacetCode() { return $this->_type . $this->_id; } @@ -77,4 +113,31 @@ class Class_Cosmogramme_Integration_Record_AuthorityRelation { public function authorityType() { return $this->_authority_type; } + + + public function isGeneric() { + return static::TYPE_GENERIC === $this->_type; + } + + + public function isSpecific() { + return static::TYPE_SPECIFIC === $this->_type; + } + + + public function isReject() { + return $this->isOther() + && static::ZONE_REJECT === substr($this->_field, 0, 1); + } + + + public function isLink() { + return $this->isOther() + && static::ZONE_LINK === substr($this->_field, 0, 1); + } + + + public function isOther() { + return static::TYPE_OTHER === $this->_type; + } } diff --git a/library/Class/Cosmogramme/Integration/Record/AuthorityType.php b/library/Class/Notice/AuthorityType.php similarity index 74% rename from library/Class/Cosmogramme/Integration/Record/AuthorityType.php rename to library/Class/Notice/AuthorityType.php index 2b704179aa21ac4ec5f633b1a6051bb9eb3848f7..dbccbe72dc47e1a554c4f0126f4317364d64f72c 100644 --- a/library/Class/Cosmogramme/Integration/Record/AuthorityType.php +++ b/library/Class/Notice/AuthorityType.php @@ -20,7 +20,11 @@ */ -class Class_Cosmogramme_Integration_Record_AuthorityType { +class Class_Notice_AuthorityType { + use Trait_Translator; + + const SUBJECT = 'j'; + protected $_map = [ '00' => 'a',// = nom de personne @@ -38,6 +42,24 @@ class Class_Cosmogramme_Integration_Record_AuthorityType { ]; + public function withTypesDo($closure) { + foreach(['a' => $this->_('nom de personne'), + 'b' => $this->_('nom de collectivité'), + 'c' => $this->_('nom de territoire ou nom géographique'), + 'd' => $this->_('marque'), + 'e' => $this->_('famille'), + 'f' => $this->_('titre uniforme'), + 'g' => $this->_('rubrique de classement'), + 'h' => $this->_('auteur / titre'), + 'i' => $this->_('auteur / rubrique de classement'), + 'j' => $this->_('matière nom commun'), + 'k' => $this->_('lieu d’édition'), + 'l' => $this->_('forme, genre ou caractéristiques physiques'), + ] as $code => $label) + $closure($code, $label); + } + + public function codeFromField($field) { if (!$field) return ''; @@ -100,4 +122,11 @@ class Class_Cosmogramme_Integration_Record_AuthorityType { foreach($this->_map as $zone => $type) $closure($zone, $type); } + + + public function zoneForType($prefix, $type) { + $map = array_flip($this->_map); + if (isset($map[$type])) + return $prefix . $map[$type]; + } } \ No newline at end of file diff --git a/library/Class/Notice/DataMap.php b/library/Class/Notice/DataMap.php new file mode 100644 index 0000000000000000000000000000000000000000..25df45d5e1ee923f3dc7628b8a7c3ca15917a63a --- /dev/null +++ b/library/Class/Notice/DataMap.php @@ -0,0 +1,29 @@ +<?php +/** + * Copyright (c) 2012-2018, 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_Notice_DataMap { + public static function forRecord($record) { + return Class_Notice::TYPE_BIBLIOGRAPHIC === $record->getType() + ? new Class_Notice_DataMap_UnimarcBiblio($record) + : new Class_Notice_DataMap_UnimarcAuthority($record); + } +} diff --git a/library/Class/Notice/DataMap/Abstract.php b/library/Class/Notice/DataMap/Abstract.php new file mode 100644 index 0000000000000000000000000000000000000000..1ee196b5faa53663821b2ca3e144ec0f841a9114 --- /dev/null +++ b/library/Class/Notice/DataMap/Abstract.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright (c) 2012-2018, 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 Class_Notice_DataMap_Abstract { + use Trait_Translator; + + protected $_record; + + public function __construct($record) { + $this->_record = $record; + } + + + /** @return string */ + abstract public function getMainTitle(); + + /** + * @param $field string field facet code + * @param $facets string + * + * @return array + */ + abstract public function getRecordField($field, $facets=''); +} diff --git a/library/Class/Notice/DataMap/UnimarcAuthority.php b/library/Class/Notice/DataMap/UnimarcAuthority.php new file mode 100644 index 0000000000000000000000000000000000000000..aabd9c86ea18ee2443b478c8cba6034aa50edee6 --- /dev/null +++ b/library/Class/Notice/DataMap/UnimarcAuthority.php @@ -0,0 +1,149 @@ +<?php +/** + * Copyright (c) 2012-2018, 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_Notice_DataMap_UnimarcAuthority extends Class_Notice_DataMap_Abstract { + public function getMainTitle() { + $titres = $this->_record->get_subfield('250', 'a'); + return $titres ? trim($titres[0]) : ''; + } + + + public function getRecordField($field, $facets='') { + if (Class_Codification::CODE_AUTHORITY_DATAS !== $field) + return []; + + return [new Class_Notice_DataMap_UnimarcAuthorityRelations($this->_record), + new Class_Notice_DataMap_UnimarcAuthorityNotes($this->_record), + new Class_Notice_DataMap_UnimarcAuthorityUsages($this->_record)]; + } +} + + + + +abstract class Class_Notice_DataMap_UnimarcAuthorityComponent { + use Trait_Translator; + + protected $_record; + + public function __construct($record) { + $this->_record = $record; + } + + abstract public function renderOn($view); +} + + + + +class Class_Notice_DataMap_UnimarcAuthorityNotes extends Class_Notice_DataMap_UnimarcAuthorityComponent { + public function renderOn($view) { + if ($notes = $this->_record->get_subfield('330', 'a')) + return $view->tag('h3', 'Note d\'application') . $view->tag('p', reset($notes)); + } +} + + + + +class Class_Notice_DataMap_UnimarcAuthorityUsages extends Class_Notice_DataMap_UnimarcAuthorityComponent { + public function renderOn($view) { + $facets = array_filter($this->_record->getFacetCodes(), + function($facet) { return $this->_isDynamicFacetValue($facet); }); + + if (!$facets) + return $this->_('Utilisé dans aucune notice'); + + $criterias = (new Class_CriteresRecherche())->setParams(['multifacets' => implode('-', $facets)]); + + if (!$count = $this->_countByCriterias($criterias)) + return $this->_('Utilisé dans aucune notice'); + + return $view->tagAnchor($view->url($criterias->getUrlCriteresWithFacettes(), null, true), + $this->_plural($count, + 'Utilisé dans aucune notice', + 'Utilisé dans 1 notice', + 'Utilisé dans %d notices', + $count)); + } + + + protected function _isDynamicFacetValue($facet) { + return Class_CodifThesaurus::CODE_FACETTE === substr($facet, 0, 1) + && strlen($facet) === (Class_CodifThesaurus::ID_KEY_LENGTH * 2) + 1; + } + + + protected function _countByCriterias($criterias) { + return (new Class_MoteurRecherche) + ->beNotExtensible() + ->lancerRecherche($criterias) + ->getRecordsCount(); + } +} + + + + +class Class_Notice_DataMap_UnimarcAuthorityRelations extends Class_Notice_DataMap_UnimarcAuthorityComponent{ + protected $_relations; + + public function renderOn($view) { + $this->_relations = new Storm_Collection(Class_Notice_AuthorityRelation::allFor($this->_record)); + + $render = []; + foreach(['isGeneric' => $this->_('Terme générique'), + 'isSpecific'=> $this->_('Terme spécifique'), + 'isReject' => $this->_('Terme rejeté'), + 'isLink' => $this->_('Terme associé')] + as $selector => $label) + $render[] = $this->_renderLabelledList($view, $label, $selector); + + return implode($render); + } + + + protected function _renderLabelledList($view, $label, $selector) { + $closure = function($item) use ($selector) { return $item->$selector(); }; + $relations = $this->_relations->select($closure); + if ($relations->isEmpty()) + return; + + $terms = []; + foreach($relations as $relation) + $terms[] = $this->_renderLabelledItem($view, $relation); + + return $view->tag('h3', $label) . $view->tag('ul', implode($terms)); + } + + + protected function _renderLabelledItem($view, $relation) { + $label = $relation->label(); + if ($item = Class_Exemplaire::findFirstAuthorityItemByOriginId($relation->id())) + $label = $view->tagAnchor($view->url(['controller' => 'recherche', + 'action' => 'viewnotice', + 'id' => $item->getIdNotice()], + null, true), $label); + + return $view->tag('li', $label); + } +} diff --git a/library/Class/Notice/DataMap/UnimarcBiblio.php b/library/Class/Notice/DataMap/UnimarcBiblio.php new file mode 100644 index 0000000000000000000000000000000000000000..ad7df0b6664b1c0a500678944f0baa3997fefff1 --- /dev/null +++ b/library/Class/Notice/DataMap/UnimarcBiblio.php @@ -0,0 +1,91 @@ +<?php +/** + * Copyright (c) 2012-2018, 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_Notice_DataMap_UnimarcBiblio extends Class_Notice_DataMap_Abstract { + public function getMainTitle() { + $titres = $this->_record->get_subfield('200', 'a'); + return $titres ? trim($titres[0]) : ''; + } + + + public function getRecordField($field, $facets='') { + if ($this->_isReboundField($field)) + return $this->_getReboundField($field, $facets); + + switch ($field) { + case Class_CodifAuteur::CODE_FACETTE: return $this->_record->getAuteursUnimarc(false, true); + case Class_Codification::CODE_TITRE: return $this->_record->getZonesTitre(); + case Class_Codification::CODE_EDITEUR: return $this->_record->getEditeurs(); + case Class_Codification::CODE_COLLECTION: return $this->_record->getCollections(true); + case Class_Codification::CODE_NOTES: return $this->_record->getNotes(); + case Class_Codification::CODE_COLLATION: return $this->_record->getCollation(); + case Class_Codification::CODE_RESUME: return $this->_record->getResume(); + case Class_Codification::CODE_URL: return $this->_record->getUrls(); + case Class_Codification::CODE_ANNEE: return $this->_record->getAnnee(); + case Class_Codification::CODE_PRIX: return $this->_record->getPrix(); + case Class_CodifLangue::CODE_FACETTE: return $this->_record->getLangues(); + case Class_Codification::CODE_IDENTIFIANT: return (new Class_Isbn($this->_record->getIsbnOrEan()))->getAll()['isbn10']; + case Class_Codification::CODE_NOUVEAUTE: return $this->_record->isNouveaute() ? $this->_('Oui'): $this->_('Non'); + } + + return []; + } + + + protected function _getReboundField($field, $facets) { + $values = []; + $items = array_filter(explode(' ', trim($facets))); + foreach ($items as $item) + $values = $this->_addReboundValueIn($field, $item, $values); + + return $values; + } + + + protected function _addReboundValueIn($field, $facet, $values) { + $codification = Class_Codification::getInstance(); + if ((substr($facet, 0, 1) != $field) + || (!$label = $codification->getLibelleFacette($facet))) + return $values; + + $values[] = $this->_record + ->getReboundFieldForFacet($facet, + $label, + $this->_('Rechercher tous les documents ayant comme %s: %s', + $codification->getNomChamp($field), + $label)); + + return $values; + } + + + protected function _isReboundField($field) { + return in_array($field, + [Class_CodifTags::CODE_FACETTE, + Class_CodifDewey::CODE_FACETTE, + Class_CodifPcdm4::CODE_FACETTE, + Class_CodifMatiere::CODE_FACETTE, + Class_TypeDoc::CODE_FACETTE, + Class_CodifGenre::CODE_FACETTE, + Class_CodifCentreInteret::CODE_FACETTE]); + } +} diff --git a/library/Class/NoticeUnimarc/Fluent.php b/library/Class/NoticeUnimarc/Fluent.php new file mode 100644 index 0000000000000000000000000000000000000000..a60d7bac7bbd4cc1f81e2c8bb79dea74592c8347 --- /dev/null +++ b/library/Class/NoticeUnimarc/Fluent.php @@ -0,0 +1,246 @@ +<?php +/** + * Copyright (c) 2012-2018, 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_NoticeUnimarc_Fluent { + protected + $_label, + $_zones; + + public function __construct() { + $this->_label = new Class_NoticeUnimarc_BibliographicLabel(); + $this->_zones = new Storm_Collection(); + } + + + public function beAuthority() { + $this->_label = new Class_NoticeUnimarc_AuthorityLabel(); + return $this; + } + + + public function type($type) { + $this->_label->type($type); + return $this; + } + + + public function zoneWithContent($label, $content) { + $this->newZone()->label($label)->content($content); + return $this; + } + + + public function zoneWithChildren($label, $children, $indicators=null) { + $zone = $this->newZone()->label($label)->children($children); + if (null !== $indicators) + $zone->indicators($indicators); + + return $this; + } + + + public function newZone() { + $zone = new Class_NoticeUnimarc_Zone(); + $this->_zones->append($zone); + return $zone; + } + + + public function render() { + $address = 0; + $directory = ''; + + $zones = implode($this->_zones + ->collect( + function($zone) use(&$address, &$directory) { + $marc = $zone->render(); + $length = strlen($marc); + $directory .= $zone->directoryWith($length, $address); + $address += $length; + return $marc; + }) + ->getArrayCopy()); + + $zones .= chr(0x1d); + $directory .= chr(0x1e); + + return $this->_label->lengths(strlen($directory), strlen($zones)) + ->render() + . $directory + . $zones; + } +} + + + +class Class_NoticeUnimarc_BibliographicLabel { + const LENGTH = 24; + const PATTERN = '%05d%1s%1s%1s%1s 22%05d%1s%1s 450 '; + + protected + $_length = 0, + $_status = 'n', + $_type = 'a', + $_biblio_level = 'm', + $_hierarchy_level = 0, + $_encoding_level = 1, + $_isbd_level = 'i', + $_base_address = 0; + + + public function type($type) { + $this->_type = substr((string)$type, 0, 1); + return $this; + } + + + public function lengths($directory, $zones) { + $this->_length = $directory + $zones + static::LENGTH; + $this->_base_address = $directory + static::LENGTH; + return $this; + } + + + public function render() { + return sprintf(static::PATTERN, + $this->_length, $this->_status, $this->_type, $this->_biblio_level, + $this->_hierarchy_level, $this->_base_address, $this->_encoding_level, + $this->_isbd_level); + } +} + + + +class Class_NoticeUnimarc_AuthorityLabel { + const LENGTH = 24; + const PATTERN = '%05d%1s%1s %1s22%05d%1s 450 '; + + protected + $_length = 0, + $_status = 'n', + $_record_type = 'x', + $_type = 'a', + $_encoding_level = 1, + $_base_address = 0; + + + public function type($type) { + $this->_type = substr((string)$type, 0, 1); + return $this; + } + + + public function lengths($directory, $zones) { + $this->_length = $directory + $zones + static::LENGTH; + $this->_base_address = $directory + static::LENGTH; + return $this; + } + + + public function render() { + return sprintf(static::PATTERN, + $this->_length, $this->_status, $this->_record_type, $this->_type, + $this->_base_address, $this->_encoding_level); + } +} + + + +class Class_NoticeUnimarc_Zone { + protected + $_label, + $_indicators = ' ', + $_sub_zones, + $_content; + + public function __construct() { + $this->_sub_zones = new Storm_Collection(); + } + + + public function label($label) { + $this->_label = $label; + return $this; + } + + + public function content($content) { + $this->_content = $content; + $this->_sub_zones = new Storm_Collection(); + return $this; + } + + + public function children($children) { + foreach($children as $code => $value) + $this->_sub_zones->append((new Class_NoticeUnimarc_SubZone)->code($code)->value($value)); + $this->_content = null; + + return $this; + } + + + public function indicators($indicators) { + $this->_indicators = $indicators; + return $this; + } + + + public function render() { + $content = $this->_content + ? $this->_content + : ($this->_indicators . implode($this->_sub_zones + ->collect(function($zone) { return $zone->render(); }) + ->getArrayCopy())); + + return $content . chr(0x1e); + } + + + public function directoryWith($length, $address) { + return sprintf('%03d%04d%05d', $this->_label, $length, $address); + } +} + + + +class Class_NoticeUnimarc_SubZone { + protected + $_code, + $_value; + + public function code($code) { + $this->_code = $code; + return $this; + } + + + public function value($value) { + $this->_value = $value; + return $this; + } + + + public function render() { + return chr(0x1f) . $this->_code . $this->_value; + } +} \ No newline at end of file diff --git a/library/Class/ProfilePrefs.php b/library/Class/ProfilePrefs.php index b1033e8384ab8bd52b1ddc98e4b749d19cd16b10..fd8f2d1a5a72f73b63c9c862eb8a2bccabdcd40d 100644 --- a/library/Class/ProfilePrefs.php +++ b/library/Class/ProfilePrefs.php @@ -280,6 +280,14 @@ class Class_ProfilePrefs extends Class_Entity { } + public function getIndexSystemsPrefs() { + $prefs = $this->getFirstPref(); + return isset($prefs[Class_IntProfilDonnees::PROFILE_INDEX_SYSTEMS_FIELDS]) + ? $prefs[Class_IntProfilDonnees::PROFILE_INDEX_SYSTEMS_FIELDS] + : []; + } + + public function getItemUrlPrefs() { return $this->getItemPrefs()[Class_IntProfilDonnees::FIELD_ITEM_URL]; } @@ -320,6 +328,12 @@ class Class_ProfilePrefs extends Class_Entity { } + public function getFirstPref() { + $prefs = $this->getPrefs(); + return reset($prefs); + } + + public function getPrefs() { if (!$datas = $this->getDatas()) return []; diff --git a/library/Class/ProfileSerializer.php b/library/Class/ProfileSerializer.php index 5a5263a50095a1f850e71f3177e3c9659d501e4c..f0a83d0000dd8d61a1e2df9e40b62ab18ffce1f8 100644 --- a/library/Class/ProfileSerializer.php +++ b/library/Class/ProfileSerializer.php @@ -36,51 +36,66 @@ class Class_ProfileSerializer { protected function _buildStrategy() { - $current_format = $this->_datas[Class_IntProfilDonnees::PROFILE_FILE_FORMAT]; - $is_csv = Class_IntProfilDonnees::isFormatCSV($current_format); - $is_unimarc = Class_IntProfilDonnees::isFormatUnimarc($current_format); + if (Class_IntProfilDonnees::isRecordFileType($this->_fileType())) + return $this->_buildStrategyWith(['UnimarcRecord' => 'isFormatUnimarc', + 'DublinCoreRecords' => 'isFormatDublinCoreOrBiblionDemand', + 'CSVItem' => 'isFormatCSV']); - if($this->_datas[Class_IntProfilDonnees::PROFILE_FILE_TYPE] == Class_IntProfilDonnees::FT_RECORDS - && $is_unimarc) - return new Class_ProfileSerializer_UnimarcRecord(); + if (Class_IntProfilDonnees::isPatronFileType($this->_fileType())) + return $this->_buildPatronStrategy(); - if($this->_datas[Class_IntProfilDonnees::PROFILE_FILE_TYPE] == Class_IntProfilDonnees::FT_RECORDS - && in_array($this->_datas[Class_IntProfilDonnees::PROFILE_FILE_FORMAT], [Class_IntProfilDonnees::FORMAT_DUBLIN_CORE, - Class_IntProfilDonnees::FORMAT_BIBLIONDEMAND])) - return new Class_ProfileSerializer_DublinCoreRecords(); + if (Class_IntProfilDonnees::isLoanFileType($this->_fileType())) + return $this->_buildStrategyWith(['CSVLoans' => 'isFormatCSV']); - if($this->_datas[Class_IntProfilDonnees::PROFILE_FILE_TYPE] == Class_IntProfilDonnees::FT_RECORDS - && $is_csv) - return new Class_ProfileSerializer_CSVItem(); + if (Class_IntProfilDonnees::isHoldFileType($this->_fileType())) + return $this->_buildStrategyWith(['CSVHolds' => 'isFormatCSV']); - if($this->_datas[Class_IntProfilDonnees::PROFILE_FILE_TYPE] == Class_IntProfilDonnees::FT_PATRONS - && $this->_datas[Class_IntProfilDonnees::PROFILE_FILE_FORMAT] == Class_IntProfilDonnees::FORMAT_XML) - return new Class_ProfileSerializer_XMLPatrons(); + if (Class_IntProfilDonnees::isBasketFileType($this->_fileType())) + return $this->_buildStrategyWith(['CSVBaskets' => 'isFormatCSV']); - if($this->_datas[Class_IntProfilDonnees::PROFILE_FILE_TYPE] == Class_IntProfilDonnees::FT_PATRONS - && $is_csv) - return new Class_ProfileSerializer_CSVPatrons(); + if (Class_IntProfilDonnees::isAuthorityFileType($this->_fileType())) + return $this->_buildStrategyWith(['UnimarcAuthority' => 'isFormatUnimarc']); + + return new Class_ProfileSerializer_Unsupported(); + } + + + protected function _buildPatronStrategy() { + $closure = function($format) { + return $format == Class_IntProfilDonnees::FORMAT_XML; + }; + + return $this->_buildStrategyWith(['XMLPatrons' => $closure, + 'CSVPatrons' => 'isFormatCSV']); + } - if($this->_datas[Class_IntProfilDonnees::PROFILE_FILE_TYPE] == Class_IntProfilDonnees::FT_LOANS - && $is_csv) - return new Class_ProfileSerializer_CSVLoans(); - if($this->_datas[Class_IntProfilDonnees::PROFILE_FILE_TYPE] == Class_IntProfilDonnees::FT_HOLDS - && $is_csv) - return new Class_ProfileSerializer_CSVHolds(); + protected function _buildStrategyWith($map) { + foreach($map as $name => $callable) { + if (is_string($callable)) + $callable = ['Class_IntProfilDonnees', $callable]; - if($this->_datas[Class_IntProfilDonnees::PROFILE_FILE_TYPE] == Class_IntProfilDonnees::FT_BASKETS - && $is_csv) - return new Class_ProfileSerializer_CSVBaskets(); + if (call_user_func($callable, $this->_fileFormat())) { + $class_name = 'Class_ProfileSerializer_' . $name; + return new $class_name; + } + } return new Class_ProfileSerializer_Unsupported(); + } + + + protected function _fileType() { + return $this->_datas[Class_IntProfilDonnees::PROFILE_FILE_TYPE]; + } + + protected function _fileFormat() { + return $this->_datas[Class_IntProfilDonnees::PROFILE_FILE_FORMAT]; } public function serializeDatas() { return serialize($this->_strategy->getDatas()); } - } -?> \ No newline at end of file diff --git a/library/Class/ProfileSerializer/Abstract.php b/library/Class/ProfileSerializer/Abstract.php index 4724e24ec4e922b05a899419d09aeb90524edfdd..c851ef071f99e6eb4662fb6eaae960fe88182c41 100644 --- a/library/Class/ProfileSerializer/Abstract.php +++ b/library/Class/ProfileSerializer/Abstract.php @@ -30,6 +30,7 @@ abstract class Class_ProfileSerializer_Abstract { return $this; } + public function getFormats() { return Class_IntProfilDonnees::getFormatsForType($this->_datas[Class_IntProfilDonnees::PROFILE_FILE_TYPE ]); } @@ -38,4 +39,3 @@ abstract class Class_ProfileSerializer_Abstract { abstract public function buildForm($form); abstract public function populateForm($form); } -?> \ No newline at end of file diff --git a/library/Class/ProfileSerializer/CSVPatrons.php b/library/Class/ProfileSerializer/CSVPatrons.php index eca254bd52fda327a3e4def365e42fc3b6a3888d..e1bc64aa618df06ab881dcfe604e675a807f57ec 100644 --- a/library/Class/ProfileSerializer/CSVPatrons.php +++ b/library/Class/ProfileSerializer/CSVPatrons.php @@ -33,4 +33,3 @@ class Class_ProfileSerializer_CSVPatrons extends Class_ProfileSerializer_CSVAbst return $form->populateCSVPatrons(); } } -?> \ No newline at end of file diff --git a/library/Class/ProfileSerializer/UnimarcAuthority.php b/library/Class/ProfileSerializer/UnimarcAuthority.php new file mode 100644 index 0000000000000000000000000000000000000000..24b1ee65d5c750854339e7bfe1f98d22fa983d5a --- /dev/null +++ b/library/Class/ProfileSerializer/UnimarcAuthority.php @@ -0,0 +1,117 @@ +<?php +/** + * Copyright (c) 2012-2014, 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_ProfileSerializer_UnimarcAuthority extends Class_ProfileSerializer_Abstract { + public function getDatas() { + return [0 => $this->_extractIndexSystems(), + 1 => [], + 2 => [], + 3 => [], + 4 => [], + 5 => [], + 6 => []]; + } + + + public function buildForm($form) { + $fields = [['name' => 'index_system_rule', 'label' => $this->_('Règles de catalogage')], + + ['name' => 'index_system_label', 'label' => $this->_('Système d\'indexation matière')], + + ['name' => 'index_system_default_type', 'label' => $this->_('Type d\'autorité par défaut'), + 'type' => 'select', + 'options' => $this->_buildAuthorityTypeOptions()], + + ['name' => 'index_system_thesaurus', 'label' => $this->_('Rattaché au thesaurus'), + 'type' => 'select', + 'options' => $this->_buildThesaurusOptions()]]; + + return $form->addElement('multiInput', 'index_systems', + ['label' => $this->_('Règles'), 'fields' => $fields]) + + ->addDisplayGroup(['index_systems'], 'indexation', + ['legend' => $this->_('Indexation')]) + ; + } + + + protected function _buildAuthorityTypeOptions() { + $options = ['' => '']; + $collector = function($code, $label) use (&$options) { + $options[$code] = $label; + }; + + (new Class_Notice_AuthorityType)->withTypesDo($collector); + + return $options; + } + + + protected function _buildThesaurusOptions() { + $options = [0 => '']; + $collector = function($model) use (&$options) { + $label = $model->getLibelle() . sprintf(' (%s$%s)', + $model->getRuleZone(), $model->getRuleIdfield()); + $options[$model->getId()] = $label; + }; + + Class_CodifThesaurus::withDynamicFacetsHavingIdFieldDo($collector); + + return $options; + } + + + public function populateForm($form) { + $values = ['index_system_rule' => [], + 'index_system_label' => [], + 'index_system_default_type' => [], + 'index_system_thesaurus' => []]; + + foreach($form->getProfilePrefs()->getIndexSystemsPrefs() as $pref) { + $values['index_system_rule'][] = $pref['rule']; + $values['index_system_label'][] = $pref['system']; + $values['index_system_default_type'][] = $pref['default_type']; + $values['index_system_thesaurus'][] = $pref['thesaurus']; + } + + return $form->index_systems->setValues($values); + } + + + protected function _extractIndexSystems() { + if (!isset($this->_datas['index_system_rule']) || !is_array($this->_datas['index_system_rule']) + && !isset($this->_datas['index_system_label']) || !is_array($this->_datas['index_system_label'])) + return []; + + $index_systems = []; + foreach($this->_datas['index_system_rule'] as $k => $rule) { + $system = $this->_datas['index_system_label'][$k]; + if ($system || $rule) + $index_systems[] = ['rule' => $rule, + 'system' => $system, + 'default_type' => $this->_datas['index_system_default_type'][$k], + 'thesaurus' => $this->_datas['index_system_thesaurus'][$k]]; + } + + return [Class_IntProfilDonnees::PROFILE_INDEX_SYSTEMS_FIELDS => $index_systems]; + } +} diff --git a/library/Class/ScriptLoader.php b/library/Class/ScriptLoader.php index 97922989c5962820a7ae0175edb93665c0390e16..988359955471ca7d94aadd172c1e34a2f6d4d1ca 100644 --- a/library/Class/ScriptLoader.php +++ b/library/Class/ScriptLoader.php @@ -869,4 +869,9 @@ class Class_ScriptLoader { public function getDate() { return date('Y-m-d H:i:s', static::getTimeSource()->time()); } + + + public function addFontAwesome() { + return $this->addOPACStyleSheet('font-awesome-4.7.0/css/font-awesome.min.css'); + } } diff --git a/library/Class/Systeme/Report.php b/library/Class/Systeme/Report.php index b9e0002245d245ccccb88d83fc1a6f286faeb297..4419267a9ec493fc5cf5bb76b354b11725661795 100644 --- a/library/Class/Systeme/Report.php +++ b/library/Class/Systeme/Report.php @@ -272,7 +272,9 @@ class Class_Systeme_Report_Variables extends Class_Systeme_Report_Abstract { class Class_Systeme_Report_Userfiles extends Class_Systeme_Report_Abstract { public function acceptVisitor($visitor) { - $disk = Class_FileManager::getDiskSpaceInfo(); + if (!$disk = Class_FileManager::getDiskSpaceInfo()) + return; + $visitor->visitData('used', $this->_('Espace disque utilisé'), $disk->getUsed()); $visitor->visitData('free', $this->_('Espace disque libre'), $disk->getFree()); $visitor->visitData('total', $this->_('Espace disque total'), $disk->getTotal()); diff --git a/library/Class/TableDescription/CosmoWaitingFiles.php b/library/Class/TableDescription/CosmoWaitingFiles.php new file mode 100644 index 0000000000000000000000000000000000000000..c17e34f3461dbe33303704920d2986ced041de54 --- /dev/null +++ b/library/Class/TableDescription/CosmoWaitingFiles.php @@ -0,0 +1,144 @@ +<?php +/** + * Copyright (c) 2012-2018, 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_TableDescription_CosmoWaitingFiles extends Class_TableDescription { + + use Trait_Translator; + + protected $_view; + + public function setView($view) { + $this->_view = $view; + return $this; + } + + + public function read() { + $statut = function($item) { + $folder = ($parent = $item->getParent()) ? $parent->getName() : ''; + + if ($prog = Class_IntMajAuto::findFirstby(['nom_fichier' => $folder . '/' . $item->getName()])) { + $item->setProgrammed($prog); + return $this->_view->tagNotice($this->_('Programmé')); + } + + if (!$all_prog = Class_IntMajAuto::findAllBy(['where' => 'nom_fichier like "' . $folder . '/[DATE]%"'])) + return $this->_view->tagWarning($this->_('Non programmé')); + + $programmed = (new Storm_Collection($all_prog)) + ->detect( + function($element) use($item) { + return $element->isFileNameValid($item); + }); + + if (!$programmed) + return $this->_view->tagWarning($this->_('Non programmé')); + + $item->setProgrammed($programmed); + + return $programmed->isFileSizeValid($item) + ? $this->_view->tagNotice($this->_('Programmé')) + : $this->_view->tagError($this->_('Programmé mais trop petit (%s < %s)', + $this->_view->memoryFormat($item->getFileSize()), + $this->_view->memoryFormat($programmed->getFileSizeLimit()))); + }; + + $delete_url = $this->_view->url(['module' => 'cosmo', + 'controller' => 'integration', + 'action' => 'waiting-files-delete'], null, true); + + $delete = function($item) use($delete_url) { + $writable = $item->isWritable(); + $ico = $this->_view->boutonIco('type=del', + 'bulle=' . ($writable + ? $this->_('Supprimer le fichier %s', $item->getName()) + : $this->_('Impossible de supprimer le fichier %s car il y a un problème de droits', $item->getName()))); + + return ($writable + ? $this->_view->tagAnchor($delete_url . '?' . http_build_query(['id' => $item->getId()]), + $ico) + : $this->_view->tag('span', + $ico, + ['style' => 'filter: opacity(0.3); cursor: not-allowed'])); + }; + + $download_url = $this->_view->url(['module' => 'cosmo', + 'controller' => 'integration', + 'action' => 'waiting-files-download'], null, true); + + $download = function($item) use($download_url) { + return $this->_view->tagAnchor($download_url . '?' . http_build_query(['id' => $item->getId()]), + $this->_view->boutonIco('picto=down', + 'bulle='. $this->_('Télécharger le fichier %s', $item->getName()))); + }; + + $this + ->addColumn($this->_('Dossier'), + function($item) { return ($parent = $item->getParent()) ? $parent->getName() : ''; }) + + ->addColumn($this->_('Fichier'), + function($item) { return $item->getName(); }) + + ->addColumn($this->_('Transféré le'), + function($item) { return $item->getMTime(); }) + + ->addColumn($this->_('Taille'), + function($item) { return $this->_view->memoryFormat($item->getFileSize()); }) + + ->addColumn($this->_('Statut'), $statut) + + ->addColumn($this->_('Bibliothèque'), + function($item) { + return ($prog = $item->getProgrammed()) + ? $prog->getLibraryLabel() + : ''; + }) + + ->addColumn($this->_('Intégration'), + function($item) { + return ($prog = $item->getProgrammed()) + ? $prog->getLibelle() + : ''; + }) + + ->addColumn($this->_('Type d\'opération'), + function($item) { + return ($prog = $item->getProgrammed()) + ? $prog->getOperationLabel() + : ''; + }) + + ->addColumn($this->_('Profil de données'), + function($item) { + return ($prog = $item->getProgrammed()) + ? $prog->getDataProfileLabel() + : ''; + }) + + ->addRowAction($delete) + + ->addRowAction($download) + ; + + return $this; + } +} \ No newline at end of file diff --git a/library/Class/TimeSource.php b/library/Class/TimeSource.php index 4ec2964607c8917bec6f096ec05eecb077b95f24..0be9b3aaec29da3663a65c715463c84e7c359b6d 100644 --- a/library/Class/TimeSource.php +++ b/library/Class/TimeSource.php @@ -99,8 +99,8 @@ class Class_TimeSource { return (int)($this->hoursFrom($time) / 24); } + public function hoursFrom($time) { return (int)(($this->time() - $time) / 3660); } - } \ No newline at end of file diff --git a/library/Class/UrlManager.php b/library/Class/UrlManager.php index 1bd5c7548e1c388878535db41636f064a365a1e8..7ef36e6c2229765e742e44d5226e7ee0e7779208 100644 --- a/library/Class/UrlManager.php +++ b/library/Class/UrlManager.php @@ -45,7 +45,7 @@ class Class_UrlManager extends Class_Entity { '://'], '', $term); - $preg = '@(' . $protocol . '://'. $search_pattern . '*' . $preg_term . $search_pattern . '*)[\b\s]?@i'; + $preg = '@(' . $protocol . '://'. $search_pattern . '*' . preg_quote($preg_term) . $search_pattern . '*)[\b\s]?@i'; } $this diff --git a/library/Class/Users.php b/library/Class/Users.php index b1a9513cad1ea8b95c2a41f6a2d595f18b02d094..5c917a7adea4143d91341b66749c80a8b0589684 100644 --- a/library/Class/Users.php +++ b/library/Class/Users.php @@ -196,16 +196,13 @@ class UsersLoader extends Storm_Model_Loader { } - /** - * @param Class_Article - * @return bool - */ public function isCurrentUserCanAccessAllBibs() { if (!$user = Class_Users::getIdentity()) return false; return $user->canAccessAllBibs(); } + /** * @return array */ @@ -213,6 +210,7 @@ class UsersLoader extends Storm_Model_Loader { return $this->findAllBy(['role_level' => 2]); } + public function getBorrowersModifiedAfter($dateMaj){ $condition = "role_level = 2 and date_maj >= '".$dateMaj."'"; return $this->findAllBy(['where' => $condition]); @@ -311,6 +309,42 @@ class UsersLoader extends Storm_Model_Loader { $count_params = $this->_buildSearchParams($defaults, $where, $valide_subscription); return Class_Users::countBy($count_params); } + + + public function findOrFetchFromSigbByLogin($login) { + if ($user = Class_Users::findFirstBy(['login' => $login])) + return $user; + + $libraries = (new Storm_Model_Collection(Class_IntBib::findAllWithWebServices())) + ->select( + function($library) { + return ($service = $library->getSIGBComm()) + && $service->providesLookupPatronByLogin(); + }); + + foreach($libraries as $library) + if ($user = $this->_fetchFromSigbByLogin($library, $login)) + return $user; + } + + + protected function _fetchFromSigbByLogin($library, $login) { + $patron = $library->getSIGBComm()->lookupPatronByLogin($login); + if (!$patron->isValid()) + return; + + $user = Class_Users::newInstance()->beAbonneSIGB(); + $patron->updateUser($user); + $user + ->setLogin($login) + ->setIdSite($library->getId()) + ->setIdIntBib($library->getId()); + if (!Class_AdminVar::isLoginThroughSigbOnlyEnabled()) + $user->setPassword(uniqid()); + $user->save(); + + return $user; + } } @@ -1781,8 +1815,8 @@ class Class_Users extends Storm_Model_Abstract { public function getRedmineLibraries() { - if($this->getRoleLevel() >= ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL) - return Class_Bib::findAllBy(['order' => 'libelle']); + if ($this->getRoleLevel() >= ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL) + return Class_Bib::findAllRedmineEnabled(); return [$this->getRedmineLibrary()]; } diff --git a/library/Class/WebService/Redmine/Workflow/Afibre.php b/library/Class/WebService/Redmine/Workflow/Afibre.php index b298a4442ee2e14e01dfdc7a2d3b774a85029e76..f739596668a0ca38257911b6ce2e44bf4ddc9753 100644 --- a/library/Class/WebService/Redmine/Workflow/Afibre.php +++ b/library/Class/WebService/Redmine/Workflow/Afibre.php @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -class Class_WebService_Redmine_Workflow_Afibre extends Class_WebService_Redmine_Workflow_Abstract { +class Class_WebService_Redmine_Workflow_Afibre extends Class_WebService_Redmine_Workflow_Abstract { const A_QUALIFIER = 1, AFFECTE_HEBERGEMENT = 13, @@ -34,24 +34,31 @@ class Class_WebService_Redmine_Workflow_Afibre extends Class_WebService_Redmine A_INTEGRER = 17, RETOUR_DEV = 22; - protected $_transitions = [self::A_QUALIFIER => [self::FERME], - 14 => [self::A_QUALIFIER], - 15 => [], - self::AFFECTE_HOTLINE => [self::AFFECTE_DEV, self::FERME], - self::AFFECTE_SYSTEME => [], - self::AFFECTE_DEV => [self::A_QUALIFIER, self::FERME], - self::AFFECTE_HEBERGEMENT => [], - self::RETOUR_DEV => [], - self::EN_DEVELOPPEMENT => [self::FERME], - 18 => [], - 16 => [], - self::A_TESTER => [self::FERME], - self::A_INTEGRER => [], - self::QUESTION_CLIENT => [self::AFFECTE_HOTLINE, self::FERME], - 8 => [self::FERME], - self::TRANSFERT_DEV => [], - self::FERME => [self::A_QUALIFIER], - 6 => [self::A_QUALIFIER, self::FERME]]; + /** @var array of [ from_status => [to_status, to_status...]] */ + protected $_transitions = []; + + + public function __construct() { + $this->_transitions = [static::A_QUALIFIER => [static::FERME], + 14 => [static::A_QUALIFIER], + 15 => [], + static::AFFECTE_HOTLINE => [static::AFFECTE_DEV, static::FERME], + static::AFFECTE_SYSTEME => [], + static::AFFECTE_DEV => [static::A_QUALIFIER, static::FERME], + static::AFFECTE_HEBERGEMENT => [], + static::RETOUR_DEV => [], + static::EN_DEVELOPPEMENT => [static::FERME], + 18 => [], + 16 => [], + static::A_TESTER => [static::FERME], + static::A_INTEGRER => [], + static::QUESTION_CLIENT => [static::AFFECTE_HOTLINE, static::FERME], + 8 => [static::FERME], + static::TRANSFERT_DEV => [], + static::FERME => [static::A_QUALIFIER], + 6 => [static::A_QUALIFIER, static::FERME]]; + } + public function getTransitions() { return $this->_transitions; @@ -59,7 +66,7 @@ class Class_WebService_Redmine_Workflow_Afibre extends Class_WebService_Redmine public function getFormSelectedStatusIdForCurrent($status_id) { - return $status_id == self::QUESTION_CLIENT ? self::AFFECTE_HOTLINE : $status_id; + return $status_id == static::QUESTION_CLIENT ? static::AFFECTE_HOTLINE : $status_id; } @@ -68,8 +75,9 @@ class Class_WebService_Redmine_Workflow_Afibre extends Class_WebService_Redmine return count($issues ->select(function($issue) - { - return $issue->getStatusId() == self::QUESTION_CLIENT; - })); + { + return in_array($issue->getStatusId(), [static::QUESTION_CLIENT, + static::A_TESTER]); + })); } } \ No newline at end of file diff --git a/library/Class/WebService/SIGB/AbstractService.php b/library/Class/WebService/SIGB/AbstractService.php index e5e527a006d3edac6d63989e32dbded2a0146490..dd2a4bf2d495aa2b80a0433bfa4cb2fc487f0282 100644 --- a/library/Class/WebService/SIGB/AbstractService.php +++ b/library/Class/WebService/SIGB/AbstractService.php @@ -209,6 +209,18 @@ abstract class Class_WebService_SIGB_AbstractService { } + /** @return bool */ + public function providesLookupPatronByLogin() { + return false; + } + + + /** @return Class_WebService_SIGB_Emprunteur */ + public function lookupPatronByLogin($login) { + return Class_WebService_SIGB_Emprunteur::nullInstance(); + } + + abstract public function getServerRoot(); abstract public function getEmprunteur($user); diff --git a/library/Class/WebService/SIGB/Koha.php b/library/Class/WebService/SIGB/Koha.php index df338d6cd6a7b0254370de20a97dde4969078b0f..bd387179858d04a5d6b06526f55a098a3b2c391d 100644 --- a/library/Class/WebService/SIGB/Koha.php +++ b/library/Class/WebService/SIGB/Koha.php @@ -69,5 +69,3 @@ class Class_WebService_SIGB_Koha { static::$services = []; } } - -?> \ No newline at end of file diff --git a/library/Class/WebService/SIGB/Koha/RestfulService.php b/library/Class/WebService/SIGB/Koha/RestfulService.php index 17ee858b192b2a7c91bfd2dcaf693d72d3509f5b..6101926c49341e7eadf11dd0b8d6fb661f482695 100644 --- a/library/Class/WebService/SIGB/Koha/RestfulService.php +++ b/library/Class/WebService/SIGB/Koha/RestfulService.php @@ -219,6 +219,16 @@ class Class_WebService_SIGB_Koha_RestfulService } + public function providesLookupPatronByLogin() { + return $this->_forwardToIlsdi(__FUNCTION__, func_get_args()); + } + + + public function lookupPatronByLogin($login) { + return $this->_forwardToIlsdi(__FUNCTION__, func_get_args()); + } + + protected function _forwardToIlsdi($name, $params) { return call_user_func_array([$this->_ilsdi_service, $name], $params); } diff --git a/library/Class/WebService/SIGB/Koha/Service.php b/library/Class/WebService/SIGB/Koha/Service.php index f2452b21c47e94fa6fb434ea8dbc72d6df97952e..2fa5a8889a865dc05c25ce541a7cbf7753798fe3 100644 --- a/library/Class/WebService/SIGB/Koha/Service.php +++ b/library/Class/WebService/SIGB/Koha/Service.php @@ -362,4 +362,19 @@ class Class_WebService_SIGB_Koha_Service extends Class_WebService_SIGB_AbstractR ? $this->getRestfulService()->saveEmprunteur($emprunteur) : parent::saveEmprunteur($emprunteur); } + + + public function providesLookupPatronByLogin() { + return true; + } + + + public function lookupPatronByLogin($login) { + $response = $this->httpGet(['service' => 'LookupPatron', + 'id' => $login]); + + return ($patron_id = $this->_getTagData($response, 'id')) + ? $this->getEmprunteurFor($patron_id)->beValid() + : Class_WebService_SIGB_Emprunteur::nullInstance(); + } } \ No newline at end of file diff --git a/library/Class/WebService/SIGB/Nanook/Service.php b/library/Class/WebService/SIGB/Nanook/Service.php index ac30505db7302a232a9b25eebd8838e3c37b82e2..d474d356220777977b0b57bffb85c7b012e3ab32 100644 --- a/library/Class/WebService/SIGB/Nanook/Service.php +++ b/library/Class/WebService/SIGB/Nanook/Service.php @@ -125,6 +125,11 @@ class Class_Webservice_SIGB_Nanook_Service extends Class_WebService_SIGB_Abstrac } + public function providesChangePasswordService() { + return true; + } + + public function saveEmprunteur($emprunteur) { $xml = $this->getWebClient() ->postData($this->buildQueryURL(['service'=>'UpdatePatronInfo', diff --git a/library/Class/WebService/SIGB/Orphee/Service.php b/library/Class/WebService/SIGB/Orphee/Service.php index a091eac712b9230b529588cc30af6a13e36bec48..1441ba487ad41272a8f19c24b752cf2e620cf1a6 100644 --- a/library/Class/WebService/SIGB/Orphee/Service.php +++ b/library/Class/WebService/SIGB/Orphee/Service.php @@ -104,6 +104,13 @@ class Class_WebService_SIGB_Orphee_Service extends Class_WebService_SIGB_Abstrac } + /** @category testing */ + public function setSessionStrategy($strategy) { + $this->_session_strategy = $strategy; + return $this; + } + + public function isConnected() { try { return $this->getSessionStrategy()->isConnected(); @@ -329,6 +336,34 @@ class Class_WebService_SIGB_Orphee_Service extends Class_WebService_SIGB_Abstrac public function _newOrpheeException($message) { throw new Class_WebService_Exception('Le SIGB Orphée a retourné l\'erreur suivante: '.$message); } + + + public function providesLookupPatronByLogin() { + return true; + } + + + public function lookupPatronByLogin($login) { + return $this + ->willTry( + function() use ($login) { + if (!$this->isConnected()) + return $this->newNullEmprunteur(); + + $result = $this->hasGetAdh() + ? $this->_search_client->GetAdh(GetAdh::withNo($login)) + : $this->_search_client->GetInfoUserCarte(GetInfoUserCarte::withNo($login)); + + if (!$emprunteur = Class_WebService_SIGB_Orphee_GetInfoUserCarteResponseReader + ::newInstance() + ->getEmprunteurFromXML($result->getXml())) + return $this->newNullEmprunteur(); + + return $emprunteur + ->beValid() + ->setService($this); + }); + } } @@ -444,7 +479,7 @@ class GetAdhResponse { public static function withResult($xml) { $instance = new self(); - $instance->GetAdhResponse = $xml; + $instance->GetAdhResult = $xml; return $instance; } diff --git a/library/ZendAfi/Acl/AdminControllerGroup.php b/library/ZendAfi/Acl/AdminControllerGroup.php index 9693cfd026d3cd79eba28aa1ba6e2cf38f2f6eab..9624585c79d0b693c0c8353f3bf1436fe7fc06b7 100644 --- a/library/ZendAfi/Acl/AdminControllerGroup.php +++ b/library/ZendAfi/Acl/AdminControllerGroup.php @@ -50,8 +50,8 @@ class ZendAfi_Acl_AdminControllerGroup { public function __construct() { $this->_activated = ['activity' => Class_AdminVar::isActivityEnabled(), 'album' => Class_AdminVar::isBibNumEnabled(), - 'oai' => Class_AdminVar::isBibNumEnabled(), - 'ead' => Class_AdminVar::isBibNumEnabled(), + 'oai' => Class_AdminVar::isBibNumEnabled() && Class_AdminVar::isOaiRepositoryEnabled(), + 'opds' => Class_AdminVar::isBibNumEnabled() && Class_AdminVar::isOpdsEnabled(), 'harvest/arte-vod-browse' => Class_AdminVar::isArteVODEnabled(), 'harvest/vodeclic-browse' => Class_AdminVar::isVodeclicEnabled(), 'harvest/orphea-browse' => Class_AdminVar::isOrpheaEnabled(), @@ -61,11 +61,18 @@ class ZendAfi_Acl_AdminControllerGroup { 'harvest/soundcloud' => Class_AdminVar::isSoundCloudEnabled(), 'sito/create' => Class_AdminVar::isSitoInAlbums(), 'album/dilicom' => Class_AdminVar::isDilicomPNBEnabled(), + 'album/import_ead' => Class_AdminVar::isImportEadEnabled(), 'premier-chapitre' => Class_AdminVar::isPremierChapitreEnabled(), 'i18n' => Class_AdminVar::isTranslationEnabled(), 'stat/matomo' => (new Class_AdminVar_Matomo())->isEnabled(), 'multimedia' => Class_AdminVar::isMultimediaEnabled(), 'search-form' => Class_AdminVar::isCustomSearchFormEnabled(), + 'systeme/importthesaurus' => Class_AdminVar::isImportThesaurusEnabled(), + 'systeme/generationsite' => Class_AdminVar::isGenerationSiteEnabled(), + 'systeme/webservices' => Class_AdminVar::isWebserviceTestEnabled(), + 'systeme/importavisopac2' => Class_AdminVar::isImportAvisOpac2Enabled(), + 'profil/genres' => Class_AdminVar::isCustomGenreIconEnabled(), + 'custom-fields-report' => Class_AdminVar::isCustomFieldsReportEnabled(), ]; $this->_activated = array_merge($this->_activated, diff --git a/library/ZendAfi/Acl/AdminControllerRoles.php b/library/ZendAfi/Acl/AdminControllerRoles.php index 8e0cdfef71d309751b6a888aadf957e57ebe3d9c..8b54e8a589d93d7f09a852ced4cfb6ad72cad632 100644 --- a/library/ZendAfi/Acl/AdminControllerRoles.php +++ b/library/ZendAfi/Acl/AdminControllerRoles.php @@ -90,6 +90,9 @@ class ZendAfi_Acl_AdminControllerRoles extends Zend_Acl { $this->add(new Zend_Acl_Resource('print')); $this->add(new Zend_Acl_Resource('external-agendas')); $this->add(new Zend_Acl_Resource('systeme')); + $this->add(new Zend_Acl_Resource('systeme/webservices')); + $this->add(new Zend_Acl_Resource('systeme/phpinfo')); + $this->add(new Zend_Acl_Resource('custom-fields-report')); $this->add(new Zend_Acl_Resource('batch')); $this->add(new Zend_Acl_Resource('file-manager')); $this->add(new Zend_Acl_Resource('url-manager')); @@ -191,6 +194,9 @@ class ZendAfi_Acl_AdminControllerRoles extends Zend_Acl { $this->deny('modo_portail','systeme'); $this->deny('modo_portail','batch'); $this->deny('modo_portail','search-form'); + $this->deny('modo_portail','custom-fields-report'); + $this->deny('modo_portail','systeme/webservices'); + $this->deny('modo_portail','systeme/phpinfo'); foreach($codifications as $controller) $this->deny('modo_portail', $controller); diff --git a/library/ZendAfi/Controller/Action/Helper/FileManagerDownload.php b/library/ZendAfi/Controller/Action/Helper/FileManagerDownload.php new file mode 100644 index 0000000000000000000000000000000000000000..9fec6a4c87bc78cff3224a58597797c524839469 --- /dev/null +++ b/library/ZendAfi/Controller/Action/Helper/FileManagerDownload.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright (c) 2012-2017, 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_FileManagerDownload + extends Zend_Controller_Action_Helper_Abstract { + + /** @param $file_manager Class_FileManager */ + public function direct($file_manager) { + Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->setNoRender(); + + if ($layout = Zend_Layout::getMvcInstance()) + $layout->disableLayout(); + + $response = $this->getResponse(); + $response->canSendHeaders(true); + + $response->clearAllHeaders(); + $response->setHeader('Content-Type', 'application/octet-stream; name="' . $file_manager->getName() . '"', true); + $response->setHeader('Content-Transfer-Encoding', 'binary', true); + + $response->setHeader('Content-Length', $file_manager->getFileSize(), true); + $response->setHeader('Expires', '0'); + $response->setHeader('Cache-Control', 'no-cache, must-revalidate'); + $response->setHeader('Pragma', 'no-cache'); + + $response->setHeader('Content-Disposition', 'attachment; filename="' . $file_manager->getName() . '"', true); + + $response->sendHeaders(); + + $file_manager->readfile(); + } +} diff --git a/library/ZendAfi/Controller/Plugin/Manager/DynamicFacet.php b/library/ZendAfi/Controller/Plugin/Manager/DynamicFacet.php new file mode 100644 index 0000000000000000000000000000000000000000..76dffb5dee3119e7dfe790b5d6650d43c8df0225 --- /dev/null +++ b/library/ZendAfi/Controller/Plugin/Manager/DynamicFacet.php @@ -0,0 +1,75 @@ +<?php +/** + * Copyright (c) 2012-2017, 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_Plugin_Manager_DynamicFacet + extends ZendAfi_Controller_Plugin_Manager_ExternalManager { + + public function getActions($model) { + if (!$model) + return []; + + return [ + ['url' => ['module' => 'cosmo', + 'controller' => 'facets', + 'action' => 'edit', + 'id' => '%s'], + 'icon' => 'edit', + 'label' => $this->_('Modifier la facette dynamique')], + + ['url' => ['module' => 'cosmo', + 'controller' => 'facets', + 'action' => 'delete', + 'id' => '%s'], + 'icon' => 'delete', + 'label' => $this->_('Supprimer la facette dynamique')], + ]; + } + + + protected function _updateNewModel($model) { + return $model->setLibelle('** nouvelle facette dynamique **'); + } + + + protected function _getFormValues($model) { + return array_merge(parent::_getFormValues($model), + $model->getRulesAsArray()); + } + + + protected function _doBeforeSave($model) { + if (!$model->isNew()) + return; + + $libelle = preg_replace('/[^a-zA-Z0-9]/', '', $model->getLibelle()); + $id_thesaurus = Class_CodifThesaurus::newIdThesaurusForLabel($libelle); + + $model->setIdThesaurus($id_thesaurus) + ->setCode($id_thesaurus); + } + + + protected function _redirectToEdit($model) { + $this->_redirectClose(sprintf('/cosmo/%s/edit/id/%s', + $this->_request->getControllerName(), $model->getId())); + } +} \ No newline at end of file diff --git a/library/ZendAfi/Controller/Plugin/Manager/Library.php b/library/ZendAfi/Controller/Plugin/Manager/Library.php index c93d05832296810ee6afb5a75c5c6252b8d258dc..3837c4d03c1334adb5c15cb1286864bf2b4e7016 100644 --- a/library/ZendAfi/Controller/Plugin/Manager/Library.php +++ b/library/ZendAfi/Controller/Plugin/Manager/Library.php @@ -54,6 +54,36 @@ class ZendAfi_Controller_Plugin_Manager_Library extends ZendAfi_Controller_Plugi } + public function localisationsAction() { + $id_bib = (int)$this->_request->getParam('id_bib'); + $this->_view->id_bib = $id_bib; + if (!$bib = Class_Bib::find($id_bib)) + return $this->_redirect('admin/bib/index'); + + $this->_addModelToView($bib); + $this->_view->nom_bib = $bib->getLibelle(); + $this->_view->localisations = $bib->getLocalisations(); + $this->_view->titre = $this->_view->_("Localisations de la bibliothèque: %s", + $bib->getLibelle()); + } + + + public function plansAction() { + $id_bib = (int)$this->_request->getParam('id_bib'); + if (!$bib= Class_Bib::find($id_bib)) + return $this->_redirect('admin/'); + + $this->_addModelToView($bib); + $this->_view->id_bib = $id_bib; + $this->_view->nom_bib = $bib->getLibelle(); + $this->_view->plans = $bib->getPlans(); + $this->_view->titre = $this->_view->_('Plans de la bibliothèque: %s', + $bib->getLibelle()); + } + + + + public function getActions($model) { return [['url' => '/admin/bib/edit/id/%s', 'icon' => 'edit', diff --git a/library/ZendAfi/Controller/Plugin/Manager/Opening.php b/library/ZendAfi/Controller/Plugin/Manager/Opening.php index c7c34b3090c99093c0bdc9fa1a8d2b76ad53972f..58960dfd139fabd13a079ac94a04e77a679cc36b 100644 --- a/library/ZendAfi/Controller/Plugin/Manager/Opening.php +++ b/library/ZendAfi/Controller/Plugin/Manager/Opening.php @@ -39,6 +39,13 @@ class ZendAfi_Controller_Plugin_Manager_Opening extends ZendAfi_Controller_Plugi } + public function getActions($model) { + return $model->getClassName() == 'Class_Bib' + ? (new ZendAfi_Controller_Plugin_Manager_Library($this->_controller))->getActions($model) + : []; + } + + protected function _doBeforeSave($model) { return $model->setIdSite($this->_getParam('id_site', 0)); } diff --git a/library/ZendAfi/Controller/Plugin/ResourceDefinition/Abstract.php b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Abstract.php index ebfae2e7f10607e71e2b83fd3c7d5f4b452d9d67..288d88ee48b512208cd118e5f651646fb51d0c9d 100644 --- a/library/ZendAfi/Controller/Plugin/ResourceDefinition/Abstract.php +++ b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Abstract.php @@ -78,7 +78,10 @@ abstract class ZendAfi_Controller_Plugin_ResourceDefinition_Abstract extends Zen public function findAll($request) { - return $this->findAllBy($this->_addScopeParam([], $request)); + $params = $this->_addScopeParam([], $request); + $params = $this->_addFilterParams($params); + + return $this->findAllBy($params); } @@ -90,6 +93,13 @@ abstract class ZendAfi_Controller_Plugin_ResourceDefinition_Abstract extends Zen } + protected function _addFilterParams($params) { + return ($filter = $this->getFilter()) + ? array_merge($params, $filter) + : $params; + } + + protected function _addScopeParam($params, $request) { $closure = function($item, $value) use (&$params) { $params[$item] = $value; @@ -230,6 +240,13 @@ abstract class ZendAfi_Controller_Plugin_ResourceDefinition_Abstract extends Zen } + public function getFilter() { + return (isset($this->_attribs['model']['filter'])) + ? $this->_attribs['model']['filter'] + : []; + } + + public function getModelName() { return $this->_attribs['model']['name']; } diff --git a/library/ZendAfi/Controller/Plugin/ResourceDefinition/DynamicFacet.php b/library/ZendAfi/Controller/Plugin/ResourceDefinition/DynamicFacet.php new file mode 100644 index 0000000000000000000000000000000000000000..6866d7a068d4b49c980c2712511ada7785c8361d --- /dev/null +++ b/library/ZendAfi/Controller/Plugin/ResourceDefinition/DynamicFacet.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright (c) 2012-2017, 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_Plugin_ResourceDefinition_DynamicFacet extends ZendAfi_Controller_Plugin_ResourceDefinition_Abstract { + public function getDefinitions() { + return + ['model' => ['class' => 'Class_CodifThesaurus', + 'name' => 'thesauri', + 'filter' => ['where' => 'rules is not null and rules != ""'], + 'order' => 'libelle'], + + 'messages' => ['successful_save' => $this->_('Facette dynamique "%s" sauvegardée'), + 'successful_delete' => $this->_('Facette dynamique "%s" supprimée')], + + 'actions' => ['index' => ['title' => $this->_('Facettes dynamiques')], + 'add' => ['title' => $this->_('Ajouter une facette dynamique')], + 'edit' => ['title' => $this->_("Modifier une facette dynamique")]], + + 'form_class_name' => 'ZendAfi_Form_Admin_DynamicFacet']; + } +} \ No newline at end of file diff --git a/library/ZendAfi/Form/Admin/DynamicFacet.php b/library/ZendAfi/Form/Admin/DynamicFacet.php new file mode 100644 index 0000000000000000000000000000000000000000..08a3791067deae1a7203778c3ede74913d0a278f --- /dev/null +++ b/library/ZendAfi/Form/Admin/DynamicFacet.php @@ -0,0 +1,96 @@ +<?php +/** + * Copyright (c) 2012-2017, 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_Admin_DynamicFacet extends ZendAfi_Form { + + public function init() { + parent::init(); + + $field_options = ['' => '', + '#' => '$0']; + foreach(range(1, 9) as $field) + $field_options[(string) $field] = '$'.$field; + + foreach(range('a', 'z') as $field) + $field_options[$field] = '$'.$field; + + $this + ->addElement('text', + 'libelle', + ['label' => $this->_('Libellé'), + 'required' => true, + 'allowEmpty' => false]) + + ->addElement('text', + 'rule_zone', + ['label' => $this->_('Zone'), + 'size' => 3, + 'maxlength' => 3, + 'required' => true, + 'allowEmpty' => false, + 'validators' => [(new Zend_Validate_Regex('/^[0-9]{3}$/')) + ->setMessage($this->_('La zone doit être composée de 3 chiffres (001, 015, etc...)'))]]) + + ->addElement('select', + 'rule_label_field', + ['label' => $this->_('Prendre le libellé en'), + 'multiOptions' => $field_options, + 'required' => true, + 'allowEmpty' => false]) + + ->addElement('number', + 'rule_label_start_pos', + ['label' => $this->_('Position du premier caractère du libellé'), + 'required' => true, + 'allowEmpty' => false, + 'min' => 1]) + + + ->addElement('number', + 'rule_label_length', + ['label' => $this->_('Longueur du libellé (0 pour prendre totalité du libellé)'), + 'required' => true, + 'allowEmpty' => false, + 'min' => 0]) + + ->addElement('select', + 'rule_id_field', + ['label' => $this->_('Prendre l\'identifiant en'), + 'multiOptions' => $field_options]) + + ->addElement('text', + 'libelle_facette', + ['label' => $this->_('Libellé dans Bokeh')]) + + ->addElement('text', + 'code', + ['label' => $this->_('Code'), + 'disabled' => 'disabled']) + + ->addElement('text', + 'id_thesaurus', + ['label' => $this->_('Identifiant thésaurus'), + 'disabled' => 'disabled']) + + ->addUniqDisplayGroup('thesauri'); + } +} \ No newline at end of file diff --git a/library/ZendAfi/Form/Admin/Newsletter.php b/library/ZendAfi/Form/Admin/Newsletter.php index 88cb4f85c7a686c954bc1ff125cee8f1024c25b1..63deb88f251960ecdae54d36cb72425c40dfa4f2 100644 --- a/library/ZendAfi/Form/Admin/Newsletter.php +++ b/library/ZendAfi/Form/Admin/Newsletter.php @@ -62,6 +62,7 @@ class ZendAfi_Form_Admin_Newsletter extends ZendAfi_Form { 'value' => 0, 'validators' => [new Zend_Validate_Int()]]) + ->addDisplayGroup(['titre', 'expediteur', 'draft'], 'letter', ['legend' => $this->_('Lettre')]) @@ -74,4 +75,39 @@ class ZendAfi_Form_Admin_Newsletter extends ZendAfi_Form { 'notices', ['legend' => $this->_('Notices')]); } + + + public function populate($datas) { + parent::populate($datas); + + $this + ->addElement('treeSelect', + 'articles_selector', + ['UrlDataSource' => Class_Url::assemble(['module' => 'admin', + 'controller' => 'bib', + 'action' => 'articles']), + + 'InputIdItemsName' => 'articles_ids', + 'IdItems' => isset($datas['articles_ids']) ? $datas['articles_ids'] : '', + 'ItemRenderer' => function($id) + { + if ($model = Class_Article::find($id)) + return $model->getTitre(); + }, + + 'InputIdCategoriesName' => 'articles_categories_ids', + 'IdCategories' => isset($datas['articles_categories_ids']) ? $datas['articles_categories_ids'] : '', + 'CategoryRenderer' => function($id) + { + if ($model = Class_ArticleCategry::find($id)) + return $model->getLibelle(); + }, + + ]); + + $this->addDisplayGroup(['articles_selector'], + 'articles', + ['legend' => $this->_('Articles')]); + return $this; + } } diff --git a/library/ZendAfi/Form/Cosmo/DataProfile.php b/library/ZendAfi/Form/Cosmo/DataProfile.php index ea2f934fc98ff69f603f15f7be598af152562fbf..887fbc0923149e96c91573e3e39211b1b472b070 100644 --- a/library/ZendAfi/Form/Cosmo/DataProfile.php +++ b/library/ZendAfi/Form/Cosmo/DataProfile.php @@ -470,6 +470,11 @@ class ZendAfi_Form_Cosmo_DataProfile extends ZendAfi_Form { } + public function getProfilePrefs() { + return $this->_profile_prefs; + } + + public function getDefaultFormat() { return $this->_strategy->getDefaultFormat(); } diff --git a/library/ZendAfi/Form/Element/Number.php b/library/ZendAfi/Form/Element/Number.php new file mode 100644 index 0000000000000000000000000000000000000000..579936c7dcbd921251fb0b97bf3fc3bf41d30256 --- /dev/null +++ b/library/ZendAfi/Form/Element/Number.php @@ -0,0 +1,35 @@ +<?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_Form_Element_Number extends Zend_Form_Element_Text { + /** + * HTML5 input type = number + * @var string + */ + public $helper = 'formNumber'; + + + public function init() { + $this->addValidator(new Zend_Validate_Int()); + } +} + +?> \ No newline at end of file diff --git a/library/ZendAfi/Form/Element/SelectDynamicFacet.php b/library/ZendAfi/Form/Element/SelectDynamicFacet.php new file mode 100644 index 0000000000000000000000000000000000000000..6f9ec980e9c08403e084f1737b461c4230c1eb74 --- /dev/null +++ b/library/ZendAfi/Form/Element/SelectDynamicFacet.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright (c) 2012-2017, 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_Element_SelectDynamicFacet extends Zend_Form_Element_Select { + public function init() { + if (!$thesaurus = Class_CodifThesaurus::findFirstBy(['rules not' => null, + 'code' => $this->_getCodeThesaurus(), + 'id_thesaurus not' => null])) + return; + + $this->setMultiOptions($this->_buildThesaurusChildrenEntries($thesaurus)); + } + + + protected function _getCodeThesaurus() { + return str_replace('rech_' . Class_CodifThesaurus::CODE_FACETTE, '', $this->getName()); + } + + + protected function _buildThesaurusChildrenEntries($thesaurus) { + $options = ['' => '']; + + foreach (Class_CodifThesaurus::findChildrenOfWith($thesaurus->getIdThesaurus(), + 100, + 'libelle') + as $child) + $options[$child->getLibelle()] = $child->getLibelle(); + + return $options; + } + + + public function loadDefault($datas) { + } +} diff --git a/library/ZendAfi/Validate/DateFormat.php b/library/ZendAfi/Validate/DateFormat.php new file mode 100644 index 0000000000000000000000000000000000000000..d5ddd78099090838f2787a465ce89d8a435c4e2f --- /dev/null +++ b/library/ZendAfi/Validate/DateFormat.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright (c) 2012-2018, 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_Validate_DateFormat extends Zend_Validate_Abstract { + + public function isValid($string, $format = 'Y-m-d') { + if (!$string) + return false; + + $date = DateTime::createFromFormat($format, $string); + return $date && ($date->format($format) === $string); + } +} \ No newline at end of file diff --git a/library/ZendAfi/Validate/LostUsername.php b/library/ZendAfi/Validate/LostUsername.php index 086cd10cec0ca61f96d0a26299a8213900395bb9..81fa89170f48ae817d21fd7757ff26c1228b21a0 100644 --- a/library/ZendAfi/Validate/LostUsername.php +++ b/library/ZendAfi/Validate/LostUsername.php @@ -52,7 +52,7 @@ class ZendAfi_Validate_LostUsername extends Zend_Validate_Abstract { return false; } - if (!$user = Class_Users::findFirstBy(['login' => $value])) { + if (!$user = Class_Users::findOrFetchFromSigbByLogin($value)) { $this->_error(static::NO_USER); return false; } diff --git a/library/ZendAfi/View/Helper/Admin/ContentNav.php b/library/ZendAfi/View/Helper/Admin/ContentNav.php index 043d6a8a25a80d0f25a461b6c33832729d9a09e3..ea1d6c10e3c6788606ade9e57f42bb3ecc51552b 100644 --- a/library/ZendAfi/View/Helper/Admin/ContentNav.php +++ b/library/ZendAfi/View/Helper/Admin/ContentNav.php @@ -32,8 +32,9 @@ class ZendAfi_View_Helper_Admin_ContentNav extends ZendAfi_View_Helper_BaseHelpe $this->menuMiseEnPage(), $this->menuStats(), $this->menuPortail(), + $this->menuCatalogue(), $this->menuSysteme(), - $this->menuCatalogue()]; + ]; return $this->_tag('div', implode($content), @@ -67,6 +68,7 @@ class ZendAfi_View_Helper_Admin_ContentNav extends ZendAfi_View_Helper_BaseHelpe ['newsletters', $this->_("Lettres d'information"), '/admin/newsletter'], ['trainings', $this->_('Activités'), '/admin/activity'], ['places', $this->_('Lieux'), '/admin/lieu'], + ['filebrowser', $this->_('Explorateur de fichiers'), '/admin/file-manager'], ]); } @@ -140,24 +142,24 @@ class ZendAfi_View_Helper_Admin_ContentNav extends ZendAfi_View_Helper_BaseHelpe ['links', $this->_('Contrôle des URL'), '/admin/url-manager'], ['variables', $this->_('Variables'), '/admin/index/adminvar', [], $is_admin], - ['webservice_tests', $this->_('Test des web-services'), '/admin/systeme/webservices', - [], $is_super_admin], + ['webservice_tests', $this->_('Test des web-services'), '/admin/systeme/webservices', [], $is_super_admin], ['sendmail_tests', $this->_('Test envoi mails'), '/admin/systeme/mailtest', [], $is_super_admin], ['php', $this->_('Informations système'), '/admin/systeme/phpinfo', [], $is_super_admin], ['image_cache', $this->_('Cache des images'), '/admin/systeme/cacheimages', [], $is_admin], ['migrate_comments', $this->_('Import avis opac2'), '/admin/systeme/importavisopac2', - [], $is_super_admin], + [], + function ($user) use ($is_super_admin) { + return $is_super_admin($user) && Class_AdminVar::isImportAvisOpac2Enabled(); + }], - ['portal_init', $this->_('Génération du site'), '/admin/systeme/generationsite', - [], function($user) { return defined('DEVELOPMENT') && $user->isAdmin();}], + ['portal_init', $this->_('Génération du site'), '/admin/systeme/generationsite'], - ['filebrowser', $this->_('Explorateur de fichiers'), '/admin/file-manager'], ['search_form', $this->_('Formulaires de recherche'), '/admin/search-form'], ['customfields', $this->_('Champs personnalisés'), '/admin/custom-fields/index', [], $is_admin], - ['customreports', $this->_('Rapports statistiques'), '/admin/custom-fields-report', [], $is_admin] + ['customreports', $this->_('Rapports statistiques'), '/admin/custom-fields-report'] ]); } @@ -168,12 +170,8 @@ class ZendAfi_View_Helper_Admin_ContentNav extends ZendAfi_View_Helper_BaseHelpe [["doctypes", $this->_("Types de documents"), "/admin/type-docs", [], function($user) { return $user->isAdmin(); }], - ["thesaurus_init", $this->_("Import Thesaurus"), "/admin/systeme/importthesaurus", - [], function($user) { return defined('DEVELOPMENT') && $user->isAdmin();}], - - ["thesaurus_edit", - $this->_("Parcourir les codifications"), "/admin/codification-browser", - []] + ["thesaurus_init", $this->_("Import Thesaurus"), "/admin/systeme/importthesaurus"], + ["thesaurus_edit", $this->_("Parcourir les codifications"), "/admin/codification-browser"] ]); } @@ -213,91 +211,3 @@ class ZendAfi_View_Helper_Admin_MenuGaucheAdminBloc { ['class' => 'menuGaucheAdmin']); } } - - - -class ZendAfi_View_Helper_Admin_MenuGaucheAdminItem { - protected static $_acl; - - protected - $_icon, - $_title, - $_url, - $_attribs, - $_skin; - - - public static function newWith($params) { - return new static($params[0], - $params[1], - $params[2], - isset($params[3]) ? $params[3] : [], - isset($params[4]) ? $params[4] : null); - } - - - public function __construct($icon, $title, $url, $attribs=[], $filter=null) { - $this->_icon = $icon; - $this->_title = $title; - $this->_url = $url; - $this->_attribs = $attribs; - $this->_filter = $filter; - $this->_skin = Class_Admin_Skin::current(); - } - - - public function renderFor($user, $view) { - if (!$this->_isAllowed($user)) - return ''; - - $url = $this->_url; - if('http' != substr($url, 0, 4)) - $url = BASE_URL . $url; - - $extra_infos = isset($this->_attribs['extra_infos']) - ? $view->tag('span', $this->_attribs['extra_infos'], ['class' => 'menu_info']) - : ''; - - $attributes = (array_key_exists('REQUEST_URI', $_SERVER) - && false !== strpos($_SERVER['REQUEST_URI'], $url)) - ? ['class' => 'selected'] - : []; - - $anchor_params = ['href' => $url]; - if (isset($this->_attribs['target'])) - $anchor_params['target'] = $this->_attribs['target']; - - $ico = $this->_skin->renderMenuIconOn($this->_icon, $view, ['alt' => $this->_title]); - - return $view->tag('li', - $view->tag('a', $ico . $this->_title, $anchor_params) . $extra_infos, - $attributes); - } - - - protected function _isAllowed($user) { - if (($filter = $this->_filter) && !$filter($user)) - return false; - - if ('/admin/' != substr($this->_url, 0, 7)) - return true; - - $url = substr($this->_url, 7); - $parts = explode('/', $url); - - return $this->getAcl()->isAllowed($user, $parts[0], isset($parts[1]) ? $parts[1] : ''); - } - - - /** @category testing */ - public static function setAcl($acl) { - static::$_acl = $acl; - } - - - protected function getAcl() { - return static::$_acl - ? static::$_acl - : static::$_acl = new ZendAfi_Acl_AdminControllerGroup(); - } -} diff --git a/library/ZendAfi/View/Helper/Admin/FileManager.php b/library/ZendAfi/View/Helper/Admin/FileManager.php index ca97542c04f0b8b39c1cebfad0f682a8a0c3555a..fcbdab68c61a49b99cf73fd5465be79e4bbd9313 100644 --- a/library/ZendAfi/View/Helper/Admin/FileManager.php +++ b/library/ZendAfi/View/Helper/Admin/FileManager.php @@ -30,7 +30,7 @@ class ZendAfi_View_Helper_Admin_FileManager extends ZendAfi_View_Helper_BaseHelp return ''; $script_loader = Class_ScriptLoader::getInstance() - ->addOPACStyleSheet('font-awesome-4.7.0/css/font-awesome.min.css') + ->addFontAwesome() ->addOPACStyleSheet('file-manager/style.css') ->addOPACPluginScript('file-manager/file-manager.js') ->addOPACPluginStyleSheet('file-manager/file-manager.css') diff --git a/library/ZendAfi/View/Helper/Admin/HelpLink.php b/library/ZendAfi/View/Helper/Admin/HelpLink.php index 516eacce6de047f335787ede99ab8a7273b5c870..db10d5fc8a719ec4534f15cab0760cfee01d4292 100644 --- a/library/ZendAfi/View/Helper/Admin/HelpLink.php +++ b/library/ZendAfi/View/Helper/Admin/HelpLink.php @@ -76,7 +76,8 @@ class ZendAfi_View_Helper_Admin_HelpLinkBokehWiki { 'library' => 'Afficher_les_horaires_d\'ouverture'], 'ouvertures' => ['index' => 'Ouvertures_des_bibliothèques'], 'bibnum' => ['index' => 'Connecteurs'], - 'album' => ['index' => 'Collections'], + 'album' => ['index' => 'Collections', + 'add-website' => 'Sitothèque_ressource_numérique'], 'catalogue' => ['index' => 'Domaines'], 'cms' => ['index' => 'Articles_-_Créer,_rédiger_et_ordonner'], 'custom-fields' => ['index' => 'Gestion_des_champs_personnalisés'], @@ -107,7 +108,15 @@ class ZendAfi_View_Helper_Admin_HelpLinkBokehWiki { 'stat' => ['matomo' => 'Matomo'], 'print' => ['index' => 'Imprimer_un_résultat_de_recherche,_une_notice_ou_des_articles'], 'file-manager' => ['index' => 'Explorateur_de_fichiers'], - 'url-manager' => ['index' => 'Gestion_des_URL'] + 'url-manager' => ['index' => 'Gestion_des_URL'], + 'search-form' => ['index' => 'Personnalisation_de_la_recherche_avancée'], + 'sito' => ['index' => 'Indexation_des_sitothèques'], + 'external-agendas' => ['index' => 'Agendas_Externes'], + 'lieu' => ['index' => 'Modifier_un_Lieu'], + 'users' => ['index' => 'Gestion_des_utilisateurs'], + 'codification-browser' => ['index' => 'Explorateur_de_codifications'], + 'batch' => ['index' => 'Batchs,_tâches_planifiées'], + 'feature' => ['index' => 'Nouvelles_fonctionnalités'], ]; diff --git a/library/ZendAfi/View/Helper/Admin/MenuGaucheAdminItem.php b/library/ZendAfi/View/Helper/Admin/MenuGaucheAdminItem.php new file mode 100644 index 0000000000000000000000000000000000000000..76020eb755c4dd20bb6ec842c4db781ee600db8c --- /dev/null +++ b/library/ZendAfi/View/Helper/Admin/MenuGaucheAdminItem.php @@ -0,0 +1,107 @@ +<?php +/** + * Copyright (c) 2012-2019, 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_Admin_MenuGaucheAdminItem { + protected static $_acl; + + protected + $_icon, + $_title, + $_url, + $_attribs, + $_skin; + + + public static function newWith($params) { + return new static($params[0], + $params[1], + $params[2], + isset($params[3]) ? $params[3] : [], + isset($params[4]) ? $params[4] : null); + } + + + public function __construct($icon, $title, $url, $attribs=[], $filter=null) { + $this->_icon = $icon; + $this->_title = $title; + $this->_url = $url; + $this->_attribs = $attribs; + $this->_filter = $filter; + $this->_skin = Class_Admin_Skin::current(); + } + + + public function renderFor($user, $view) { + if (!$this->_isAllowed($user)) + return ''; + + $url = $this->_url; + if('http' != substr($url, 0, 4)) + $url = BASE_URL . $url; + + $extra_infos = isset($this->_attribs['extra_infos']) + ? $view->tag('span', $this->_attribs['extra_infos'], ['class' => 'menu_info']) + : ''; + + $attributes = (array_key_exists('REQUEST_URI', $_SERVER) + && false !== strpos($_SERVER['REQUEST_URI'], $url)) + ? ['class' => 'selected'] + : []; + + $anchor_params = ['href' => $url]; + if (isset($this->_attribs['target'])) + $anchor_params['target'] = $this->_attribs['target']; + + $ico = $this->_skin->renderMenuIconOn($this->_icon, $view, ['alt' => $this->_title]); + + return $view->tag('li', + $view->tag('a', $ico . $this->_title, $anchor_params) . $extra_infos, + $attributes); + } + + + protected function _isAllowed($user) { + if (($filter = $this->_filter) && !$filter($user)) + return false; + + if ('/admin/' != substr($this->_url, 0, 7)) + return true; + + $url = substr($this->_url, 7); + $parts = explode('/', $url); + + return $this->getAcl()->isAllowed($user, $parts[0], isset($parts[1]) ? $parts[1] : ''); + } + + + /** @category testing */ + public static function setAcl($acl) { + static::$_acl = $acl; + } + + + protected function getAcl() { + return static::$_acl + ? static::$_acl + : static::$_acl = new ZendAfi_Acl_AdminControllerGroup(); + } +} diff --git a/library/ZendAfi/View/Helper/AdvancedSearch.php b/library/ZendAfi/View/Helper/AdvancedSearch.php index f75765a488448ab13fe7fcc952b53c4c48de1b03..56f501e541b449d0887a9b0b2bd895a58bb34679 100644 --- a/library/ZendAfi/View/Helper/AdvancedSearch.php +++ b/library/ZendAfi/View/Helper/AdvancedSearch.php @@ -59,8 +59,9 @@ class ZendAfi_View_Helper_AdvancedSearch extends ZendAfi_View_Helper_BaseHelper protected function _renderDefaultAdvancedSearch() { - return $this->view->renderForm($this->_defaultAdvancedSearch(), - ['append' => [$this->_clearFormButton()]]); + $form_id = 'advanced_form'; + return $this->view->renderForm($this->_defaultAdvancedSearch($form_id), + ['append' => [$this->_clearFormButton($form_id)]]); } @@ -77,8 +78,8 @@ class ZendAfi_View_Helper_AdvancedSearch extends ZendAfi_View_Helper_BaseHelper } - protected function _defaultAdvancedSearch() { - return $this->_populateForm((new ZendAfi_Form_AdvancedSearch)->loadDefaults()); + protected function _defaultAdvancedSearch($form_id) { + return $this->_populateForm((new ZendAfi_Form_AdvancedSearch)->loadDefaults(), $form_id); } diff --git a/library/ZendAfi/View/Helper/CosmoFacets.php b/library/ZendAfi/View/Helper/CosmoFacets.php deleted file mode 100644 index 351d21879d8e37520d4d2d7d470beafc86f4ba3b..0000000000000000000000000000000000000000 --- a/library/ZendAfi/View/Helper/CosmoFacets.php +++ /dev/null @@ -1,139 +0,0 @@ -<?php -/** - * Copyright (c) 2012-2014, 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_CosmoFacets extends ZendAfi_View_Helper_CosmoEmplacement { - public function cosmoFacets($model, $display) { - $this->model = $model; - return $this->view - ->tag('div', $this->_getForm(), [ - 'class' => 'form', - 'id' => 'facet'. $model->getId(), - 'style' => 'width:600px;margin-left:20px;' - . ((!$display) ? 'display:none;': '')]); - } - - - protected function _getForm() { - return $this->view - ->tag('form', $this->_getFields(), [ - 'method' => 'post', - 'action' => $this->view->url([ - 'module' => 'cosmo', - 'controller' => 'facets', - 'action' => 'validate', - 'id' => $this->model->getId()], null, true)]); - } - - - protected function _getFields() { - return $this->view - ->tag( - 'table', - $this->_getTitle() - . $this->_helpCode() - . $this->_getCode() - . $this->_getLabel() - . $this->_getHelp() - . $this->_getRules() - . $this->_getDisplay() - . $this->_getActions(), - ['class' => 'form', 'cellspacing' => 0, 'cellpadding' => 5]); - } - - - protected function _getTitle() { - return $this->view->tag('tr', $this->view->tag('th', 'Création de facettes dynamiques', [ - 'class' => 'form', 'colspan' => 2, 'align' => 'left' - ])); - } - - - protected function _getLabel() { - return $this->view->tag( - 'tr', - $this->view->tag('td', 'Libellé', [ - 'class' => 'form_first', 'align' => 'right', 'width' => '35%']) . - $this->view->tag('td', $this->view->formText('libelle_facette', $this->model->getLibelleFacette(), ['size' => 43]), ['class' => 'form_first'])); - } - - - protected function _helpCode() { - return '<tr> - <td class="form_first" align="center" colspan="2"> - <div class="commentaire">Critère de recherche: rech_H'. - $this->model->getCode().'</div> - </td> - </tr>'; - } - - - protected function _getCode() { - return - $this->view->tag( - 'tr', - $this->view->tag('td', 'Code', [ - 'class' => 'form_first', 'align' => 'right', 'width' => '35%']) . - $this->view->tag('td', $this->view->formText('code', $this->model->getCode(), ['size' => 43, 'disabled' => 'disabled']), ['class' => 'form_first'])); - } - - - protected function _getHelp() { - return '<tr> - <td class="form_first" align="center" colspan="2"> - <div class="commentaire">Syntaxe : zone$champ</div> - </td> - </tr>'; - } - - - protected function _getRules() { - return $this->_getSimpleInput( - 'Règles de reconnaissance', - $this->view->formTextarea('rules', $this->model->getRulesLabel(), [ - 'cols' => 40, 'rows' => 5]) - ); - } - - - protected function _getDisplay() { - return ''; - } - - protected function _getActions() { - return $this->view->tag('tr', - $this->view->tag( - 'th', - $this->view->formSubmit('facetsSubmit', 'Valider', ['class' => 'bouton']) . - ($this->model->getId() ? str_repeat(' ', 5) . - $this->view->cosmoButton( - 'Supprimer', - $this->view->url([ - 'module' => 'cosmo', - 'controller' => 'facets', - 'action' => 'delete', - 'id' => $this->model->getId()], null, true), - 'Voulez-vous vraiment supprimer cet facets ?') : ''), - ['class' => 'form', 'align' => 'center', 'colspan' => 2] - ) - ); - } -} diff --git a/library/ZendAfi/View/Helper/FormEmail.php b/library/ZendAfi/View/Helper/FormEmail.php index de826f8331572aeb4ef436dc4cc3a0db68b7a800..dbb06cfc47b5ce90cd065ce7ce821918eac63f6a 100644 --- a/library/ZendAfi/View/Helper/FormEmail.php +++ b/library/ZendAfi/View/Helper/FormEmail.php @@ -19,21 +19,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -class ZendAfi_View_Helper_FormEmail extends Zend_View_Helper_FormText { +class ZendAfi_View_Helper_FormEmail extends ZendAfi_View_Helper_FormHTML5 { public function formEmail($name, $value = null, $attribs = null) { - $info = $this->_getInfo($name, $value, $attribs); - extract($info); - $disabled = []; - if ($disable) - $disabled ['disabled'] = 'disabled'; + return $this->renderElement($name, $value, $attribs); + } + - return $this->view->tag('input', - null, - array_merge(['type' => 'email', - 'name' => $this->view->escape($name), - 'id' => $this->view->escape($id), - 'value' => $value], - $attribs, - $disabled)); + public function inputType() { + return 'email'; } } \ No newline at end of file diff --git a/library/ZendAfi/View/Helper/FormHTML5.php b/library/ZendAfi/View/Helper/FormHTML5.php new file mode 100644 index 0000000000000000000000000000000000000000..864187dde9f46c589f3d682a5feab2bb06556db3 --- /dev/null +++ b/library/ZendAfi/View/Helper/FormHTML5.php @@ -0,0 +1,42 @@ +<?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 + */ + +abstract class ZendAfi_View_Helper_FormHTML5 extends Zend_View_Helper_FormText { + public abstract function inputType(); + + + public function renderElement($name, $value = null, $attribs = null) { + $info = $this->_getInfo($name, $value, $attribs); + extract($info); + $disabled = []; + if ($disable) + $disabled ['disabled'] = 'disabled'; + + return $this->view->tag('input', + null, + array_merge(['type' => $this->inputType(), + 'name' => $this->view->escape($name), + 'id' => $this->view->escape($id), + 'value' => $value], + $attribs, + $disabled)); + } +} \ No newline at end of file diff --git a/library/ZendAfi/View/Helper/FormNumber.php b/library/ZendAfi/View/Helper/FormNumber.php new file mode 100644 index 0000000000000000000000000000000000000000..4b276b968430571e1973882f636121663e1bed12 --- /dev/null +++ b/library/ZendAfi/View/Helper/FormNumber.php @@ -0,0 +1,31 @@ +<?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_View_Helper_FormNumber extends ZendAfi_View_Helper_FormHTML5 { + public function formNumber($name, $value = null, $attribs = null) { + return $this->renderElement($name, $value, $attribs); + } + + + public function inputType() { + return 'number'; + } +} \ No newline at end of file diff --git a/library/ZendAfi/View/Helper/FormUrl.php b/library/ZendAfi/View/Helper/FormUrl.php index ce8b7fa981ad6196d2bc23aa9fe781d1de7f5c9b..a9f7f678ff0c308b3c8a348dd996f1ddc3ecc46c 100644 --- a/library/ZendAfi/View/Helper/FormUrl.php +++ b/library/ZendAfi/View/Helper/FormUrl.php @@ -19,22 +19,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -class ZendAfi_View_Helper_FormUrl extends Zend_View_Helper_FormText { +class ZendAfi_View_Helper_FormUrl extends ZendAfi_View_Helper_FormHTML5 { public function formUrl($name, $value = null, $attribs = null) { - $info = $this->_getInfo($name, $value, $attribs); - extract($info); + return $this->renderElement($name, $value, $attribs); + } - $disabled = []; - if ($disable) - $disabled ['disabled'] = 'disabled'; - return $this->view->tag('input', - null, - array_merge(['type' => 'url', - 'name' => $this->view->escape($name), - 'id' => $this->view->escape($id), - 'value' => $value], - $attribs, - $disabled)); + public function inputType() { + return 'url'; } } \ No newline at end of file diff --git a/library/ZendAfi/View/Helper/LibraryOpenings.php b/library/ZendAfi/View/Helper/LibraryOpenings.php index b8a512e7be61be2484d04f45b725c33186d926de..93aeee6f3fe4f9096eb0ccbbf0d7a211c1f5404e 100644 --- a/library/ZendAfi/View/Helper/LibraryOpenings.php +++ b/library/ZendAfi/View/Helper/LibraryOpenings.php @@ -162,8 +162,11 @@ class ZendAfi_View_Helper_LibraryOpenings extends ZendAfi_View_Helper_BaseHelper $hours = $this->_renderTimes($am, $pm); - return $opening->getFormattedJour() - . ($hours ? (' : ' . str_replace('h00', 'h', $hours)) : ''); + return sprintf('%s : %s', + $opening->getFormattedJour(), + $hours + ? str_replace('h00', 'h', $hours) + : $this->_('fermé')); } diff --git a/library/digital_resources/DiMusic/tests/DiMusicTest.php b/library/digital_resources/DiMusic/tests/DiMusicTest.php index 20301543a77147f669fdd88b34874f4b73530b49..d570649f4fad546fa1e885ff9c3ca4a2fcfb25e9 100644 --- a/library/digital_resources/DiMusic/tests/DiMusicTest.php +++ b/library/digital_resources/DiMusic/tests/DiMusicTest.php @@ -525,7 +525,7 @@ abstract class DiMusicRechercheControllerTestCase extends AbstractControllerTest public function setUp() { parent::setUp(); - + Class_AdminVar::set('AUTHOR_PAGE', 0); $this->_prepareFixtures(); $bridges = $this->fixture('Class_Album', diff --git a/library/startup.php b/library/startup.php index 9b46cd86a71e8f1f9654c58934421fa029d89be8..71f92d9220716af6c79d33e2e4a41260a3212b12 100644 --- a/library/startup.php +++ b/library/startup.php @@ -81,7 +81,7 @@ class Bokeh_Engine { function setupConstants() { defineConstant('BOKEH_MAJOR_VERSION','7.12'); - defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.53'); + defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.56'); defineConstant('BOKEH_REMOTE_FILES', 'http://git.afi-sa.fr/afi/opacce/'); @@ -312,7 +312,6 @@ class Bokeh_Engine { function setupFrontController() { $this->_front_controller = $this ->newFrontController() - ->addControllerDirectory(ROOT_PATH.'afi/application/modules/opacpriv/controllers','opacpriv') ->setBaseURL(BASE_URL); $this->setupRoutes($this->_front_controller, $this->_config); diff --git a/public/admin/js/multi_inputs/multi_inputs.js b/public/admin/js/multi_inputs/multi_inputs.js index a923f2844076cb64e6b6ef0217c4c5539e248a7f..c2baaaec07c372bbe7a83cde6ed319a569be8f5e 100644 --- a/public/admin/js/multi_inputs/multi_inputs.js +++ b/public/admin/js/multi_inputs/multi_inputs.js @@ -62,12 +62,12 @@ for (var key in options.fields) { var input = options.fields[key]; var value = (null != value_index && value_index < options.values[input.name].length) ? - options.values[input.name][value_index] : ''; + options.values[input.name][value_index] : ''; var desc = (null != value_index - && null != options.descs - && input.name in options.descs - && value_index < options.descs[input.name].length) ? - options.descs[input.name][value_index] : ''; + && null != options.descs + && input.name in options.descs + && value_index < options.descs[input.name].length) ? + options.descs[input.name][value_index] : ''; var html = input.type == 'select' ? '<select></select>' : '<input type="text" />'; var node = $(html).attr('name', input.name + '[]'); @@ -76,12 +76,12 @@ if (input.options) { for (var option_value in input.options) { - if (typeof input.options[option_value] === 'string') { + if (typeof input.options[option_value] === 'string') { var option = $('<option value="' + option_value + '">' + input.options[option_value] + '</option>'); if (option_value == value) option.attr('selected', 'selected'); node.append(option); - } else { + } else { var optgroup = $('<optgroup label="' + option_value + '"></optgroup>'); var optgroup_options = input.options[option_value]; for (var optgroup_value in optgroup_options) { @@ -91,20 +91,20 @@ optgroup.append(optgroup_option) } node.append(optgroup); - } + } } } - + for (var attrib_name in input.attribs) if (input.attribs.hasOwnProperty(attrib_name)) - node.attr(attrib_name,input.attribs[attrib_name]); + node.attr(attrib_name,input.attribs[attrib_name]); inputs[inputs.length] = $('<div/>').append( node ).append(desc).html(); } var inputs_str = '<tr><td style="vertical-align:top;">' - + inputs.join('</td><td style="vertical-align:top;">') - + '</td><td data-type="actions"></td></tr>'; + + inputs.join('</td><td style="vertical-align:top;">') + + '</td><td data-type="actions"></td></tr>'; var tbody = $(table).find('tbody'); tbody.append(inputs_str); if (null != value_index && options.line_errors && options.line_errors[value_index]) @@ -129,16 +129,16 @@ var source_img = $(this); $('<div>Etes vous sur de vouloir supprimer ' + current.options.delete_message + ' ?</div>') .dialog({ - title:'Attention', - closeOnEscape:true, - modal:true, - buttons:{'Annuler':function(){$(this).dialog('close')}, + title:'Attention', + closeOnEscape:true, + modal:true, + buttons:{'Annuler':function(){$(this).dialog('close')}, 'Supprimer':function(){ source_img.parent().parent().remove(); current.refresh(); $(this).dialog('close') }} - }); + }); }); }, @@ -164,7 +164,7 @@ var input = options.fields[key]; if (input.source) { $(table).find('input[name="' + input.name + '[]"]').each(function() { - $(this).autocomplete({source: input.source}); + $(this).autocomplete({source: input.source}); }); } } diff --git a/scripts/emacs/yasnippet/snippets/text-mode/php-mode/class b/scripts/emacs/yasnippet/snippets/text-mode/php-mode/class index 31100f1fc8fa502c88b5a636c4ba9514397ff4b2..121bc84ab8a099add59df20fc44f5ea189bcb539 100644 --- a/scripts/emacs/yasnippet/snippets/text-mode/php-mode/class +++ b/scripts/emacs/yasnippet/snippets/text-mode/php-mode/class @@ -3,7 +3,7 @@ # -- <?php /** - * Copyright (c) 2012-2018, Agence Française Informatique (AFI). All rights reserved. + * Copyright (c) 2012-2019, 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 @@ -28,4 +28,3 @@ class ${class_name} { $0 } } -?> \ No newline at end of file diff --git a/scripts/reindex_local_authorities.php b/scripts/reindex_local_authorities.php new file mode 100644 index 0000000000000000000000000000000000000000..838505f1f2990e03e6007b6136c4690e079fd69c --- /dev/null +++ b/scripts/reindex_local_authorities.php @@ -0,0 +1,115 @@ +<?php +error_reporting(E_ERROR | E_PARSE); +require(__DIR__.'/../console.php'); + + +echo "\n\nWelcome to the iReindex Authorities 3000 PRO tool by @patbator\n\n"; + +$int_bib = null; + +while(!$int_bib) { + $id_int_bib = (int)readline('Please tell me the id_int_bib : '); + echo ($int_bib = Class_IntBib::find($id_int_bib)) + ? ("Authorities generated by bibliographic links will be linked to : " . $int_bib->getNomCourt() . "\n\n") + : "IntBib not found try again \n\n"; +} + +echo "\n\n==== AUTHORITIES ====\n\n"; + +class Scripts_Local_Authorities_Indexer { + protected + $_index_systems = [], + $_authority_facets; + + + public function __construct() { + $this->_authority_facets = new Class_Cosmogramme_Integration_Record_AuthorityFacets(); + } + + + public function index($record) { + echo '.'; + $index_systems = $this->_indexSystemsFor($record); + $facets = $this->_authority_facets->getFacets($record->getNoticeUnimarc(), + function() { return; }, + $index_systems); + $record->setFacettes($facets); + $record->save(); + } + + + protected function _indexSystemsFor($record) { + if (!$item = $record->getFirstExemplaire()) + return []; + + if (!$bib = $item->getIntBib()) + return []; + + if (isset($this->_index_systems[$bib->getId()])) + return $this->_index_systems[$bib->getId()]; + + if (!$autos = $bib->getIntMajAutos()) + return []; + + foreach($autos as $auto) + if ($auto->getProfilDonnees()->isAuthorityRecords()) { + $prefs = $auto->getProfilDonnees()->getIndexSystemsPrefs(); + $index_systems = Class_Notice_AuthorityIndexSystem::collectionFromPrefs($prefs); + return $this->_index_systems[$bib->getId()] = $index_systems; + } + + return []; + } +} + + +$indexer = new Scripts_Local_Authorities_Indexer(); +$page = 1; +while ($records = Class_Notice::findAllBy(['type' => Class_Notice::TYPE_AUTHORITY, + 'limitPage' => [$page, 1000]])) { + echo "\npage: $page\n"; + $page ++; + array_map([$indexer, 'index'], $records); + + Storm_Model_Abstract::unsetLoaders(); + Storm_Model_Loader::resetCache(); + gc_collect_cycles(); +} + +echo "\n\n==== BIBLIOS ====\n\n"; + +class Scripts_Local_Biblios_Indexer { + protected $_dynamic_facets, $_int_bib; + + + public function __construct($int_bib) { + $this->_int_bib = $int_bib; + $this->_dynamic_facets = new Class_Cosmogramme_Integration_Record_BibliographicDynamicFacets(); + } + + + public function index($record) { + echo '.'; + $thesauri = $this->_dynamic_facets->thesauriOf($record, $this->_int_bib); + $record->updateFacette(implode(' ', array_map(function($item) { return $item->getFacetCode(); }, + array_filter($thesauri)))) + ->save(); + } +} + + +$indexer = new Scripts_Local_Biblios_Indexer($int_bib); +$page = 1; +while ($records = Class_Notice::findAllBy(['type' => Class_Notice::TYPE_BIBLIOGRAPHIC, + 'limitPage' => [$page, 1000]])) { + echo "\npage: $page\n"; + $page ++; + array_map([$indexer, 'index'], $records); + + Storm_Model_Abstract::unsetLoaders(); + Storm_Model_Loader::resetCache(); + gc_collect_cycles(); +} + + +echo "\n\nDONE !!!!\n\n"; \ No newline at end of file diff --git a/tests/TestSpeedTrap.php b/tests/TestSpeedTrap.php index 87cf90ab2e94afb35646939a550ace8ec27a2e2a..c63d369842d59e5c96513fd8291710c9f9b41361 100644 --- a/tests/TestSpeedTrap.php +++ b/tests/TestSpeedTrap.php @@ -23,11 +23,16 @@ * @package Tests */ class TestSpeedTrap extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener { - protected static $_speed_trapped_test = [], - $_speed_limit = 0.01; + protected static + $_speed_trapped_test = [], + $_speed_limit = 0.01, + $_should_print = false; public static function printSpeedTrappedTests() { + if (!static::$_should_print) + return; + self::sortTrapped(); self::renderScore(); } @@ -39,6 +44,7 @@ class TestSpeedTrap extends PHPUnit_Util_Printer implements PHPUnit_Framework_Te */ public function endTest(PHPUnit_Framework_Test $test, $length) { + static::$_should_print = true; if ($length > self::$_speed_limit) $this->collect(get_class($test) . '::' . $test->getName(), round($length, 4)); } diff --git a/tests/application/modules/admin/controllers/AdminAbstractControllerTestCase.php b/tests/application/modules/admin/controllers/AdminAbstractControllerTestCase.php index f30bfe8617bfc4b218b409ad68b3b7c803672296..64ef5ff067d3e0d9b1d54f1d9549c91d37b9c62c 100644 --- a/tests/application/modules/admin/controllers/AdminAbstractControllerTestCase.php +++ b/tests/application/modules/admin/controllers/AdminAbstractControllerTestCase.php @@ -31,5 +31,10 @@ abstract class Admin_AbstractControllerTestCase extends AbstractControllerTestCa $account->LOGIN = "sysadmin"; $account->PSEUDO = "admin"; } + + + public function tearDown() { + ZendAfi_View_Helper_Admin_MenuGaucheAdminItem::setAcl(null); + parent::tearDown(); + } } -?> \ No newline at end of file diff --git a/tests/application/modules/admin/controllers/AdminIndexControllerTest.php b/tests/application/modules/admin/controllers/AdminIndexControllerTest.php index 074e4fc7a78377d0bf41d5700efbb73081f2cf6a..23a09001d62c1aee5155d067e86873f255bd1454 100644 --- a/tests/application/modules/admin/controllers/AdminIndexControllerTest.php +++ b/tests/application/modules/admin/controllers/AdminIndexControllerTest.php @@ -81,12 +81,6 @@ class AdminIndexControllerIndexActionTest extends AdminIndexControllerTestCase { public function menuGaucheShouldContainsCustomFields() { $this->assertXPathContentContains('//li//a','Champs personnalisés'); } - - - /** @test */ - public function menuGaucheShouldContainsCustomFieldReport() { - $this->assertXPathContentContains('//li//a','Rapports statistiques'); - } } @@ -161,7 +155,7 @@ class AdminIndexControllerAdminVarActionTest extends Admin_AbstractControllerTes /** @test */ public function bibnumShouldDisplayDelImageAndDisabledLabel() { - $base_xpath = '//table[@id="adminvars"]//a[contains(text(), "BIBNUM")]/ancestor::tr[1]/td[2]'; + $base_xpath = '//table[@id="adminvars"]//sub[contains(text(), "BIBNUM")]/ancestor::tr[1]/td[2]'; $this->assertXPath($base_xpath . '/img[contains(@src, "unpublish_16.png")]'); $this->assertXPathContentContains($base_xpath, 'Désactivé'); } @@ -169,7 +163,7 @@ class AdminIndexControllerAdminVarActionTest extends Admin_AbstractControllerTes /** @test */ public function cacheActifShouldDisplayCocheVerteImageAndEnabledLabel() { - $base_xpath = '//table[@id="adminvars"]//a[contains(text(), "CACHE_ACTIF")]/ancestor::tr[1]/td[2]'; + $base_xpath = '//table[@id="adminvars"]//sub[contains(text(), "CACHE ACTIF")]/ancestor::tr[1]/td[2]'; $this->assertXPathContentContains($base_xpath, 'Activé'); $this->assertXPath($base_xpath . '/img[contains(@src, "publish_16.png")]'); } diff --git a/tests/application/modules/admin/controllers/AlbumControllerTest.php b/tests/application/modules/admin/controllers/AlbumControllerTest.php index 64821a20b22be6dcece4adb20178b04e35f8a1a1..c31ce32943db5f891790aa1e3f426f44b125e6bd 100644 --- a/tests/application/modules/admin/controllers/AlbumControllerTest.php +++ b/tests/application/modules/admin/controllers/AlbumControllerTest.php @@ -42,9 +42,9 @@ abstract class Admin_AlbumControllerTestCase extends Admin_AbstractControllerTes $fre = $langue_loader->newInstanceWithId('fre')->setLibelle('français'); $dak = $langue_loader->newInstanceWithId('dak')->setLibelle('dakota'); - Storm_Test_ObjectWrapper::onLoaderOfModel('Class_CodifLangue') - ->whenCalled('findAllBy') - ->answers(array($cus, $fre, $dak)); + $this->onLoaderOfModel('Class_CodifLangue') + ->whenCalled('findAllBy') + ->answers([$cus, $fre, $dak]); $favoris = $this->fixture('Class_AlbumCategorie', ['id' => 2]) ->setParentId(0) @@ -2646,6 +2646,9 @@ class Admin_AlbumControllerPreviewAlbumBibleSouvignyPostTest extends Admin_Album class Admin_AlbumControllerImportEADTest extends Admin_AlbumControllerTestCase { public function setUp() { parent::setUp(); + + Class_AdminVar::set('IMPORT_EAD', 1); + $this->dispatch('/admin/album/import_ead'); } diff --git a/tests/application/modules/admin/controllers/BibControllerTest.php b/tests/application/modules/admin/controllers/BibControllerTest.php index 3f841e5880d0cc4bc164d14dff167d5d2a7b057d..6b9154cd2da76d247fa98302ea08c39484b22187 100644 --- a/tests/application/modules/admin/controllers/BibControllerTest.php +++ b/tests/application/modules/admin/controllers/BibControllerTest.php @@ -1217,8 +1217,6 @@ class BibControllerLocalisationNewTest extends BibControllerTestCase { public function libelleShouldBeNouvelleLocalisation(){ $this->assertXPath('//input[@id="libelle"][@value="** nouvelle localisation **"]'); } - - } @@ -1266,6 +1264,43 @@ class BibControllerLocalisationNewPostTest extends BibControllerTestCase { +class BibControllerLocalisationsAnnecyListTest extends BibControllerTestCase { + public function setUp() { + parent::setUp(); + + $this->fixture('Class_Localisation', + ['id' => 9, + 'libelle' => 'Arts', + 'description' => 'Coin des arts.', + 'bib' => $this->bib_annecy, + 'image' => 'bib_2_localisation_9.jpg']); + + $this->dispatch('admin/bib/localisations/id_bib/2'); + + } + + + /** @test */ + public function titleShouldBeLocalisations() { + $this->assertXPathContentContains('//h1', 'Localisations de la bibliothèque: Annecy'); + } + + + /** @test */ + public function tdShouldListLocalisationArts() { + $this->assertXPathContentContains('//td', 'Arts'); + } + + + /** @test */ + public function pageShouldContainsLinkToEditLibrary2() { + $this->assertXPath('//div[@class="actions"]//a[contains(@href, "/admin/bib/edit/id/2")]'); + } +} + + + + class BibControllerLocalisatonDeleteTest extends BibControllerTestCase { public function setUp() { parent::setUp(); @@ -1390,10 +1425,17 @@ class BibControllerPlanMajTest extends BibControllerTestCase { $this->assertXPath('//img[contains(@src,"plans/bib_3_plan_3.png")]',$this->_response->getBody()); } + + /** @test */ + public function forCranPageShouldContainsLinkToEditIdBibThree() { + $this->dispatch('admin/bib/plans/id_bib/3'); + $this->assertXPath('//div[@class="actions"]//a[contains(@href, "/admin/bib/edit/id/3")]'); + } } + class BibControllerPostMajPlanTest extends BibControllerTestCase { public function setUp() { parent::setUp(); diff --git a/tests/application/modules/admin/controllers/CustomFieldsReportControllerTest.php b/tests/application/modules/admin/controllers/CustomFieldsReportControllerTest.php index 5f0503bb5cdd721bc8ab80e8dd512f37c543a8ba..7f3e70280cfdb12904e909f26d9547672dc82837 100644 --- a/tests/application/modules/admin/controllers/CustomFieldsReportControllerTest.php +++ b/tests/application/modules/admin/controllers/CustomFieldsReportControllerTest.php @@ -25,6 +25,7 @@ class CustomFieldsReportControllerAddTest extends AbstractControllerTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('CUSTOM_FIELDS_REPORT', 1); $this->dispatch('/admin/custom-fields-report/add', true); } @@ -67,6 +68,8 @@ class CustomFieldsReportControllerEditTest extends AbstractControllerTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('CUSTOM_FIELDS_REPORT', 1); + $this->fixture('Class_Report', [ 'id' => 2, 'label' => 'Report', @@ -90,6 +93,9 @@ class CustomFieldsReportControllerGenerateTest extends AbstractControllerTestCas public function setUp() { parent::setUp(); + + Class_AdminVar::set('CUSTOM_FIELDS_REPORT', 1); + $this->fixture('Class_Report', [ 'id' => 42, 'label' => '', @@ -108,5 +114,4 @@ class CustomFieldsReportControllerGenerateTest extends AbstractControllerTestCas public function customFieldsJsShouldBePresent() { $this->assertXPath('//script[contains(@src, "custom-fields/custom_fields.js")]'); } -} -?> \ No newline at end of file +} \ No newline at end of file diff --git a/tests/application/modules/admin/controllers/IndexControllerTest.php b/tests/application/modules/admin/controllers/IndexControllerTest.php index 895333b89180b95b7d909f6023be3b3dd656efed..7c6174595a53ad1673b9d864c6767ed00784518f 100644 --- a/tests/application/modules/admin/controllers/IndexControllerTest.php +++ b/tests/application/modules/admin/controllers/IndexControllerTest.php @@ -441,6 +441,18 @@ class Admin_IndexControllerAdminvarActionTest extends Admin_AbstractControllerTe public function varNewsletterUnsubscribeTextShouldBeLienPourSeDesinscrire() { $this->assertXPathContentContains('//tr[@data-adminvar="NEWSLETTER_UNSUBSCRIBE_TEXT"]//td', 'Lien pour se '); } + + + /** @test */ + public function varBibnumShouldBePublique() { + $this->assertXPathContentContains('//tr[@data-adminvar="BIBNUM"]//td', 'Publique'); + } + + + /** @test */ + public function varAllowedDiskSpaceShouldBePrivate() { + $this->assertXPathContentContains('//tr[@data-adminvar="ALLOWED_DISK_SPACE"]//td', 'Privée'); + } } diff --git a/tests/application/modules/admin/controllers/NewsletterControllerTest.php b/tests/application/modules/admin/controllers/NewsletterControllerTest.php index d5ec95319d7f3aca96e914cc4773964aece9b7d2..88a47098fedfc4236162ce123216eab52e5abaa4 100644 --- a/tests/application/modules/admin/controllers/NewsletterControllerTest.php +++ b/tests/application/modules/admin/controllers/NewsletterControllerTest.php @@ -67,7 +67,7 @@ class Admin_NewsletterControllerConfigActionTest extends Admin_NewsletterControl /** @test */ public function newsletterUnsubscribeVarShouldBeDisplayed() { - $this->assertXPathContentContains('//tr//td[1]','NEWSLETTER_UNSUBSCRIBE_TEXT'); + $this->assertXPathContentContains('//tr//td[1]','NEWSLETTER UNSUBSCRIBE TEXT'); } @@ -316,6 +316,7 @@ class Admin_NewsletterControllerEditActionTest extends Admin_NewsletterControlle 'titre' => 'Nouveautés', 'contenu'=>'Notre sélection du mois', 'expediteur' => 'laurent@free.fr', + 'articles_ids' => '6-42', 'user_groups' => [Class_UserGroup::find(14), Class_UserGroup::find(15)]]); @@ -359,6 +360,19 @@ class Admin_NewsletterControllerEditActionTest extends Admin_NewsletterControlle public function testSubmitButton() { $this->assertXPath("//div//button[contains(@onclick,\"submit()\")]"); } + + + /** @test */ + public function articlesTabShouldBePresent() { + $this->assertXPathContentContains('//form//fieldset//legend', 'Articles'); + } + + + /** @test */ + public function articleSelectionFieldsShouldBePresent() { + $this->assertXPath('//form//input[@name="articles_ids"][@value="6-42"]'); + $this->assertXPath('//form//input[@name="articles_categories_ids"][@value=""]'); + } } @@ -374,7 +388,9 @@ class Admin_NewsletterControllerAddActionPostTest extends Admin_NewsletterContro 'contenu' => 'Plein les yeux', 'id_catalogue' => '', 'id_panier' => '', - 'nb_notices' => 2]; + 'nb_notices' => 2, + 'articles_ids' => '6-42', + 'articles_categories_ids' => '3-4']; $this->postDispatch('/admin/newsletter/add', $data); $this->_new = Class_Newsletter::findFirstBy(['titre' => 'Fêtes du lac']); @@ -404,6 +420,17 @@ class Admin_NewsletterControllerAddActionPostTest extends Admin_NewsletterContro $this->assertEquals('Groupe manuel pour la lettre "Fêtes du lac"', $this->_new->getDedicatedGroup()->getLibelle()); } + + + /** @test */ + public function articlesIdsShouldBe6_42() { + $this->assertEquals('6-42', $this->_new->getArticlesIds()); + } + + /** @test */ + public function articlesCategoriesIdsShouldBe3And4() { + $this->assertEquals('3-4', $this->_new->getArticlesCategoriesIds()); + } } @@ -837,6 +864,27 @@ class Admin_NewsletterControllerPreviewActionTest extends Admin_NewsletterContro 'libelle' => 'Mon catalogue', 'type_doc' => 5]); + $septante_millions = $this->fixture('Class_Article', + ['id' => 35, + 'titre' => '70 millions …', + 'contenu' => 'Ils sont 70 millions prêts à prendre sa place.']); + + $le_roi_des_cons = $this->fixture('Class_Article', + ['id' => 36, + 'titre' => 'Le Roi des cons', + 'contenu' => 'Il est beau, il est fier sur son throne.']); + + $l_arnaque = $this->fixture('Class_Article', + ['id' => 12, + 'titre' => 'L\'arnaque', + 'contenu' => 'La révolution a oublié de décapiter la misère et l\'exploitation.']); + + $this->fixture('Class_ArticleCategorie', + ['id' => 89, + 'libelle' => 'La France', + 'articles' => [$le_roi_des_cons, + $septante_millions]]); + $nouveautes = $this->fixture('Class_Newsletter', ['id' => 3, 'titre' => 'Nouveautés', @@ -844,6 +892,8 @@ class Admin_NewsletterControllerPreviewActionTest extends Admin_NewsletterContro 'id_catalogue' => 1, 'nb_notices' => 0, 'id_panier' => null, + 'articles_categories_ids' => '89-99', + 'articles_ids' => '12', 'last_distribution_date' => '2012-03-02']); @@ -854,18 +904,22 @@ class Admin_NewsletterControllerPreviewActionTest extends Admin_NewsletterContro $this->dispatch('/admin/newsletter/preview/id/3', true); } + public function testFrom() { $this->assertQueryContentContains('p', 'laurent@afi-sa.net'); } + public function testSubject() { $this->assertQueryContentContains('p', 'Nouveautés'); } + public function testBodyText() { $this->assertQueryContentContains('p', 'Notre sélection du mois Hoho'); } + public function testBodyHtml() { $this->assertXPath('//div//img[@src="zork.jpg"]', $this->_response->getBody()); } @@ -876,16 +930,29 @@ class Admin_NewsletterControllerPreviewActionTest extends Admin_NewsletterContro $this->assertQueryContentContains('p', 'Martine à la plage', $this->_response->getBody()); } + /** @test */ public function noticeMartineALaPlageUrlShouldBeRechercheViewNotice42() { $this->assertXPath('//a[@href="' . Class_Url::absolute('/recherche/viewnotice/id/42') . '"]'); } + /** @test */ public function templateShouldNotCreateNewsletterDispatch() { $this->assertEmpty(Class_Newsletter_Dispatch::findAll()); } + + /** @test */ + public function leRoiDesConsShouldBeDisplay() { + $this->assertXpath('//div', 'Le Roi des cons', $this->_response->getBody()); + } + + + /** @test */ + public function lArnaqueShouldBeDisplay() { + $this->assertXpath('//div', 'L\'arnaque', $this->_response->getBody()); + } } diff --git a/tests/application/modules/admin/controllers/OaiControllerTest.php b/tests/application/modules/admin/controllers/OaiControllerTest.php index bce98625543a380761d7f0b967338f8639bbfac0..817488322b86ef884991501c5aad07852ca4e115 100644 --- a/tests/application/modules/admin/controllers/OaiControllerTest.php +++ b/tests/application/modules/admin/controllers/OaiControllerTest.php @@ -48,6 +48,9 @@ abstract class Admin_OaiControllerTestCase extends Admin_AbstractControllerTestC class Admin_OaiControllerIndexActionTest extends Admin_OaiControllerTestCase { public function setUp() { parent::setUp(); + + Class_AdminVar::set('OAI_REPOSITORY', 1); + $this->dispatch('/admin/oai'); } @@ -91,6 +94,7 @@ class Admin_OaiControllerIndexActionTest extends Admin_OaiControllerTestCase { class Admin_OaiControllerAddActionTest extends Admin_OaiControllerTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('OAI_REPOSITORY', 1); $this->dispatch('/admin/oai/add'); } @@ -107,6 +111,7 @@ class Admin_OaiControllerAddActionTest extends Admin_OaiControllerTestCase { class Admin_OaiControllerEditActionTest extends Admin_OaiControllerTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('OAI_REPOSITORY', 1); $this->dispatch('/admin/oai/edit/id/4'); } @@ -123,6 +128,7 @@ class Admin_OaiControllerEditActionTest extends Admin_OaiControllerTestCase { class Admin_OaiControllerBrowseGallicaActionTest extends Admin_OaiControllerTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('OAI_REPOSITORY', 1); $web_client = Storm_Test_ObjectWrapper::mock(); Class_WebService_OAI::setDefaultHttpClient($web_client); @@ -155,6 +161,9 @@ class Admin_OaiControllerImportIsaacAsimovFoundationTest extends Admin_OaiContro public function setUp() { parent::setUp(); + + Class_AdminVar::set('OAI_REPOSITORY', 1); + $foundation = Class_NoticeOAI::getLoader() ->newInstanceWithId(23) ->setData(serialize(array('titre' => 'Prelude to foundation', @@ -227,6 +236,7 @@ class Admin_OaiControllerImportIsaacAsimovFoundationTest extends Admin_OaiContro class Admin_OaiControllerSearchAsimovActionTest extends Admin_OaiControllerTestCase { /** @test */ public function pageShouldRedirectToOaiIndexWithExpressionRecherche() { + Class_AdminVar::set('OAI_REPOSITORY', 1); $this->dispatch('/admin/oai/search?expression=asimov', true); $this->assertRedirectTo('/admin/oai/index/expression/asimov'); } @@ -238,6 +248,7 @@ class Admin_OaiControllerSearchAsimovActionTest extends Admin_OaiControllerTestC abstract class Admin_OaiControllerSearchActionTestCase extends Admin_OaiControllerTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('OAI_REPOSITORY', 1); $this->mock_sql = Storm_Test_ObjectWrapper::on(Zend_Registry::get('sql')); Zend_Registry::set('sql', $this->mock_sql); } @@ -307,8 +318,4 @@ class Admin_OaiControllerIndexSearchInsignifantWordActionTest extends Admin_OaiC public function pageShouldContainsPasAssezDeMotsSignifications() { $this->assertXPathContentContains('//div[@class="error"]', "Il n'y aucun mot assez significatif pour la recherche"); } -} - - - -?> \ No newline at end of file +} \ No newline at end of file diff --git a/tests/application/modules/admin/controllers/OpdsControllerTest.php b/tests/application/modules/admin/controllers/OpdsControllerTest.php index 1beb9a10de8ed051b57b2883e9ebaf99f53cccd5..a9f8579094ffc4f9f19599e33079374f5ffd1f46 100644 --- a/tests/application/modules/admin/controllers/OpdsControllerTest.php +++ b/tests/application/modules/admin/controllers/OpdsControllerTest.php @@ -24,6 +24,9 @@ abstract class Admin_OpdsControllerTestCase extends Admin_AbstractControllerTest public function setUp() { parent::setUp(); + + Class_AdminVar::set('OPDS', 1); + Storm_Test_ObjectWrapper::onLoaderOfModel('Class_OpdsCatalog') ->whenCalled('findAllBy') ->with(array('order' => 'libelle')) @@ -59,6 +62,7 @@ class Admin_OpdsControllerWithReferentActionTest extends Admin_AbstractControlle public function setUp() { parent::setUp(); + Class_AdminVar::set('OPDS', 1); Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Users') ->whenCalled('getIdentity') ->answers($user_referent=Class_Users::getLoader()->newInstanceWithId(2) @@ -945,5 +949,4 @@ class Admin_OpdsControllerBrowseFeedbooksTestCase extends Admin_OpdsControllerTe $album = Class_Album::getLoader()->getFirstAttributeForLastCallOn('save'); $this->assertEquals('In his extraordinary debut novel of psychological suspense, Thomas OCallaghan proves himself a worthy successor to Thomas Harris as he introduces one of the most compelling and terrifying serial killers since Hannibal Lecter in a book where every...', $album->getDescription()); } -} -?> \ No newline at end of file +} \ No newline at end of file diff --git a/tests/application/modules/admin/controllers/OuverturesControllerTest.php b/tests/application/modules/admin/controllers/OuverturesControllerTest.php index 92a7760a9128576c5978c01efe81bc3f5ad6f729..586250c07cc2488965324cae843299048ebd43cc 100644 --- a/tests/application/modules/admin/controllers/OuverturesControllerTest.php +++ b/tests/application/modules/admin/controllers/OuverturesControllerTest.php @@ -243,10 +243,17 @@ class OuverturesControllerIndexActionSiteCranTest extends OuverturesControllerTe public function shouldContainReposApresAnniversaireDeFrancine() { $this->assertXPathContentContains('//ul//li[6]//table//td', 'Repos après l\'anniversaire de francine'); } + + + /** @test */ + public function pageShouldContainsLinkToEditLibraryOne() { + $this->assertXPath('//div[@class="actions"]//a[contains(@href, "/admin/bib/edit/id/1")]'); + } } + class OuverturesControllerIndexActionSiteCranMultimediaEnabledTest extends OuverturesControllerTestCase { public function setUp() { parent::setUp(); diff --git a/tests/application/modules/admin/controllers/ProfilControllerTest.php b/tests/application/modules/admin/controllers/ProfilControllerTest.php index d4c6642b22b56fbacc43a8fe9844531c90751e23..6b201a6be244c71fb5cf96010c5c08e59586167d 100644 --- a/tests/application/modules/admin/controllers/ProfilControllerTest.php +++ b/tests/application/modules/admin/controllers/ProfilControllerTest.php @@ -1357,17 +1357,19 @@ class Admin_ProfilControllerNonExistingProfileTest extends Admin_AbstractControl class Admin_ProfilControllerGenresActionTest extends Admin_AbstractControllerTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('CUSTOM_GENRE_ICON', 1); + $this->dispatch('/admin/profil/genres'); } /** @test */ - function actionShouldBeGenres() { + public function actionShouldBeGenres() { $this->assertAction('genres'); } - } + class Admin_ProfilControllerEditMenuHorizontalTest extends Admin_AbstractControllerTestCase { public function setUp() { parent::setUp(); diff --git a/tests/application/modules/admin/controllers/RedmineControllerTest.php b/tests/application/modules/admin/controllers/RedmineControllerTest.php index 8fc8aab752b9f33ce46d06d934da9cbcde9c5f9c..7ede71a553c9743788ddf45c1c206a1c0194e803 100644 --- a/tests/application/modules/admin/controllers/RedmineControllerTest.php +++ b/tests/application/modules/admin/controllers/RedmineControllerTest.php @@ -305,8 +305,8 @@ class Admin_RedmineControllerIndexTest extends Admin_RedmineControllerWithApiTes /** @test */ - public function menuHorizontalShouldContainsOneIssueQuestionClient() { - $this->assertXPathContentContains('//div[contains(@class, "barre_nav")]//a[@title="Assistance"]//span[@class="menu_info"]', '1', $this->_response->getBody()); + public function menuHorizontalShouldContainsTwoIssues() { + $this->assertXPathContentContains('//div[contains(@class, "barre_nav")]//a[@title="Assistance"]//span[@class="menu_info"]', '2', $this->_response->getBody()); } } @@ -331,7 +331,7 @@ class Admin_RedmineControllerCacheTest extends Admin_RedmineControllerWithApiTes public function onAdminIndexMenuHorizontalShouldGetResultFromCache() { $this->dispatch('/admin/index/index'); - $this->assertXPathContentContains('//div[contains(@class, "barre_nav")]//a[@title="Assistance"]//span[@class="menu_info"]', '1'); + $this->assertXPathContentContains('//div[contains(@class, "barre_nav")]//a[@title="Assistance"]//span[@class="menu_info"]', '2'); } diff --git a/tests/application/modules/admin/controllers/ReferentPortailControllerTest.php b/tests/application/modules/admin/controllers/ReferentPortailControllerTest.php index 8df217220e728e80c0ca0f0aa9518aa79d270c76..c91cb8c5cdc770063b7aea7454528f8223122be8 100644 --- a/tests/application/modules/admin/controllers/ReferentPortailControllerTest.php +++ b/tests/application/modules/admin/controllers/ReferentPortailControllerTest.php @@ -1,4 +1,4 @@ -<?php +b<?php /** * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved. * @@ -16,12 +16,13 @@ * * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE * along with BOKEH; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ require_once 'AbstractControllerTestCase.php'; -abstract class ReferentPortailController_AbstractControllerTestCase extends AbstractControllerTestCase { - use Trait_UserGroupFixtures; +abstract class ReferentPortailControllerTestCase extends AbstractControllerTestCase { + use Trait_UserGroupFixtures; + protected function _initProfilHook($profil) { $profil->setLibelle('AFI'); } @@ -36,10 +37,10 @@ abstract class ReferentPortailController_AbstractControllerTestCase extends Abst public function setUp() { parent::setUp(); $user_referent=Class_Users::getLoader()->newInstanceWithId(777) - ->setLogin('referent') - ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL) - ->setPseudo('referent'); - + ->setLogin('referent') + ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL) + ->setPseudo('referent'); + $this->addUserToRightsReferent($user_referent); } @@ -47,39 +48,42 @@ abstract class ReferentPortailController_AbstractControllerTestCase extends Abst -class ReferentPortailControllerIndexActionTest extends ReferentPortailController_AbstractControllerTestCase { +class ReferentPortailControllerIndexActionTest extends ReferentPortailControllerTestCase { public function setUp() { parent::setUp(); - Class_AdminVar::getLoader()->newInstanceWithId('BIBNUM') - ->setValeur(1); + + Class_AdminVar::set('BIBNUM', 1); + Class_AdminVar::set('OPDS', 1); + $this->dispatch('/admin/index', true); } + /** @test */ function menuGaucheShouldContainsSitotheque() { $this->assertXPathContentContains('//li//a','Sitothèque',$this->_response->getBody()); } - /** @test */ + /** @test */ function menuGaucheShouldContainsDomaines() { $this->assertXPathContentContains('//li//a','Domaines',$this->_response->getBody()); } - /** @test */ + /** @test */ function menuGaucheShouldContainsModeration() { $this->assertXPathContentContains('//li//a','Modération',$this->_response->getBody()); } - /** @test */ + /** @test */ function menuGaucheShouldContainsDemandeDinscription() { $this->assertXPathContentContains('//li//a','Demandes d\'inscription',$this->_response->getBody()); } - /** @test */ + /** @test */ function menuGaucheShouldContainsCollections() { $this->assertXPathContentContains('//li//a','Collections',$this->_response->getBody()); } @@ -99,8 +103,4 @@ class ReferentPortailControllerIndexActionTest extends ReferentPortailController function menuGaucheShouldContainsUtilisateurs() { $this->assertXPathContentContains('//li//a','Utilisateurs',$this->_response->getBody()); } - - -} - -?> \ No newline at end of file +} \ No newline at end of file diff --git a/tests/application/modules/admin/controllers/SystemeControllerOpac2ImportTest.php b/tests/application/modules/admin/controllers/SystemeControllerOpac2ImportTest.php index ec4c1e924c4bb32f12886ad98192a5f7ef5fe6bf..43403ee7fe2104ef79558d8ed176654c0694b640 100644 --- a/tests/application/modules/admin/controllers/SystemeControllerOpac2ImportTest.php +++ b/tests/application/modules/admin/controllers/SystemeControllerOpac2ImportTest.php @@ -27,6 +27,8 @@ abstract class SystemeControllerOpac2ImportTestCase parent::setUp(); Storm_Model_Loader::defaultToVolatile(); + Class_AdminVar::set('IMPORT_AVIS_OPAC2', 1); + $this->fixture('Class_AdminVar', ['id' => 'AVIS_MAX_SAISIE', 'valeur' => '1000000']); diff --git a/tests/application/modules/admin/controllers/SystemeControllerWebServicesTest.php b/tests/application/modules/admin/controllers/SystemeControllerWebServicesTest.php index 1be3c1c221f959b5ac199a15d18bad4248a63c2f..0834aa3952b5512b591f6e38bb9521869a40787d 100644 --- a/tests/application/modules/admin/controllers/SystemeControllerWebServicesTest.php +++ b/tests/application/modules/admin/controllers/SystemeControllerWebServicesTest.php @@ -21,6 +21,9 @@ class SystemeControllerWebServicesIndexActionTest extends Admin_AbstractControllerTestCase { public function setUp() { parent::setUp(); + + Class_AdminVar::set('WEBSERVICE_TEST', 1); + $this->dispatch('admin/systeme/webservices'); } @@ -48,6 +51,7 @@ class SystemeControllerWebServicesActionTest extends Admin_AbstractControllerTes * @test */ public function webServiceFnacGetResumeShouldWork() { + Class_AdminVar::set('WEBSERVICE_TEST', 1); $this->dispatch('/admin/systeme/webservices/id_service/Fnac/id_fonction/1'); $this->assertXPathContentContains('//pre[@class="resultat"]', 'Un campus prestigieux figé sous la neige', @@ -62,11 +66,10 @@ class SystemeControllerWebServicesActionTest extends Admin_AbstractControllerTes * @test */ public function webServicePremiereGetResumeShouldWork() { + Class_AdminVar::set('WEBSERVICE_TEST', 1); $this->dispatch('/admin/systeme/webservices/id_service/Premiere/id_fonction/1', true); $this->assertXPathContentContains('//pre[@class="resultat"]', 'Jake Sully est un ancien marine', $this->_response->getBody()); } -} - -?> \ No newline at end of file +} \ No newline at end of file diff --git a/tests/application/modules/admin/controllers/UrlManagerControllerTest.php b/tests/application/modules/admin/controllers/UrlManagerControllerTest.php index cb0e132374fdf6406561ae4e3edbe2e4c84c36b8..eef5d11f77c8d0e7cea9b60fdee00b33d6c733b4 100644 --- a/tests/application/modules/admin/controllers/UrlManagerControllerTest.php +++ b/tests/application/modules/admin/controllers/UrlManagerControllerTest.php @@ -292,3 +292,27 @@ class UrlManagerControllerAsyncUpdateUrlInModelsActionTest extends UrlManagerTes $this->assertContains('https', Class_Article::find(78)->getContenu()); } } + + + + +class UrlManagerControllerIndexDispatchUrlWithPlusTest extends UrlManagerTestCase { + public function setUp() { + parent::setUp(); + + $this->fixture('Class_Article', + ['id' => 78, + 'titre' => 'Chien et chat', + 'description' => 'test de description : http://mon-domain.org', + 'contenu' => 'test: http://monurl.fr. http://mon-domain.org/recherche/pommo+d\'api']); + + $this->dispatch(sprintf('/admin/url-manager/index/term/%s', + urlencode('http://mon-domain.org/recherche/pommo+d\'api'))); + } + + + /** @test **/ + public function tableUrlShouldContainsMonDomainePregEscaped() { + $this->assertXPathContentContains('//table[@id="urls"]//td', 'http://mon-domain.org/recherche/pommo+d\'api'); + } +} \ No newline at end of file diff --git a/tests/application/modules/opac/controllers/AbonneControllerLoansHistoryNanookTest.php b/tests/application/modules/opac/controllers/AbonneControllerLoansHistoryNanookTest.php index c66ab627d62bcfbab33fa2b64e30b39ea4d48195..e445867f63aba0b44268ef3669a6cb981a794bdb 100644 --- a/tests/application/modules/opac/controllers/AbonneControllerLoansHistoryNanookTest.php +++ b/tests/application/modules/opac/controllers/AbonneControllerLoansHistoryNanookTest.php @@ -103,6 +103,7 @@ abstract class AbonneControllerLoansHistoryNanookTestCase extends AbstractContro class AbonneControllerLoansHistoryNanookIndexTest extends AbonneControllerLoansHistoryNanookTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('AUTHOR_PAGE', 0); $this->dispatch('/abonne/loans-history',true); } diff --git a/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php b/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php index 98cc8395e97584f3c7692aeedd134671d23793df..dc8b18f4cfa89b8d3fe1d153da00b44c8f025da7 100644 --- a/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php +++ b/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php @@ -276,6 +276,9 @@ class AbonneControllerPretsExportThreePretsTest extends AbonneControllerPretsLis class AbonneControllerPretsListThreePretsTest extends AbonneControllerPretsListThreePretsTestCase { public function setUp() { parent::setUp(); + + Class_AdminVar::set('AUTHOR_PAGE', 0); + $this->fixture('Class_CodifAuteur', ['id' => 565, 'libelle' => 'QUINROSE']); @@ -588,6 +591,7 @@ abstract class AbonneControllerPretsListReservationTestCase extends AbstractAbon class AbonneControllerPretsListReservationTest extends AbonneControllerPretsListReservationTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('AUTHOR_PAGE', 0); $this->dispatch('/opac/abonne/reservations', true); } @@ -635,7 +639,7 @@ class AbonneControllerPretsListReservationTest extends AbonneControllerPretsList } - /** @test */ + /** @test */ public function authorShouldBeRowlingAndLinkSearch() { $this->assertXPathContentContains('//tbody/tr[1]//td//a[@href="/recherche/simple/code_rebond/A456/retour_abonne/reservations"]', 'JOANNE KATHLEEN ROWLING', diff --git a/tests/application/modules/opac/controllers/AuthControllerLostPasswordTest.php b/tests/application/modules/opac/controllers/AuthControllerLostPasswordTest.php new file mode 100644 index 0000000000000000000000000000000000000000..481509f9164e32c1d101525e4a747694fbd4a4f8 --- /dev/null +++ b/tests/application/modules/opac/controllers/AuthControllerLostPasswordTest.php @@ -0,0 +1,398 @@ +<?php +/** + * Copyright (c) 2012-2019, 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 'Class/WebService/SIGB/Orphee/Service.php'; +require_once __DIR__ . '/../../../../fixtures/KohaFixtures.php'; + + +abstract class AuthControllerLostPasswordTestCase extends AbstractControllerTestCase { + protected + $_mail_transport, + $_storm_default_to_volatile = true; + + public function setUp() { + parent::setUp(); + + Zend_Mail::setDefaultTransport($this->_mail_transport = new MockMailTransport()); + + $cfg_accueil = ['modules' => [4 => ['division' => '4', + 'id_module' => 4, + 'type_module' => 'LOGIN', + 'preferences' => [ + 'identifiant' => 'Numéro de carte', + 'mot_de_passe'=> 'Année de naissance', + 'identifiant_exemple' => 'jj-mm-aaaa', + 'mot_de_passe_exemple' => '1983', + 'titre_connecte' => 'Vous êtes connecté(e)', + 'lien_connexion' => 'please, log me', + 'lien_mot_de_passe_oublie' => 'me rappelle plus', + 'pre_registration' => 'Se préinscrire', + 'profil_redirect' => 1, + 'profil_logout_redirect' => 0]]], + 'options' => []]; + + Class_Profil::getCurrentProfil() + ->setBrowser('opac') + ->setCfgAccueil(ZendAfi_Filters_Serialize::serialize($cfg_accueil)); + + ZendAfi_Auth::getInstance()->clearIdentity(); + } +} + + + + +class AuthControllerLostPasswordActionTest extends AuthControllerLostPasswordTestCase { + public function setUp() { + parent::setUp(); + $this->dispatch('/opac/auth/lostpass', true); + } + + + /** @test */ + public function formActionShouldBeLostPass() { + $this->assertXPath('//form[@id="form_lostpass"][contains(@action, "/auth/lostpass")]'); + } + + + /** @test */ + public function formShouldContainsInputForUsername() { + $this->assertXPath('//form[@id="form_lostpass"]//input[@type="text"][@name="lost_username"][@placeholder="jj-mm-aaaa"]', $this->_response->getBody()); + } + + + /** @test */ + public function formShouldContainsLabelNumeroDeCarteForInputForUsername() { + $this->assertXPathContentContains('//form[@id="form_lostpass"]//label[@for="lost_username"]', 'Numéro de carte'); + } + + + /** @test */ + public function pageShouldBeHTML5Valid() { + $this->assertHTML5(); + } +} + + + + +class AuthControllerLostPasswordValidPostTest extends AuthControllerLostPasswordTestCase { + protected $_mail_transport; + + public function setUp() { + parent::setUp(); + + $sigb = $this->fixture('Class_IntBib', + ['id' => 3, + 'comm_params' => ['url_serveur' => 'http://localhost', + 'restful' => '1'], + 'comm_sigb' => Class_IntBib::COM_KOHA + ]); + + $this->fixture('Class_Bib', ['id' => 3, + 'libelle' => 'Bibliothèque Georges Brassens', + 'int_bib' => $sigb]); + + $user = $this->fixture('Class_Users', + ['id' => 78, + 'login' => 'Chambelle', + 'password' => 'upw', + 'idabon' => '93658', + 'mail' => 'Chambelle@here.fr', + 'id_site' => 3, + 'int_bib' => $sigb]); + + $user->beAbonneSIGB()->assertSave(); + + $this->postDispatch('/opac/auth/lostpass', ['lost_username' => 'Chambelle']); + } + + + /** @test */ + public function mailShouldBeSent() { + $this->assertNotNull($this->_mail_transport->sent_mail); + } + + + /** @test */ + public function mailShouldContainsVousAvezFaitUneDemande() { + $this->assertContains('Vous avez fait une demande', + $this->_mail_transport->sent_mail->getBodyText(true)); + } +} + + + + +class AuthControllerLostPasswordUnknownPostTest extends AuthControllerLostPasswordTestCase { + /** @test */ + public function withUnknowUserShouldDisplayError() { + $this->postDispatch('/opac/auth/lostpass', ['lost_username' => 'unknown']); + $this->assertXPathContentContains('//div', + 'Identifiant inconnu', + $this->_response->getBody()); + } + + + /** @test */ + public function withEmptyUserShouldDisplayError() { + $this->postDispatch('/opac/auth/lostpass', ['lost_username' => '']); + $this->assertXPathContentContains('//div', + 'Une valeur est requise', + $this->_response->getBody()); + } +} + + + + +class AuthControllerLostPasswordNoMailPostTest extends AuthControllerLostPasswordTestCase { + public function setUp() { + parent::setUp(); + + $user = $this->fixture('Class_Users', + ['id' => 1, + 'pseudo' => 'luddite', + 'login' => 'luddite', + 'password' => 'notech', + 'nom' => 'Lu', + 'prenom' => 'Dites']); + + $this->postDispatch('/opac/auth/lostpass' , ['lost_username' => 'luddite']); + } + + + /** @test */ + public function withoutEmailShouldReturnErrorMessage() { + $this->assertXPathContentContains('//div', "Votre mail n'est pas renseigné dans votre compte lecteur. Merci de vous adresser à la bibliothèque pour récupérer votre mot de passe ou bien le remplacer par un nouveau."); + } +} + + + + +class AuthControllerLostPasswordIncompatibleSigbMessageTest extends AuthControllerLostPasswordTestCase { + public function setUp() { + parent::setUp(); + + $sigb = $this->fixture('Class_IntBib', + ['id' => 3, + 'comm_params' => ['url_serveur' => 'http://localhost', + 'restful' => '0'], + 'comm_sigb' => Class_IntBib::COM_KOHA + ]); + + $this->fixture('Class_Bib', ['id' => 3, + 'libelle' => 'Bibliothèque Georges Brassens', + 'int_bib' => $sigb]); + + $user = $this->fixture('Class_Users', + ['id' => 78, + 'login' => 'Chambelle', + 'password' => 'upw', + 'idabon' => '93658', + 'mail' => 'Chambelle@here.fr', + 'id_site' => 3, + 'int_bib' => $sigb]); + + $user->beAbonneSIGB()->save(); + } + + + /** @test */ + public function withoutSIGBProvideResetPasswordShouldDisplayCustomMessage() { + Class_Bib::find(3)->setResetPassword('Venir à l\'accueil'); + $this->postDispatch('/opac/auth/lostpass' , ['lost_username' => 'Chambelle']); + $this->assertXPathContentContains('//ul[@class="errors"]', "Venir à l'accueil"); + } + + + /** @test */ + public function withoutSIGBProvideResetPasswordShouldDisplayErrorMessage() { + $this->postDispatch('/opac/auth/lostpass' , ['lost_username' => 'Chambelle']); + $this->assertXPathContentContains('//ul[@class="errors"]', 'Merci de vous adresser à la bibliothèque pour récupérer votre mot de passe ou bien le remplacer par un nouveau.'); + } +} + + + + +class AuthControllerLostPasswordOrpheeOnDemandBorrowerCreationTest + extends AuthControllerLostPasswordTestCase { + + public function setUp() { + parent::setUp(); + + $comm_params = ['url_serveur' => 'http://localhost', + 'key' => '0', + 'allow_hold_available_items' => '']; + + $this->fixture('Class_IntBib', + ['id' => 3, + 'comm_params' => $comm_params, + 'comm_sigb' => Class_IntBib::COM_ORPHEE + ]); + + $client = $this->mock() + ->whenCalled('hasFunction')->with('GetAdh')->answers(true) + ->whenCalled('hasFunction')->with('SetPwdAdh')->answers(true) + + ->whenCalled('GetAdh') + ->answers(GetAdhResponse::withResult('<user> + <is_depot><![CDATA[False]]></is_depot> + <no><![CDATA[3062803]]></no> + <nom><![CDATA[DUPONT]]></nom> + <prenom><![CDATA[Henry]]></prenom> + <adr1><![CDATA[28 chemin du Port]]></adr1> + <adr2 /> + <cp><![CDATA[92150]]></cp> + <ville><![CDATA[SURESNES]]></ville> + <tel><![CDATA[0612345678]]></tel> + <birth><![CDATA[02/12/1970]]></birth> + <mail><![CDATA[hdupont@gmail.com]]></mail> + <pwd><![CDATA[secret]]></pwd> + <cb><![CDATA[200092468590]]></cb> + <bloquee><![CDATA[0]]></bloquee> + <cat_stat><![CDATA[20]]></cat_stat> + <lib_cat_stat><![CDATA[ 41-50 ans]]></lib_cat_stat> + <cat_pret><![CDATA[7]]></cat_pret> + <codif><![CDATA[0]]></codif> + <lib_cat_pret><![CDATA[ Pers médiat]]></lib_cat_pret> + <cat_tarif><![CDATA[1]]></cat_tarif> + <lib_cat_tarif><![CDATA[ Gratuit]]></lib_cat_tarif> + <anx><![CDATA[1]]></anx> + <lib_anx><![CDATA[ Bibliothèque]]></lib_anx> + <site><![CDATA[20]]></site> + <date_last_adhes><![CDATA[09/10/2017]]></date_last_adhes> + <sms_rel1><![CDATA[1]]></sms_rel1> + <sms_rel2><![CDATA[0]]></sms_rel2> + <sms_rel3><![CDATA[0]]></sms_rel3> + <sms_rel4><![CDATA[0]]></sms_rel4> + <sms_rsv><![CDATA[0]]></sms_rsv> + <sms_pret><![CDATA[0]]></sms_pret> + <sms_info><![CDATA[0]]></sms_info> + <courrier_rel1><![CDATA[1]]></courrier_rel1> + <courrier_rel2><![CDATA[0]]></courrier_rel2> + <courrier_rel3><![CDATA[0]]></courrier_rel3> + <courrier_rel4><![CDATA[0]]></courrier_rel4> + <courrier_rsv><![CDATA[0]]></courrier_rsv> + <courrier_pret><![CDATA[0]]></courrier_pret> + <courrier_info><![CDATA[0]]></courrier_info> + <mel_rel1><![CDATA[0]]></mel_rel1> + <mel_rel2><![CDATA[0]]></mel_rel2> + <mel_rel3><![CDATA[0]]></mel_rel3> + <mel_rel4><![CDATA[0]]></mel_rel4> + <mel_rsv><![CDATA[0]]></mel_rsv> + <mel_pret><![CDATA[0]]></mel_pret> + <mel_info><![CDATA[0]]></mel_info> + <date_renouv><![CDATA[09/10/2018]]></date_renouv> + <nb_prets><![CDATA[58]]></nb_prets> + <nb_ret><![CDATA[0]]></nb_ret> + <nb_rsv_aff><![CDATA[0]]></nb_rsv_aff> + <nb_rsv_att><![CDATA[2]]></nb_rsv_att> + <solde><![CDATA[0]]></solde> + <lst_cat /> + </user>')); + + Class_WebService_SIGB_Orphee::getService($comm_params) + ->setSearchClient($client) + ->setSessionStrategy($this->mock() + ->whenCalled('isConnected')->answers(true) + ->whenCalled('disconnect')->answers(true)); + + Class_AdminVar::set('LOGIN_THROUGH_SIGB_ONLY', '1'); + + $this->postDispatch('/opac/auth/lostpass', ['lost_username' => '200092468590']); + } + + + public function tearDown() { + Class_WebService_SIGB_Orphee::reset(); + parent::tearDown(); + } + + + /** @test */ + public function userShouldBeCreated() { + $this->assertNotNull(Class_Users::findFirstBy(['login' => '200092468590'])); + } + + + /** @test */ + public function mailShouldBeSent() { + $this->assertNotNull($this->_mail_transport->sent_mail); + } +} + + + +class AuthControllerLostPasswordKohaOnDemandBorrowerCreationTest + extends AuthControllerLostPasswordTestCase { + + public function setUp() { + parent::setUp(); + + $comm_params = ['url_serveur' => 'http://localhost', + 'restful' => '1']; + + $this->fixture('Class_IntBib', + ['id' => 3, + 'comm_params' => $comm_params, + 'comm_sigb' => Class_IntBib::COM_KOHA + ]); + + $client = $this->mock() + ->whenCalled('open_url')->with('http://localhost?service=LookupPatron&id=10002000') + ->answers(KohaFixtures::xmlLookupPatronLaure()) + + ->whenCalled('open_url')->with('http://localhost?service=GetPatronInfo&patron_id=572&show_contact=1&show_loans=1&show_holds=1') + ->answers(KohaFixtures::xmlGetPatronInfoLaure()) + ; + + + Class_WebService_SIGB_Koha::getService(array_merge($comm_params, ['id_bib' => 3, 'type' => 5])) + ->setWebClient($client) + ; + + Class_AdminVar::set('LOGIN_THROUGH_SIGB_ONLY', '1'); + + $this->postDispatch('/opac/auth/lostpass', ['lost_username' => '10002000']); + } + + + public function tearDown() { + Class_WebService_SIGB_Koha::reset(); + parent::tearDown(); + } + + + /** @test */ + public function userShouldBeCreated() { + $this->assertNotNull(Class_Users::findFirstBy(['login' => '10002000'])); + } + + + /** @test */ + public function mailShouldBeSent() { + $this->assertNotNull($this->_mail_transport->sent_mail); + } +} \ No newline at end of file diff --git a/tests/application/modules/opac/controllers/AuthControllerTest.php b/tests/application/modules/opac/controllers/AuthControllerTest.php index cf681457a8a5378df4ccbd9af01c4c2021720085..a246477e6ea9d74386d5ec1561597c1b5e31a58d 100644 --- a/tests/application/modules/opac/controllers/AuthControllerTest.php +++ b/tests/application/modules/opac/controllers/AuthControllerTest.php @@ -1333,87 +1333,6 @@ class AuthControllerLoginActionWithDefaultPreferencesRenderTest extends AuthCont -class AuthControllerLostPasswordUnknownPostTest extends AbstractControllerTestCase{ - protected $_storm_default_to_volatile = true; - - /** @test */ - public function withUnknowUserShouldDisplayError() { - $this->postDispatch('/opac/auth/lostpass', ['lost_username' => 'unknown']); - $this->assertXPathContentContains('//div', - 'Identifiant inconnu', - $this->_response->getBody()); - } - - - /** @test */ - public function withEmptyUserShouldDisplayError() { - $this->postDispatch('/opac/auth/lostpass', ['lost_username' => '']); - $this->assertXPathContentContains('//div', - 'Une valeur est requise', - $this->_response->getBody()); - } -} - - - -class AuthControllerLostPasswordNoMailPostTest extends AbstractControllerTestCase{ - protected $_storm_default_to_volatile = true; - - public function setUp() { - parent::setUp(); - $user = $this->fixture('Class_Users', - ['id' => 1, - 'pseudo' => 'luddite', - 'login' => 'luddite', - 'password' => 'notech', - 'nom' => 'Lu', - 'prenom' => 'Dites']); - - $this->postDispatch('/opac/auth/lostpass' , ['lost_username' => 'luddite']); - } - - - /** @test */ - public function withoutEmailShouldReturnErrorMessage() { - $this->assertXPathContentContains('//div', "Votre mail n'est pas renseigné dans votre compte lecteur. Merci de vous adresser à la bibliothèque pour récupérer votre mot de passe ou bien le remplacer par un nouveau."); - } -} - - - -class AuthControllerLostPasswordTest extends AuthControllerNobodyLoggedTestCase { - public function setUp() { - parent::setUp(); - $this->dispatch('/opac/auth/lostpass', true); - } - - - /** @test */ - public function formActionShouldBeLostPass() { - $this->assertXPath('//form[@id="form_lostpass"][contains(@action, "/auth/lostpass")]'); - } - - - /** @test */ - public function formShouldContainsInputForUsername() { - $this->assertXPath('//form[@id="form_lostpass"]//input[@type="text"][@name="lost_username"][@placeholder="jj-mm-aaaa"]', $this->_response->getBody()); - } - - - /** @test */ - public function formShouldContainsLabelNumeroDeCarteForInputForUsername() { - $this->assertXPathContentContains('//form[@id="form_lostpass"]//label[@for="lost_username"]', 'Numéro de carte'); - } - - - /** @test */ - public function pageShouldBeHTML5Valid() { - $this->assertHTML5(); - } -} - - - class AuthControllerNobodyLoggedAndRegistrationAllowedRegisterTest extends AuthControllerNobodyLoggedTestCase { public function setUp() { @@ -2644,56 +2563,3 @@ class AuthControllerPostLoginWithDifferentIdIntBibTest $this->assertEquals(56, $user->getIdIntBib()); } } - - - - -class AuthControllerBorrowerLostPasswordTest extends AbstractControllerTestCase{ - protected $_storm_default_to_volatile = true; - - public function setUp() { - parent::setUp(); - - $mail_transport = new MockMailTransport(); - Zend_Mail::setDefaultTransport($mail_transport); - - $sigb = $this->fixture('Class_IntBib', - ['id' => 3, - 'comm_params' => ['url_serveur' => 'http://localhost', - 'restful' => '0'], - 'comm_sigb' => Class_IntBib::COM_KOHA - ]); - - $this->fixture('Class_Bib', ['id' => 3, - 'libelle' => 'Bibliothèque Georges Brassens', - 'int_bib' => $sigb]); - - $user = $this->fixture('Class_Users', - ['id' => 78, - 'login' => 'Chambelle', - 'password' => 'upw', - 'idabon' => '93658', - 'mail' => 'Chambelle@here.fr', - 'id_site' => 3, - 'int_bib' => $sigb]); - - $user->beAbonneSIGB()->save(); - - ZendAfi_Auth::getInstance()->clearIdentity(); - } - - - /** @test */ - public function withoutSIGBProvideResetPasswordShouldDisplayCustomMessage() { - Class_Bib::find(3)->setResetPassword('Venir à l\'accueil'); - $this->postDispatch('/opac/auth/lostpass' , ['lost_username' => 'Chambelle']); - $this->assertXPathContentContains('//ul[@class="errors"]', "Venir à l'accueil"); - } - - - /** @test */ - public function withoutSIGBProvideResetPasswordShouldDisplayErrorMessage() { - $this->postDispatch('/opac/auth/lostpass' , ['lost_username' => 'Chambelle']); - $this->assertXPathContentContains('//ul[@class="errors"]', 'Merci de vous adresser à la bibliothèque pour récupérer votre mot de passe ou bien le remplacer par un nouveau.'); - } -} \ No newline at end of file diff --git a/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php b/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php index 3a5d1955fed854fc07e4b19e5ec8d0351a2be5a2..41a5ea88bb769afce3443e0fe57e5dec91c2c0b3 100644 --- a/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php +++ b/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php @@ -172,7 +172,7 @@ class NoticeAjaxControllerNoticeSimilairesSouleymaneTest extends NoticeAjaxContr public function setUp() { parent::setUp(); - + Class_AdminVar::set('AUTHOR_PAGE', 0); Class_Notice::newInstanceWithId(18787, ['titres' => 'IRM SOULEY', 'auteurs' => 'MOI', diff --git a/tests/application/modules/opac/controllers/RechercheControllerTest.php b/tests/application/modules/opac/controllers/RechercheControllerTest.php index 8b8c251c431f2dfd1e199dd82ca5109708617355..339237723974e2015cd57f3444f8e0bd012d37c2 100644 --- a/tests/application/modules/opac/controllers/RechercheControllerTest.php +++ b/tests/application/modules/opac/controllers/RechercheControllerTest.php @@ -304,6 +304,8 @@ class RechercheControllerViewNoticeWithPreferencesTest extends RechercheControll public function setUp() { parent::setUp(); + Class_AdminVar::set('AUTHOR_PAGE', 0); + $time_source = new TimeSourceForTest('2013-12-27 09:00:00'); Class_Notice::setTimeSource($time_source); @@ -562,6 +564,7 @@ class RechercheControllerViewNoticeWithPreferencesTest extends RechercheControll class RechercheControllerViewNoticeTest extends RechercheControllerNoticeTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('AUTHOR_PAGE', 0); $this->dispatch('recherche/viewnotice/id/345', true); } @@ -573,16 +576,19 @@ class RechercheControllerViewNoticeTest extends RechercheControllerNoticeTestCas $this->_response->getBody()); } + /** @test */ public function pageShouldContainsOnlyTwoH1() { $this->assertXPathCount('//h1', 2, $this->_response->getBody()); } + /** @test */ public function pageShouldContainsH1WithTitleAndAuthor() { $this->assertXPath('//h1//span[contains(text(), "Cinéma d\'animation")][following-sibling::span[text()="Bernard Génin"]]'); } + /** @test */ public function tagReseauSociauxShouldBePresent() { $this->assertXPath('//div[@id="reseaux-sociaux"]'); @@ -3129,8 +3135,7 @@ class RechercheControlleSimpleActionWithMultifacetsThesauriTest extends Recherch 'libelle_facette' => 'Document', 'id_thesaurus' => 'DOCU', 'id_origine' => null, - 'code' => 'DOCU', - 'rules' => '{"label":" 99$t "}']); + 'code' => 'DOCU']); $this->fixture('Class_CodifThesaurus', ['id' => 30, @@ -3138,32 +3143,28 @@ class RechercheControlleSimpleActionWithMultifacetsThesauriTest extends Recherch 'libelle_facette' => 'Musique', 'id_thesaurus' => 'MUSI', 'id_origine' => null, - 'code' => 'MUSI', - 'rules' => '{"label":" 95$t "}']); + 'code' => 'MUSI']); $this->fixture('Class_CodifThesaurus', ['id' => 4, 'libelle' => 'SIFI', 'libelle_facette' => 'Science fiction', 'id_thesaurus' => 'DOCU0001', - 'code' => 'SIFI', - 'rules' => '{"label":" 99$t "}']); + 'code' => 'SIFI']); $this->fixture('Class_CodifThesaurus', ['id' => 5, 'libelle' => 'BD', 'libelle_facette' => 'Bande dessinee', 'id_thesaurus' => 'DOCU0002', - 'code' => 'BD', - 'rules' => '{"label":" 99$t "}']); + 'code' => 'BD']); $this->fixture('Class_CodifThesaurus', ['id' => 6, 'libelle' => 'BD', 'libelle_facette' => 'Manga', 'id_thesaurus' => 'DOCU00020001', - 'code' => 'Manga', - 'rules' => '{"label":" 90$t "}']); + 'code' => 'Manga']); $this->fixture('Class_CodifThesaurus', ['id' => 31, @@ -3171,8 +3172,7 @@ class RechercheControlleSimpleActionWithMultifacetsThesauriTest extends Recherch 'libelle_facette' => 'Experimentale', 'id_origine' => 30, 'id_thesaurus' => 'MUSI0001', - 'code' => 'EXPE', - 'rules' => '{"label":" 95$t "}']); + 'code' => 'EXPE']); $this->fixture('Class_Article', ['id' => 1, diff --git a/tests/db/UpgradeDBTest.php b/tests/db/UpgradeDBTest.php index a575eeef114bb5c7889f1377cc726a86b3f4eaa2..4eb5ae89b45542799e95045101302cadc1579ed2 100644 --- a/tests/db/UpgradeDBTest.php +++ b/tests/db/UpgradeDBTest.php @@ -1999,7 +1999,6 @@ class UpgradeDB_341_Test extends UpgradeDBTestCase { - class UpgradeDB_342_Test extends UpgradeDBTestCase { public function prepare() {} @@ -2410,6 +2409,67 @@ class UpgradeDB_361_Test extends UpgradeDBTestCase { class UpgradeDB_362_Test extends UpgradeDBTestCase { + public function prepare() { + $this->silentQuery('ALTER TABLE album drop KEY date_maj'); + } + + + /** @test */ + public function dateMajShouldBeIndexed() { + $this->assertIndex('album', 'date_maj'); + } +} + + + + +class UpgradeDB_363_Test extends UpgradeDBTestCase { + public function prepare() { + $this->silentQuery("replace into codif_thesaurus (id_thesaurus, libelle, code, rules) values ('TEST', 'TEST', 'TEST', '{\"label\":\"609\$a\"}')"); + } + + + /** @test */ + public function rulesShouldBeMigrated() { + $thesaurus = $this->query('select rules from codif_thesaurus where id_thesaurus="TEST"')->fetch(); + $expected = (new Class_CodifThesaurus_Rules())->setZone('609')->setLabelField('a')->format(); + $this->assertEquals($expected, $thesaurus['rules']); + } +} + + + + +class UpgradeDB_364_Test extends UpgradeDBTestCase { + public function prepare() { + $this->silentQuery('ALTER TABLE newsletters DROP column articles_ids'); + $this->silentQuery('ALTER TABLE newsletters DROP column articles_categories_ids'); + } + + /** @test **/ + public function articlesIdsShouldBePresent() { + $this->assertColumn('newsletters', 'articles_ids'); + } + + /** @test **/ + public function articlesCategoriesShouldBePresent() { + $this->assertColumn('newsletters', 'articles_categories_ids'); + } +} + + + +class UpgradeDB_365_Test extends UpgradeDBTestCase { + public function prepare() {} + + /** @test */ + public function placeholderForBokehEightMigration() {} +} + + + + +class UpgradeDB_366_Test extends UpgradeDBTestCase { public function prepare() { $this ->silentQuery('ALTER TABLE codif_auteur DROP KEY wikidata_id') @@ -2444,4 +2504,4 @@ class UpgradeDB_362_Test extends UpgradeDBTestCase { public function itemTypeShouldBeIndexed() { $this->assertIndex('codif_auteur', 'wikidata_id'); } -} \ No newline at end of file +} diff --git a/tests/fixtures/RedmineFixtures.php b/tests/fixtures/RedmineFixtures.php index 5bab9f300c192019c13ba59da5569c81b8682bd0..4aac063424b4e3c9167b4b75ad4a0f4e9db3b9cf 100644 --- a/tests/fixtures/RedmineFixtures.php +++ b/tests/fixtures/RedmineFixtures.php @@ -87,7 +87,8 @@ class RedmineFixtures { 'story_points' => ''], static::issue34247(), - static::issue34248()], + static::issue34248(), + static::issue34249()], 'total_count' => 2, 'offset' => 0 , 'limit' => 25]; @@ -158,6 +159,38 @@ class RedmineFixtures { } + public static function issue34249() { + return ['id' => 34249, + 'project' => ['id' => 56, + 'name' => 'Développement Bokeh AFI-OPAC 2.0'], + 'tracker' => ['id' => 2, + 'name' => 'Développement'], + 'status' => ['id' => 3, + 'name' => 'Réaliser à tester'], + 'priority' => ['id' => 4, + 'name' => 'Normal'], + 'author' => ['id' => 207, + 'name' => 'gloas'], + 'assigned_to' => ['id' => 207, + 'name' => 'gloas'], + 'subject' => 'Un problème à tester', + 'description' => 'important', + 'done_ratio' => 80, + 'custom_fields' => [ ['id' => 37, + 'name' => 'Module Portail', + 'value' => ''], + ['id' => 5 , + 'name' => 'Priorité client', + 'value' => 'Normale'], + ['id' => 11, + 'name' => 'Phase', + 'value' => '']], + 'created_on' => '2015-12-04T09:19:11Z', + 'updated_on' => '2015-12-04T09:25:42Z', + 'story_points' => '']; + } + + public static function projectHotline() { return ['project' => ['name' => 'Hotline']]; } diff --git a/tests/library/Class/ArticleLoaderTest.php b/tests/library/Class/ArticleLoaderTest.php index 4ebb6445c88bd68dc5586ef875ac28943fde6572..215bd719044b73a7596c29f7fae54c807356a840 100644 --- a/tests/library/Class/ArticleLoaderTest.php +++ b/tests/library/Class/ArticleLoaderTest.php @@ -715,7 +715,11 @@ class ArticleLoaderFilterByDayTest extends ArticleLoaderGetArticlesByPreferences $this->assertEquals([18, 55, 57], $this->_getArticlesId(['event_date' => '2011-09-04'])); } -} -?> + /** @test */ + public function withMonthShouldGetAllArticles() { + $this->assertEquals([23, 18, 55, 57], + $this->_getArticlesId(['event_date' => '2011-09'])); + } +} diff --git a/tests/library/Class/CodifThesaurusTest.php b/tests/library/Class/CodifThesaurusTest.php index 6e9a199bafe46b045aee70a977a756fdee0fc33e..9cb92269d4caab0e0faf85b031e9814596326c6d 100644 --- a/tests/library/Class/CodifThesaurusTest.php +++ b/tests/library/Class/CodifThesaurusTest.php @@ -200,7 +200,7 @@ class CodifThesaurusTooManyValuesTest extends ModelTestCase { 'code' => 'TEST', 'id' => 723, 'libelle_facette' => 'test', - 'rules' => '{"label":"610$a"}']); + 'rules' => null]); $this->fixture('Class_CodifThesaurus', ['id_thesaurus' => 'TEST9999', @@ -213,6 +213,7 @@ class CodifThesaurusTooManyValuesTest extends ModelTestCase { } + /** @test */ public function shouldNotInsertMoreThan9999Child() { Class_CodifThesaurus::find(723) diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseAuthorityTest.php b/tests/library/Class/Cosmogramme/Integration/PhaseAuthorityTest.php index e9af0c2775e30eeeda01581f13feaad8f63994c9..3a77c89121f85b64e299a13db74a1d583c02ba2f 100644 --- a/tests/library/Class/Cosmogramme/Integration/PhaseAuthorityTest.php +++ b/tests/library/Class/Cosmogramme/Integration/PhaseAuthorityTest.php @@ -38,12 +38,19 @@ class PhaseAuthorityTest extends Class_Cosmogramme_Integration_PhaseTestCase { protected function _prepareFixtures() { + $attributs = [[Class_IntProfilDonnees::PROFILE_INDEX_SYSTEMS_FIELDS + => [['rule' => '', + 'system' => 'TESS', + 'default_type' => '', + 'thesaurus' => '5']]]]; + $this->fixture('Class_IntProfilDonnees', ['id' => 102, 'libelle' => 'Autorités Pergame', 'accents' => Class_IntProfilDonnees::ENCODING_UTF8, 'type_fichier' => Class_IntProfilDonnees::FT_AUTHORITY, 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'attributs' => serialize($attributs), ]); $this->fixture('Class_IntBib', @@ -59,6 +66,11 @@ class PhaseAuthorityTest extends Class_Cosmogramme_Integration_PhaseTestCase { 'traite' => 'non', 'fichier' => 'authorities_tess_mini.mrc', 'pointeur_reprise' => 0]); + + $this->fixture('Class_CodifThesaurus', + ['id' => 5, + 'id_thesaurus' => 'HMOTS', + 'libelle' => 'Mots-clés TESS']); } @@ -107,6 +119,15 @@ class PhaseAuthorityTest extends Class_Cosmogramme_Integration_PhaseTestCase { } + /** + * @test + * @depends amenagementDuTerritoireShouldExists + **/ + public function amenagementDuTerritoireShouldHaveIndexSystemThesaurusFacet($record) { + $this->assertContains('HMOTS', $record->getFacettes()); + } + + /** @test */ public function codifMatiereAmenagementDuTerritoireShouldExists() { $this->assertNotNull(Class_CodifMatiere::findFirstBy(['libelle' => 'Aménagement du territoire'])); diff --git a/tests/library/Class/Cosmogramme/Integration/PhasePrepareIntegrationsTest.php b/tests/library/Class/Cosmogramme/Integration/PhasePrepareIntegrationsTest.php index 6eff530223fa9b45b35dc3cf6de98688b980049c..a3c3f28f6720444fb5289c45b7a0ce7ddd73708b 100644 --- a/tests/library/Class/Cosmogramme/Integration/PhasePrepareIntegrationsTest.php +++ b/tests/library/Class/Cosmogramme/Integration/PhasePrepareIntegrationsTest.php @@ -1,4 +1,4 @@ -~<?php +<?php /** * Copyright (c) 2012-2014, Agence Française Informatique (AFI). All rights reserved. * @@ -27,49 +27,89 @@ abstract class PhasePrepareIntegrationsWithOAITestCase public function setUp() { parent::setUp(); - $file_system = $this->mock() - ->whenCalled('is_file') - ->with ('ftp/my-library.net/transferts/foo/mylibrarytotal.txt') - ->answers(true) + $foo = + $this->mock() + ->whenCalled('getName')->answers('foo') + ->whenCalled('getPath')->answers('ftp/my-library.net/transferts/foo'); - ->whenCalled('filesize') - ->with ('ftp/my-library.net/transferts/foo/mylibrarytotal.txt') - ->answers(11000000) + $file_with_date = + $this->mock() + ->whenCalled('getName')->answers('20180517mylibraryincr.txt') + ->whenCalled('getId')->answers('ftp/my-library.net/transferts/foo/20180517mylibraryincr.txt') + ->whenCalled('getFileMTime')->answers(strtotime('2018-05-17')) + ->whenCalled('getParent')->answers($foo); - ->whenCalled('is_file') - ->with ('ftp/my-library.net/transferts/foo/toosmall.txt') - ->answers(true) + $other_with_date = + $this->mock() + ->whenCalled('getName')->answers('20190118mylibraryincr.txt') + ->whenCalled('getId')->answers('ftp/my-library.net/transferts/foo/20190118mylibraryincr.txt') + ->whenCalled('getFileMTime')->answers(strtotime('2019-01-18')) + ->whenCalled('getParent')->answers($foo); - ->whenCalled('filesize') - ->with ('ftp/my-library.net/transferts/foo/toosmall.txt') - ->answers(1000000) + $file_system_manager = + $this->mock() + ->whenCalled('diskSpaceInfo')->answers(null) - ->whenCalled('is_file') - ->with ('ftp/my-library.net/transferts/foo/20180517mylibraryincr.txt') - ->answers(true) + ->whenCalled('directoriesAt')->with('ftp/my-library.net/transferts/') + ->answers([$foo]) - ->whenCalled('opendir') - ->with ('ftp/my-library.net/transferts/foo/') - ->answers('dir_pointer') + ->whenCalled('filesAt')->with('ftp/my-library.net/transferts/foo') + ->answers([$file_with_date, + $other_with_date]); - ->whenCalled('readdir') - ->with ('dir_pointer') - ->answers('20180517mylibraryincr.txt') - ->whenCalled('closedir') - ->with ('dir_pointer') - ->answers(true) + Class_FileManager::setFileSystem($file_system_manager); - ->whenCalled('rename') - ->with('ftp/my-library.net/transferts/foo/mylibrarytotal.txt', - 'ftp/my-library.net/integration/integre1179.pan') - ->answers(true) + $file_system = + $this->mock() + ->whenCalled('is_file') + ->with ('ftp/my-library.net/transferts/foo/mylibrarytotal.txt') + ->answers(true) - ->whenCalled('rename') - ->with('ftp/my-library.net/transferts/foo/20180517mylibraryincr.txt', - 'ftp/my-library.net/integration/integre1180.pan') - ->answers(true) - ->beStrict(); + ->whenCalled('filesize') + ->with ('ftp/my-library.net/transferts/foo/mylibrarytotal.txt') + ->answers(11000000) + + ->whenCalled('is_file') + ->with ('ftp/my-library.net/transferts/foo/toosmall.txt') + ->answers(true) + + ->whenCalled('filesize') + ->with ('ftp/my-library.net/transferts/foo/toosmall.txt') + ->answers(1000000) + + ->whenCalled('is_file') + ->with ('ftp/my-library.net/transferts/foo/20180517mylibraryincr.txt') + ->answers(true) + + ->whenCalled('opendir') + ->with ('ftp/my-library.net/transferts/foo/') + ->answers('dir_pointer') + + ->whenCalled('readdir') + ->with('dir_pointer') + ->answers('20180517mylibraryincr.txt') + + ->whenCalled('closedir') + ->with ('dir_pointer') + ->answers(true) + + ->whenCalled('rename') + ->with('ftp/my-library.net/transferts/foo/mylibrarytotal.txt', + 'ftp/my-library.net/integration/integre1179.pan') + ->answers(true) + + ->whenCalled('rename') + ->with('ftp/my-library.net/transferts/foo/20180517mylibraryincr.txt', + 'ftp/my-library.net/integration/integre1180.pan') + ->answers(true) + + ->whenCalled('rename') + ->with('ftp/my-library.net/transferts/foo/20190118mylibraryincr.txt', + 'ftp/my-library.net/integration/integre1181.pan') + ->answers(true) + + ->beStrict(); $this->_http_client = $this->mock() ->whenCalled('postData') @@ -216,29 +256,15 @@ class PhasePrepareIntegrationsWithOAITest extends PhasePrepareIntegrationsWithOA /** @test */ - public function threeIntegrationsShouldHaveBeenCreated() { - $this->assertEquals(4, count(Class_Cosmogramme_Integration::findAll())); - } - - - /** @test */ - public function firstIntegrationFileShouldBeIntegre1179DotPan() { - $this->assertEquals('integre1179.pan', - Class_Cosmogramme_Integration::find(2)->getFichier()); - } - - - /** @test */ - public function firstIntegrationFileNameShouldBeMyLibraryTotalDotTxt() { - $this->assertEquals('foo/mylibrarytotal.txt', - Class_Cosmogramme_Integration::find(2)->getNomFichier()); + public function fiveIntegrationsShouldHaveBeenCreated() { + $this->assertEquals(5, count(Class_Cosmogramme_Integration::findAll())); } /** @test */ public function firstIntegrationKeyShouldBeHash() { - $this->assertEquals('a7be1b1bbdfe70b6fec563334accab3f', - Class_Cosmogramme_Integration::find(2)->getHash()); + $this->assertEquals(Class_Cosmogramme_Integration::findFirstBy(['nom_fichier' => 'foo/mylibrarytotal.txt']) + ->getHash(), 'a7be1b1bbdfe70b6fec563334accab3f'); } @@ -258,7 +284,7 @@ class PhasePrepareIntegrationsWithOAITest extends PhasePrepareIntegrationsWithOA /** @test */ public function thirdIntegrationURIShouldBeOAIRepository() { $this->assertEquals('http://oai-repository.fr/oai', - Class_Cosmogramme_Integration::find(4)->getFichier()); + Class_Cosmogramme_Integration::find(5)->getFichier()); } @@ -336,8 +362,8 @@ class PhasePrepareIntegrationsWithOAIIntegrationAlreadyRegisteredTest /** @test */ - public function oneIntegrationShouldHaveBeenCreated() { - $this->assertEquals(4, count(Class_Cosmogramme_Integration::findAll())); + public function fiveIntegrationShouldHaveBeenCreated() { + $this->assertEquals(5, count(Class_Cosmogramme_Integration::findAll())); } } @@ -352,12 +378,39 @@ class PhasePrepareIntegrationsNanookStandardTest Zend_Registry::set('sql', $this->mock()->beStrict()); - $file_system = $this->mock() - ->whenCalled('is_file') - ->with('ftp/my-library.net/transferts/foo/mylibrarytotal.txt') - ->answers(false) - ->beStrict(); + $file_system = $this->mock()->beStrict(); + + foreach ([2, 6, 8] as $site) + $file_system + + ->whenCalled('is_file') + ->with('ftp/my-library.net/transferts/foo/site' . $site . '/suppressions.txt') + ->answers(false) + + ->whenCalled('is_file') + ->with('ftp/my-library.net/transferts/foo/site' . $site . '/notices_total.txt') + ->answers(false) + + ->whenCalled('is_file') + ->with('ftp/my-library.net/transferts/foo/site' . $site . '/notices.txt') + ->answers(false) + + ->whenCalled('is_file') + ->with('ftp/my-library.net/transferts/foo/site' . $site . '/abonnes.txt') + ->answers(false) + + ->whenCalled('is_file') + ->with('ftp/my-library.net/transferts/foo/site' . $site . '/prets.txt') + ->answers(false) + + ->whenCalled('is_file') + ->with('ftp/my-library.net/transferts/foo/site' . $site . '/paniers_total.txt') + ->answers(false) + + ->whenCalled('is_file') + ->with('ftp/my-library.net/transferts/foo/site' . $site . '/paniers.txt') + ->answers(false); $this->_http_client = $this->mock() ->whenCalled('postData') diff --git a/tests/library/Class/Cosmogramme/Integration/PhasePseudoRecordTest.php b/tests/library/Class/Cosmogramme/Integration/PhasePseudoRecordTest.php index a09e4baf1208c19b08ff9e4d90bc69b1ded19690..c9f694ee7cf97d8a6b44c4b508298a81e343cd1b 100644 --- a/tests/library/Class/Cosmogramme/Integration/PhasePseudoRecordTest.php +++ b/tests/library/Class/Cosmogramme/Integration/PhasePseudoRecordTest.php @@ -36,21 +36,22 @@ abstract class PhasePseudoRecordTestCase extends Class_Cosmogramme_Integration_P protected function _prepareFixtures() { - $loader = $this->onLoaderOfModel($this->_model_name) + $loader = $this + ->onLoaderOfModel($this->_model_name) - ->whenCalled('findAllBy') - ->with(['where' => $this->_model_id . ' > 0', - 'order' => $this->_model_id, - 'limit' => 100]) - ->answers([$this->_buildModel(15)]) + ->whenCalled('findAllBy') + ->with(['where' => $this->_model_id . ' > 0', + 'order' => $this->_model_id, + 'limit' => 100]) + ->answers([$this->_buildModel(15)]) - ->whenCalled('findAllBy') - ->with(['where' => $this->_model_id . ' > 15', - 'order' => $this->_model_id, - 'limit' => 100]) - ->answers([$this->_buildModel(16)]) + ->whenCalled('findAllBy') + ->with(['where' => $this->_model_id . ' > 15', + 'order' => $this->_model_id, + 'limit' => 100]) + ->answers([$this->_buildModel(16)]) - ->whenCalled('findAllBy')->answers([]); + ->whenCalled('findAllBy')->answers([]); } @@ -423,11 +424,42 @@ abstract class PhasePseudoRecordAlbumTestCase extends PhasePseudoRecordTestCase $_model_name = 'Class_Album', $_model_id = 'id'; + protected function _prepareFixtures() { + Class_Cosmogramme_Integration_PhasePseudoRecordAlbum::setTimeSource(new TimeSourceForTest('2019-01-09 12:11:38')); + + Class_CosmoVar::setValueOf('date_maj_albums', '2018-12-18 17:21:54'); + + $loader = $this + ->onLoaderOfModel($this->_model_name) + ->whenCalled('findAllBy') + ->with(['where' => $this->_model_id . ' > 0 and date_maj >= \'2018-12-18 17:21:54\'', + 'order' => $this->_model_id, + 'limit' => 100]) + ->answers([$this->_buildModel(15)]) + + ->whenCalled('findAllBy') + ->with(['where' => $this->_model_id . ' > 15 and date_maj >= \'2018-12-18 17:21:54\'', + 'order' => $this->_model_id, + 'limit' => 100]) + ->answers([$this->_buildModel(16)]) + + ->whenCalled('findAllBy')->answers([]) + ; + } + + + public function tearDown() { + Class_Cosmogramme_Integration_PhasePseudoRecordAlbum::setTimeSource(null); + parent::tearDown(); + } + + protected function _getModelAttribs($id) { return array_merge(parent::_getModelAttribs($id), ['titre' => 'Album ' . $id, 'visible' => 1, - 'status' => Class_Album::STATUS_VALIDATED]); + 'status' => Class_Album::STATUS_VALIDATED, + 'date_maj' => '2018-12-18 17:21:54']); } } @@ -472,6 +504,13 @@ class PhasePseudoRecordAlbumValidInteractiveCallbackTest ->beCallBack() ->setData('nombre', 1) ->setData('pointeur_reprise', 15) + ->setData('pointeur', '2018-12-18 17:21:54') ->setCount(Class_Cosmogramme_Integration_Phase::RECORD_INSERT, 6); } + + + /** @test */ + public function dateMajAlbumsShouldBeUpdated() { + $this->assertEquals('2019-01-09 12:11:38', Class_CosmoVar::get('date_maj_albums')); + } } \ No newline at end of file diff --git a/tests/library/Class/DecodageUnimarcTest.php b/tests/library/Class/DecodageUnimarcTest.php index d306b3aa18bb6ce9635e7ab0e5df2d3140ee1434..5a474e0d5d716b2ec1d1b5a85de4627b8f3e3deb 100644 --- a/tests/library/Class/DecodageUnimarcTest.php +++ b/tests/library/Class/DecodageUnimarcTest.php @@ -246,6 +246,7 @@ class DecodageUnimarcEcosseTest extends PHPUnit_Framework_TestCase { class DecodageUnimarcConcertoAuteursTest extends PHPUnit_Framework_TestCase { public function setUp() { + Class_AdminVar::set('AUTHOR_PAGE', 0); $this->concerto = new Class_Notice(); $this->concerto->setUnimarc("00963njm0 2200265 450 001000600000010002000006101001300026200002400039200002600063200002700089200002800116200004400144210004000188215003300228608003800261608003800299610005900337610005900396686000600455700006500461700005300526702002900579702004200608702004700650265555 aHMU907286d15.7 afreafre1 aPiano concerto N 3� iIallegro ma non tanto� iII Intermezzo : adagio� iIII Finale : alla breve� iRhapsody on a theme of Paganini, op. 43 aArlesd 2001cHarmonia mundi France a1 disque compacte1 brochure amusique instrumentale orchestrale amusique instrumentale orchestrale aConcertos (piano) - Disques compactsxDisques compacts aConcertos (piano) - Disques compactsxDisques compacts a3 1aRACHMANINOVbSergueï Vassilievitch4Fonction indéterminée 1aRACHMANINOVbSergueï Vassilievitch4Compositeur 1aNAKAMATSUbJon4Musicien 1aSEAMANbChristopher4Chef d'orchestre 1aROCHESTER PHILHARMONIC ORCHESTRA4Musicien"); @@ -317,7 +318,7 @@ class DecodageUnimarcDVDUnHerosTresDiscretTest extends ModelTestCase { public function setUp() { parent::setUp(); - + Class_AdminVar::set('AUTHOR_PAGE', 0); $this->fixture('Class_CodifLangue', ['id' => 23, 'libelle' => '']); diff --git a/tests/library/Class/Migration/BokehEightTest.php b/tests/library/Class/Migration/BokehEightTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8871cc1f0522c6220f25a347371dce44dd590bc9 --- /dev/null +++ b/tests/library/Class/Migration/BokehEightTest.php @@ -0,0 +1,168 @@ +<?php +/** + * Copyright (c) 2012-2019, 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_BokehEightTest extends ModelTestCase { + + /** @test */ + public function bibnumShouldBecomeEnabled() { + Class_AdminVar::set('BIBNUM', 0); + (new Class_Migration_BokehEight)->run(); + $this->assertTrue(Class_AdminVar::isBibNumEnabled()); + } + + + /** @test */ + public function bibnumDefaultShouldBeEnabled() { + $this->assertTrue(Class_AdminVar::isBibNumEnabled()); + } + + + /** @test */ + public function opdsShouldBecomeEnabled() { + Class_AdminVar::set('OPDS', 0); + (new Class_Migration_BokehEight)->run(); + $this->assertTrue(Class_AdminVar::isOpdsEnabled()); + } + + + /** @test */ + public function opdsDefaultShouldBeEnabled() { + $this->assertTrue(Class_AdminVar::isOpdsEnabled()); + } + + + /** @test */ + public function codificationBrowserShouldBecomeEnabled() { + Class_AdminVar::set('CODIFICATION_BROWSER', 0); + (new Class_Migration_BokehEight)->run(); + $this->assertTrue(Class_AdminVar::isCodificationBrowserEnabled()); + } + + + /** @test */ + public function codificationBrowserDefaultShouldBeEnabled() { + $this->assertTrue(Class_AdminVar::isCodificationBrowserEnabled()); + } + + + /** @test */ + public function inspectorGadgetMarcXMLShouldBecomeEnabled() { + Class_AdminVar::set('INSPECTOR_GADGET_MARC_XML', 0); + (new Class_Migration_BokehEight)->run(); + $this->assertTrue(Class_AdminVar::isInspectorGadgetMarcXmlEnabled()); + } + + + /** @test */ + public function inspectorGadgetMarcXMLShouldBeEnabled() { + $this->assertTrue(Class_AdminVar::isInspectorGadgetMarcXmlEnabled()); + } + + + /** @test */ + public function customSearchFormShouldBecomeEnabled() { + Class_AdminVar::set('CUSTOM_SEARCH_FORM', 0); + (new Class_Migration_BokehEight)->run(); + $this->assertTrue(Class_AdminVar::isCustomSearchFormEnabled()); + } + + + /** @test */ + public function customSearchFormShouldBeEnabled() { + $this->assertTrue(Class_AdminVar::isCustomSearchFormEnabled()); + } + + + /** @test */ + public function authorPageShouldBecomeEnabled() { + Class_AdminVar::set('AUTHOR_PAGE', 0); + (new Class_Migration_BokehEight)->run(); + $this->assertTrue(Class_AdminVar::isAuthorPageEnabled()); + } + + + /** @test */ + public function authorPageShouldBeEnabled() { + $this->assertTrue(Class_AdminVar::isAuthorPageEnabled()); + } + + + /** @test */ + public function withSingleKohaLoginThroughSigbOnlyShouldBecomeEnabled() { + Class_AdminVar::set('LOGIN_THROUGH_SIGB_ONLY', 0); + $this->fixture('Class_Intbib', + ['id' => 4, + 'sigb' => Class_IntBib::SIGB_KOHA, + 'comm_params' => ['url_serveur' => 'https://service.local']]); + (new Class_Migration_BokehEight)->run(); + $this->assertTrue(Class_AdminVar::isLoginThroughSigbOnlyEnabled()); + } + + + /** @test */ + public function withSingleNanookLoginThroughSigbOnlyShouldBecomeEnabled() { + Class_AdminVar::set('LOGIN_THROUGH_SIGB_ONLY', 0); + $this->fixture('Class_Intbib', + ['id' => 4, + 'sigb' => Class_IntBib::SIGB_NANOOK, + 'comm_params' => ['url_serveur' => 'https://service.local']]); + (new Class_Migration_BokehEight)->run(); + $this->assertTrue(Class_AdminVar::isLoginThroughSigbOnlyEnabled()); + } + + + /** @test */ + public function withOrpheeLoginThroughSigbOnlyShouldRemainDisabled() { + Class_AdminVar::set('LOGIN_THROUGH_SIGB_ONLY', 0); + $this->fixture('Class_Intbib', + ['id' => 4, + 'sigb' => Class_IntBib::SIGB_ORPHEE, + 'comm_params' => ['url_serveur' => 'https://service.local']]); + (new Class_Migration_BokehEight)->run(); + $this->assertFalse(Class_AdminVar::isLoginThroughSigbOnlyEnabled()); + } + + + /** @test */ + public function withBothNanookAndKohaLoginThroughSigbOnlyShouldRemainDisabled() { + Class_AdminVar::set('LOGIN_THROUGH_SIGB_ONLY', 0); + $this->fixture('Class_Intbib', + ['id' => 4, + 'sigb' => Class_IntBib::SIGB_NANOOK, + 'comm_params' => ['url_serveur' => 'https://service-nanook.local']]); + $this->fixture('Class_Intbib', + ['id' => 5, + 'sigb' => Class_IntBib::SIGB_KOHA, + 'comm_params' => ['url_serveur' => 'https://service-koha.local']]); + + (new Class_Migration_BokehEight)->run(); + $this->assertFalse(Class_AdminVar::isLoginThroughSigbOnlyEnabled()); + } + + + /** @test */ + public function variableDateMajAlbumsShouldHaveGroup6() { + Class_CosmoVar::setValueOf('date_maj_albums', ''); + (new Class_Migration_BokehEight)->run(); + $this->assertEquals(6, Class_CosmoVar::find('date_maj_albums')->getGroupe()); + } +} diff --git a/tests/library/Class/User/LostPassTest.php b/tests/library/Class/User/LostPassTest.php index 7844721e2458757f810826a709797e50f2f568fb..3d000ea4d701c14e4b53cbc7c69377e77412ca3c 100644 --- a/tests/library/Class/User/LostPassTest.php +++ b/tests/library/Class/User/LostPassTest.php @@ -92,6 +92,15 @@ class Class_User_LostPassSendTest extends ModelTestCase { } + /** @test */ + public function withNanookMailShouldContainsResetLink() { + $this->_sigb->setCommSigb(Class_IntBib::COM_NANOOK)->save(); + (new Class_User_LostPass($this->_user))->send(); + $mail = $this->_mail_transport->getSentMails()[0]->getBodyText()->getContent(); + $this->assertContains('/auth/reset-password', $mail); + } + + /** @test */ public function withPergameShouldNotsendMail() { $this->_sigb->setCommSigb(Class_IntBib::COM_PERGAME)->save(); diff --git a/tests/library/Class/WebService/SIGB/KohaTest.php b/tests/library/Class/WebService/SIGB/KohaTest.php index 3b79e497552b5ca59ab533d48a30af23634b61a8..ae1c49d70f15878f1072b6e64648a2e74fc86e5f 100644 --- a/tests/library/Class/WebService/SIGB/KohaTest.php +++ b/tests/library/Class/WebService/SIGB/KohaTest.php @@ -83,8 +83,8 @@ class KohaGetServiceTest extends ModelTestCase { } + abstract class KohaTestCase extends ModelTestCase { - protected $_storm_default_to_volatile = true; protected $mock_web_client; protected $service; @@ -1352,4 +1352,44 @@ class KohaErrorMessagesOperationTest extends KohaTestCase { $this->assertEquals(array('statut' => false, 'erreur' => 'Prolongation impossible : '.$message), $this->service->prolongerPret($this->_lafond, '24426')); } +} + + + +class KohaServiceLookupPatronByLoginTest extends KohaTestCase { + /** @test */ + public function serviceShouldProvideLookupPatronByLogin() { + $this->assertTrue($this->service->providesLookupPatronByLogin()); + } + + + /** @test */ + public function lookupUnknownPatronShouldReturnInvalidPatron() { + $this->mock_web_client + ->whenCalled('open_url') + ->with('http://cat-aficg55.biblibre.com/cgi-bin/koha/ilsdi.pl?service=LookupPatron&id=unknown') + ->answers('<?xml version="1.0" encoding="UTF-8" ?> +<LookupPatron> + <message>PatronNotFound</message> +</LookupPatron>'); + + $this->assertFalse($this->service->lookupPatronByLogin('unknown')->isValid()); + } + + + /** @test */ + public function lookupKnownPatronShouldReturnLaure() { + $this->mock_web_client + ->whenCalled('open_url') + ->with('http://cat-aficg55.biblibre.com/cgi-bin/koha/ilsdi.pl?service=LookupPatron&id=10002000') + ->answers(KohaFixtures::xmlLookupPatronLaure()) + + ->whenCalled('open_url') + ->with('http://cat-aficg55.biblibre.com/cgi-bin/koha/ilsdi.pl?service=GetPatronInfo&patron_id=572&show_contact=1&show_loans=1&show_holds=1') + ->answers(KohaFixtures::xmlGetPatronInfoLaure()); + + $patron = $this->service->lookupPatronByLogin('10002000'); + + $this->assertTrue($patron->isValid()); + } } \ No newline at end of file diff --git a/tests/library/ZendAfi/View/Helper/Admin/MenuGaucheAdminTest.php b/tests/library/ZendAfi/View/Helper/Admin/MenuGaucheAdminTest.php index b81b0e4aff3b49b100e7589b2dd060824957a7c4..64c32e9924bbfe346f4bc2191d0c820a1425a602 100644 --- a/tests/library/ZendAfi/View/Helper/Admin/MenuGaucheAdminTest.php +++ b/tests/library/ZendAfi/View/Helper/Admin/MenuGaucheAdminTest.php @@ -35,6 +35,8 @@ abstract class ZendAfi_View_Helper_Admin_MenuGaucheAdminTestCase extends ViewHel $this->helper->setView($this->view); ZendAfi_View_Helper_Admin_MenuGaucheAdminItem::setAcl(null); + Class_AdminVar::set('OPDS', 1); + Class_AdminVar::set('BIBNUM', 1); $this->html = $this->helper->Admin_ContentNav(); } @@ -60,7 +62,6 @@ class ZendAfi_View_Helper_Admin_MenuGaucheAdminVariableAsAdminTest public function _prepareFixtures() { parent::_prepareFixtures(); - $this->login(ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL); RessourcesNumeriquesFixtures::activateOrphea(); RessourcesNumeriquesFixtures::deactivateDilicom(); @@ -354,10 +355,20 @@ class ZendAfi_View_Helper_Admin_MenuGaucheAdminRightsTest extends ViewHelperTest $this->helper = new ZendAfi_View_Helper_Admin_ContentNav(); $this->helper->setView($this->view); ZendAfi_View_Helper_Admin_MenuGaucheAdminItem::setAcl(null); + Class_AdminVar::set('ACTIVITY', 1); Class_AdminVar::set('BIBNUM', 1); Class_AdminVar::set('SITO_IN_ALBUMS', 1); Class_AdminVar::set('CODIFICATION_BROWSER', 1); + Class_AdminVar::set('OAI_REPOSITORY', 1); + Class_AdminVar::set('CUSTOM_GENRE_ICON', 1); + Class_AdminVar::set('WEBSERVICE_TEST', 1); + Class_AdminVar::set('IMPORT_AVIS_OPAC2', 1); + Class_AdminVar::set('GENERATION_SITE', 1); + Class_AdminVar::set('CUSTOM_FIELDS_REPORT', 1); + Class_AdminVar::set('IMPORT_THESAURUS', 1); + Class_AdminVar::set('IMPORT_EAD', 1); + } diff --git a/tests/library/ZendAfi/View/Helper/AuthorAnchorTest.php b/tests/library/ZendAfi/View/Helper/AuthorAnchorTest.php index 96a803057163cf4a11a7c82c1040e83fb304f416..e2efa037f6f55e09a195ef27561e8c4dfd723046 100644 --- a/tests/library/ZendAfi/View/Helper/AuthorAnchorTest.php +++ b/tests/library/ZendAfi/View/Helper/AuthorAnchorTest.php @@ -27,6 +27,8 @@ class ZendAfi_View_Helper_AnchorAuthorSimpleTest extends ViewHelperTestCase { public function setup() { parent::setUp(); + Class_AdminVar::set('AUTHOR_PAGE', 0); + $brisson = $this->fixture('Class_CodifAuteur', ['id' => 10, 'libelle' => 'Stéphanie BRISSON', diff --git a/tests/library/ZendAfi/View/Helper/RenderLibraryOpeningTest.php b/tests/library/ZendAfi/View/Helper/RenderLibraryOpeningTest.php index eb33101c42a0a6abb95dfb1c861f8d0aaf8421fa..bf9195a6dddbde574ec85f0cacd5690f28b5e1ff 100644 --- a/tests/library/ZendAfi/View/Helper/RenderLibraryOpeningTest.php +++ b/tests/library/ZendAfi/View/Helper/RenderLibraryOpeningTest.php @@ -108,6 +108,63 @@ class ZendAfi_View_Helper_RenderLibraryOpeningOnMondayMorningTest extends ZendAf + +class ZendAfi_View_Helper_RenderLibraryOpeningSomeDaysClosedOnHolidaysTestTest extends ZendAfi_View_Helper_RenderLibraryOpeningTestCase { + public function setUp() { + parent::setUp(); + $timesource = new TimeSourceForTest('2018-12-21 11:00:00'); + ZendAfi_View_Helper_RenderLibraryOpening::setTimeSource($timesource); + Class_Ouverture_Visitor::setTimeSource($timesource); + + + $this->meythet + ->addOuverture($this->fixture('Class_Ouverture', + ['id' => 400, + 'horaires' => ['00:00', '00:00', '00:00', '00:00'], + 'jour_semaine' => Class_Ouverture::LUNDI, + 'id_site' => 4, + 'validity_start' => '2018-12-22', + 'validity_end' => '2019-01-06'])) + + + ->addOuverture($this->fixture('Class_Ouverture', + ['id' => 401, + 'horaires' => ['11:00', '12:00', '14:00', '18:00'], + 'jour_semaine' => Class_Ouverture::MARDI, + 'id_site' => 4, + 'validity_start' => '2018-12-22', + 'validity_end' => '2019-01-06'])); + } + + + + protected function _renderOpening($library) { + $helper = new ZendAfi_View_Helper_RenderLibrary(); + $helper->setView(new ZendAfi_Controller_Action_Helper_View()); + + return $helper->renderLibrary($library, ['fields' => Class_Systeme_ModulesAccueil_Library::FIELD_OPEN_CLOSE . ';' . Class_Systeme_ModulesAccueil_Library::FIELD_OPENING_HOURS]); + } + + + /** @test */ + public function meythetShouldReopenOnTuesdayAtEleven() { + $this->assertXPathContentContains($this->_renderOpening($this->meythet), + '//p[@class="closed"]', + utf8_encode('Fermé. Réouverture Mardi à 11:00')); + } + + + /** @test */ + public function holidaysOpeningsShouldContainsMondayClosed() { + $this->assertXPathContentContains($this->_renderOpening($this->meythet), + '//div[@class="field-opening-hours"]//ul/li[2]//li', + utf8_encode('Lundi : fermé')); + } +} + + + + class ZendAfi_View_Helper_RenderLibraryOpeningHolidaysTest extends ZendAfi_View_Helper_RenderLibraryOpeningTestCase { /** @test */ diff --git a/tests/library/ZendAfi/View/Helper/SuggestsTest.php b/tests/library/ZendAfi/View/Helper/SuggestsTest.php index a886184925ac2850c3483dde8beba3ebfecc3a8d..8a953d75bda8642eb59dea18406ed82a3cc56edf 100644 --- a/tests/library/ZendAfi/View/Helper/SuggestsTest.php +++ b/tests/library/ZendAfi/View/Helper/SuggestsTest.php @@ -29,6 +29,8 @@ class ZendAfi_View_Helper_SuggestsTest extends ViewHelperTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('AUTHOR_PAGE', 0); + $this->fixture('Class_CodifAuteur', ['id' => 43, 'libelle' => 'Pomme d\'API']); @@ -112,5 +114,3 @@ class ZendAfi_View_Helper_SuggestsTest extends ViewHelperTestCase { } } - -?> \ No newline at end of file diff --git a/tests/phpunit.xml b/tests/phpunit.xml index 72f26a4c9cd6b6f766a2c2c0e698a6bbb9d040ca..364222cea41c840538c00a3a4ac5362be28bf4c2 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -7,12 +7,10 @@ stopOnError="false" > <testsuites> - <testsuite name="ApplicationTestSuite"> + <testsuite name="Bokeh scenario, application, library and digital resources"> <directory>./scenarios/</directory> <directory>./application/</directory> <directory>./library/</directory> - </testsuite> - <testsuite name="DigitalResourcesTestSuite"> <directory>../library/digital_resources/</directory> </testsuite> </testsuites> @@ -35,6 +33,6 @@ </whitelist> </filter> <listeners> - <listener file = "./TestSpeedTrap.php" class="TestSpeedTrap"/> + <listener file="./TestSpeedTrap.php" class="TestSpeedTrap"/> </listeners> </phpunit> diff --git a/tests/phpunit_db.xml b/tests/phpunit_db.xml index 98eae1b422c625033031e48e5343498b97c1a6e7..d304e16455683964ded110128608831163053302 100644 --- a/tests/phpunit_db.xml +++ b/tests/phpunit_db.xml @@ -7,7 +7,7 @@ stopOnError="false" > <testsuites> - <testsuite name="DBTestSuite"> + <testsuite name="Bokeh database migrations"> <directory>./db/</directory> </testsuite> </testsuites> diff --git a/tests/phpunit_js.xml b/tests/phpunit_js.xml index cb78ead1e0145a7b4461dcc8b63f8ed257de34ea..b11558c2100918dae468a570f2795d06b1c8c0b6 100644 --- a/tests/phpunit_js.xml +++ b/tests/phpunit_js.xml @@ -7,7 +7,7 @@ stopOnError="false" > <testsuites> - <testsuite name="JSTestSuite"> + <testsuite name="Bokeh JavaScript components"> <directory>./js/</directory> </testsuite> </testsuites> diff --git a/tests/scenarios/AdvancedSearch/AdminConfigurationTest.php b/tests/scenarios/AdvancedSearch/AdminConfigurationTest.php index ae828b91d92eca5e8f82443b34d8dc4512028071..252cc063c5de409862d6ecbdfc52a8b6db5179fc 100644 --- a/tests/scenarios/AdvancedSearch/AdminConfigurationTest.php +++ b/tests/scenarios/AdvancedSearch/AdminConfigurationTest.php @@ -20,7 +20,7 @@ */ -class AdvancedSearch_AdminConfigurationUnactiveTest extends Admin_AbstractControllerTestCase { +class AdvancedSearch_AdminConfigurationUnactiveTest extends Admin_AbstractControllerTestCase { protected $_storm_default_to_volatile = true; public function setUp() { @@ -29,12 +29,6 @@ class AdvancedSearch_AdminConfigurationUnactiveTest extends Admin_AbstractCont } - public function tearDown() { - ZendAfi_View_Helper_Admin_MenuGaucheAdminItem::setAcl(null); - parent::tearDown(); - } - - /** @test */ public function menuAdvancedFormShouldBeDisplayed() { $this->dispatch('/admin'); @@ -64,12 +58,6 @@ abstract class AdvancedSearch_ActiveTestCase extends Admin_AbstractControllerTes 'visible' => true ]); } - - - public function tearDown() { - ZendAfi_View_Helper_Admin_MenuGaucheAdminItem::setAcl(null); - parent::tearDown(); - } } diff --git a/tests/scenarios/AdvancedSearch/AdvancedSearchTest.php b/tests/scenarios/AdvancedSearch/AdvancedSearchTest.php index 80463ec061eae7dd9b08ad118bb348e0cdc256da..2f6b309de68fe073ba04a431ca9bd283e72d7573 100644 --- a/tests/scenarios/AdvancedSearch/AdvancedSearchTest.php +++ b/tests/scenarios/AdvancedSearch/AdvancedSearchTest.php @@ -414,8 +414,7 @@ class AdvancedSearchForbiddenCallCustomFormSelectedTest -class AdvancedSearchValidCustomFormSelectedNotPublishedTest - extends AdvancedSearchCustomFormSelectedTestCase { +class AdvancedSearchFormWithDateSelectorsTest extends AdvancedSearchCustomFormSelectedTestCase { protected function _prepareFixtures() { parent::_prepareFixtures(); @@ -423,6 +422,61 @@ class AdvancedSearchValidCustomFormSelectedNotPublishedTest $form_filename = 'userfiles/forms/form.php'; $this->fixture('Class_SearchForm', ['id' => 3, 'filename' => $form_filename]); + $this->fixture('Class_CodifThesaurus', + ['id' => 1, + 'libelle' => 'Année de publication', + 'id_thesaurus' => 'APUB', + 'id_origine' => null, + 'code' => 'APUB', + 'rule_zone' => '995', + 'rule_label_field' => 'w', + 'rule_label_start_pos' => 1, + 'rule_label_length' => 4 + ]); + + + $this->fixture('Class_CodifThesaurus', + ['id' => 2, + 'libelle' => 'Mois de publication', + 'id_thesaurus' => 'MPUB', + 'id_origine' => null, + 'code' => 'MPUB', + 'rule_zone' => '995', + 'rule_label_field' => 'w', + 'rule_label_start_pos' => 6, + 'rule_label_length' => 2 + ]); + + $this->fixture('Class_CodifThesaurus', + ['id' => 3, + 'libelle' => 'Jour de publication', + 'id_thesaurus' => 'JPUB', + 'id_origine' => null, + 'code' => 'JBUB', + 'rule_zone' => '995', + 'rule_label_field' => 'w', + 'rule_label_start_pos' => 9, + 'rule_label_length' => 2 + ]); + + + $this->fixture('Class_CodifThesaurus', + ['id' => 34, + 'libelle' => '3', + 'id_thesaurus' => 'JPUB0003', + 'id_origine' => null, + 'code' => 'JPUB', + ]); + + $this->fixture('Class_CodifThesaurus', + ['id' => 35, + 'libelle' => '1', + 'id_thesaurus' => 'JPUB0001', + 'id_origine' => null, + 'code' => 'JPUB', + ]); + + $file_system = $this->mock() ->whenCalled('directoryAt')->with($form_filename)->answers(false) ->whenCalled('fileAt')->with($form_filename) @@ -435,11 +489,7 @@ class AdvancedSearchValidCustomFormSelectedNotPublishedTest ->setParentPath('userfiles/forms') ->setWritable(true)) ->whenCalled('getContent')->with($form_filename) - ->answers('<?php -$form - ->addElement(\'text\', \'my_super_input\', [\'label\' => \'so good\']) - ->addUniqDisplayGroup(\'yeah\') - ;') + ->answers('<?php ?>') ; Class_FileManager::setFileSystem($file_system); @@ -447,21 +497,37 @@ $form function($path, $form) { $form ->addElement('text', 'my_super_input', ['label' => 'so good']) - ->addUniqDisplayGroup('yeah') - ; + ->addElement('selectDynamicFacet', 'annee', ['label' => 'this should not break']) + ->addElement('selectDynamicFacet', 'rech_HAPUB', ['label' => 'année de publication']) + ->addElement('selectDynamicFacet', 'rech_HMPUB', ['label' => 'mois de publication']) + ->addElement('selectDynamicFacet', 'rech_HJPUB', ['label' => 'jour de publication']) + ->addUniqDisplayGroup('yeah'); }); } /** @test */ public function mySuperInputShouldBePresent() { - $this->assertXPath('//input[@name="my_super_input"]', $this->_response->getBody()); + $this->assertXPath('//input[@name="my_super_input"]'); + } + + + /** @test */ + public function daySelectorFirstOptionShouldBeEmpty() { + $this->assertXPath('//select[@name="rech_HJPUB"]/option[@value=""]'); + } + + + /** @test */ + public function daySelectorShouldIncludeOptionForDayOne() { + $this->assertXPath('//select[@name="rech_HJPUB"]/option[@value="1"]'); } /** @test */ - public function notPublishedMessageShouldBePresent() { - $this->assertXPathContentContains('//p[@class="error"]', 'Ce formulaire n\'est pas visible.'); + public function dayThreeShouldBePresentAfterDayOne() { + $this->assertXPathContentContains('//select[@name="rech_HJPUB"]/option[@value="3"][preceding-sibling::option[@value="1"]]', + '3'); } } @@ -717,7 +783,8 @@ class AdvancedSearchMultiFacetsPostDispatchTest extends Admin_AbstractController 'id_thesaurus' => 'DOCU', 'id_origine' => null, 'code' => 'DOCU', - 'rules' => '{"label":" 99$t "}']); + 'rule_zone' => '995', + 'rule_label_field' => 't']); $this->fixture('Class_CodifThesaurus', ['id' => 4, @@ -726,7 +793,8 @@ class AdvancedSearchMultiFacetsPostDispatchTest extends Admin_AbstractController 'id_thesaurus' => 'DOCU0001', 'id_origine' => null, 'code' => 'DOCU', - 'rules' => '{"label":" 99$t "}']); + 'rule_zone' => '999', + 'rule_label_field' => 't']); } diff --git a/tests/scenarios/AlbumAudioRecord/AlbumAudioRecordTest.php b/tests/scenarios/AlbumAudioRecord/AlbumAudioRecordTest.php index 62346993881234d840702db0c697f62f27aecc22..ba38b9c6ebc4387685f3bfe91f7a1624ebe08197 100644 --- a/tests/scenarios/AlbumAudioRecord/AlbumAudioRecordTest.php +++ b/tests/scenarios/AlbumAudioRecord/AlbumAudioRecordTest.php @@ -117,6 +117,8 @@ class AlbumAudioRecordViewNoticeTest extends AlbumAudioRecordTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('AUTHOR_PAGE', 0); + $this->mock_sql = $this->mock() ->whenCalled('execute')->answers('') ->whenCalled('fetchOne')->answers(null) @@ -295,6 +297,7 @@ class AlbumAudioRecordViewMorceauxTest extends AlbumAudioRecordTestCase { class AlbumAudioRecordViewDetailsTest extends AlbumAudioRecordTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('AUTHOR_PAGE', 0); $this->dispatch('/opac/noticeajax/detail/id_notice/'.$this->_notice->getId(), true); } diff --git a/tests/scenarios/Authorities/AuthoritiesTest.php b/tests/scenarios/Authorities/AuthoritiesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..49a133afd7b9cb66509a5f59cbd3468311afd487 --- /dev/null +++ b/tests/scenarios/Authorities/AuthoritiesTest.php @@ -0,0 +1,391 @@ +<?php +/** + * Copyright (c) 2012-2018, 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 AuthoritiesTestCase extends AbstractControllerTestCase { + protected + $_storm_default_to_volatile = true; + + public function setup() { + parent::setup(); + ZendAfi_Auth::getInstance()->clearIdentity(); + + $this->fixture('Class_Notice', + ['id' => 1, + 'type_doc' => 'j', + 'annee' => '2017', + 'type' => Class_Notice::TYPE_AUTHORITY, + 'facettes' => 'HMOTS HMOTS0001', + 'unimarc' => file_get_contents(__DIR__ . '/developpement_local.mrc')]); + + $this->fixture('Class_Exemplaire', + ['id' => 999, + 'type' => Class_Notice::TYPE_AUTHORITY, + 'id_origine' => '185611', + 'id_notice' => 1]); + } +} + + + +class AuthoritiesRechercheControllerViewNoticeAuthoritySimpleTest extends AuthoritiesTestCase { + /** @test */ + public function titleShouldBeDeveloppementLocal() { + $this->dispatch('/recherche/viewnotice/id/1'); + $this->assertXpathContentContains('//h1', 'Développement local'); + } + + + /** @test */ + public function withAuthorPageShouldNotHaveError() { + Class_AdminVar::set('AUTHOR_PAGE', 1); + $this->dispatch('/recherche/viewnotice/id/1'); + } +} + + + +class AuthoritiesRechercheControllerViewNoticeWithAuthorityIdAndThesaurusIdTest extends AuthoritiesTestCase { + /** @test */ + public function shouldRedirectToViewNoticeIdOne() { + $this->dispatch('/recherche/viewnotice/authority_id/185611/thesaurus_id/MOTS'); + $this->assertRedirectTo('/opac/recherche/viewnotice/id/1'); + } +} + + + +class AuthoritiesNoticeAjaxControllerTest extends AuthoritiesTestCase { + public function setUp() { + parent::setUp(); + + $this->fixture('Class_Exemplaire', + ['id' => 67, + 'type' => Class_Notice::TYPE_AUTHORITY, + 'id_origine' => '185349', + 'id_notice' => 2]); + + $this->fixture('Class_Exemplaire', + ['id' => 68, + 'type' => Class_Notice::TYPE_AUTHORITY, + 'id_origine' => '189260', + 'id_notice' => 3]); + + $records = array_fill(0, 22, [1, '']); + + Zend_Registry::set('sql', + $this->mock() + ->whenCalled('fetchAll')->answers($records)); + + $this->dispatch('/noticeajax/detail/id/1'); + } + + + /** @test */ + public function genericAmenagementDuTerritoireShouldBePresent() { + $this->assertXPathContentContains('//h3', utf8_encode('Terme générique')); + $this->assertXPathContentContains('//li/a[contains(@href, "/recherche/viewnotice/id/2")]', + utf8_encode('Aménagement du territoire')); + } + + + /** @test */ + public function specificContratDePaysShouldBePresent() { + $this->assertXPathContentContains('//h3', utf8_encode('Terme spécifique')); + $this->assertXPathContentContains('//li/a[contains(@href, "/recherche/viewnotice/id/3")]', + 'Contrat de pays'); + } + + + /** @test */ + public function rejectDLShouldBePresent() { + $this->assertXPathContentContains('//h3', utf8_encode('Terme rejeté')); + $this->assertXPathContentContains('//li', 'DL'); + } + + + /** @test */ + public function linkedActeurLocalEncoreShouldBePresent() { + $this->assertXPathContentContains('//h3', utf8_encode('Terme associé')); + $this->assertXPathContentContains('//li', 'Acteur local encore'); + } + + + /** @test */ + public function noteShouldBePresent() { + $this->assertXPathContentContains('//h3', 'Note d\'application'); + $this->assertXPathContentContains('//p', 'S\'utilise lorsque le besoin'); + } + + + /** @test */ + public function usageLinkShouldBePresent() { + $this->assertXPathContentContains('//a[contains(@href, "HMOTS0001")]', + utf8_encode('Utilisé dans 22 notices')); + } +} + + + + +class AuthoritiesBibliographicDynamicFacetsWithoutIndexSystemTest extends ModelTestCase { + protected $_thesaurus; + + public function setUp() { + parent::setUp(); + + $this->fixture('Class_CodifThesaurus', + ['id' => 6, + 'libelle' => 'Mots-clés TESS', + 'id_thesaurus' => 'MOTS', + 'id_origine' => null, + 'code' => 'MOTS', + 'rule_zone' => '619', + 'rule_label_field' => 'a', + 'rule_id_field' => '9']); + + $thesauri = (new Class_Cosmogramme_Integration_Record_BibliographicDynamicFacets()) + ->thesauriOf((new Class_NoticeUnimarc())->setNotice(file_get_contents(__DIR__ . '/vagabond.mrc')), + $this->fixture('Class_IntBib', ['id' => 3])); + $this->_thesaurus = reset($thesauri); + } + + + /** @test */ + public function thesaurusIdShouldBeMots0001() { + $this->assertEquals('MOTS0001', $this->_thesaurus->getIdThesaurus()); + } + + + /** @test */ + public function thesaurusLabelShouldBeManga() { + $this->assertEquals('Manga', $this->_thesaurus->getLibelle()); + } + + + /** @test */ + public function shouldNotCreateAuthorityRecord() { + $this->assertEmpty(Class_Notice::findAllBy(['type' => Class_Notice::TYPE_AUTHORITY])); + } +} + + + + +class AuthoritiesBibliographicDynamicFacetsWithIndexSystemNotExistingTest extends ModelTestCase { + protected + $_thesaurus, + $_authority; + + public function setUp() { + parent::setUp(); + + $this->fixture('Class_CodifThesaurus', + ['id' => 6, + 'libelle' => 'Mots-clés TESS', + 'id_thesaurus' => 'MOTS', + 'id_origine' => null, + 'code' => 'MOTS', + 'rule_zone' => '619', + 'rule_label_field' => 'a', + 'rule_id_field' => '9']); + + $attributs = [[Class_IntProfilDonnees::PROFILE_INDEX_SYSTEMS_FIELDS + => [['rule' => '', + 'system' => 'TESS', + 'default_type' => 'j', + 'thesaurus' => '6']]]]; + + $this->fixture('Class_IntProfilDonnees', + ['id' => 1004, + 'libelle' => 'Authorities', + 'type_fichier' => Class_IntProfilDonnees::FT_AUTHORITY, + 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'accents' => Class_IntProfilDonnees::ENCODING_UTF8, + 'attributs' => serialize($attributs), + ]); + + Class_Notice_AuthorityPartial::setTimeSource(new TimeSourceForTest('2018-12-12')); + + $thesauri = (new Class_Cosmogramme_Integration_Record_BibliographicDynamicFacets()) + ->thesauriOf((new Class_NoticeUnimarc())->setNotice(file_get_contents(__DIR__ . '/vagabond.mrc')), + $this->fixture('Class_IntBib', ['id' => 3])); + + $this->_thesaurus = reset($thesauri); + $this->_authority = Class_Notice::findFirstBy(['type' => Class_Notice::TYPE_AUTHORITY]); + } + + + public function tearDown() { + Class_Notice_AuthorityPartial::setTimeSource(null); + parent::tearDown(); + } + + + /** @test */ + public function thesaurusIdShouldBeMots0001() { + $this->assertEquals('MOTS0001', $this->_thesaurus->getIdThesaurus()); + } + + + /** @test */ + public function thesaurusLabelShouldBeManga() { + $this->assertEquals('Manga', $this->_thesaurus->getLibelle()); + } + + + /** @test */ + public function authorityTypeShouldBeSubject() { + $this->assertEquals('j', $this->_authority->getTypeDoc()); + } + + + /** @test */ + public function authorityShouldHaveThesaurusFacet() { + $this->assertContains('HMOTS0001', $this->_authority->getFacetCodes()); + } + + + /** @test */ + public function authority001ShouldBe213399() { + $this->assertEquals('213399', $this->_authority->get_subfield('001')[0]); + } + + + /** @test */ + public function authority100DollarAShouldContainsCurrentDate() { + $this->assertContains('20181212', $this->_authority->get_subfield('100', 'a')[0]); + } + + + /** @test */ + public function authority152DollarBShouldBeTess() { + $this->assertEquals('TESS', $this->_authority->get_subfield('152', 'b')[0]); + } + + + /** @test */ + public function authority250DollarAShouldBeManga() { + $this->assertEquals('Manga', $this->_authority->get_subfield('250', 'a')[0]); + } + + + /** @test */ + public function authority801DollarBShouldBeBokeh() { + $this->assertEquals('Bokeh', $this->_authority->get_subfield('801', 'b')[0]); + } + + + /** @test */ + public function authorityItemIdOrigineShouldBe213399() { + $this->assertEquals('213399', $this->_authority->getExemplaires()[0]->getIdOrigine()); + } + + + /** @test */ + public function authorityItemIntBibShouldBe3() { + $this->assertEquals('3', $this->_authority->getExemplaires()[0]->getIdIntBib()); + } +} + + + +class AuthoritiesBibliographicDynamicFacetsWithIndexSystemAlreadyExistingTest extends ModelTestCase { + protected + $_thesaurus, + $_authority; + + public function setUp() { + parent::setUp(); + + $this->fixture('Class_CodifThesaurus', + ['id' => 6, + 'libelle' => 'Mots-clés TESS', + 'id_thesaurus' => 'MOTS', + 'id_origine' => null, + 'code' => 'MOTS', + 'rule_zone' => '619', + 'rule_label_field' => 'a', + 'rule_id_field' => '9']); + + $attributs = [[Class_IntProfilDonnees::PROFILE_INDEX_SYSTEMS_FIELDS + => [['rule' => '', + 'system' => 'TESS', + 'default_type' => 'j', + 'thesaurus' => '6']]]]; + + $this->fixture('Class_IntProfilDonnees', + ['id' => 1004, + 'libelle' => 'Authorities', + 'type_fichier' => Class_IntProfilDonnees::FT_AUTHORITY, + 'format' => Class_IntProfilDonnees::FORMAT_UNIMARC, + 'accents' => Class_IntProfilDonnees::ENCODING_UTF8, + 'attributs' => serialize($attributs), + ]); + + $this->fixture('Class_Notice', ['id' => 14, + 'type' => Class_Notice::TYPE_AUTHORITY, + 'type_doc' => 'j', + 'facettes' => 'HMOTS']); + + $this->fixture('Class_Exemplaire', ['id' => 145, + 'type' => Class_Notice::TYPE_AUTHORITY, + 'id_origine' => 213399, + 'id_int_bib' => 5, + 'notice' => Class_Notice::find(14)]); + + $thesauri = (new Class_Cosmogramme_Integration_Record_BibliographicDynamicFacets()) + ->thesauriOf((new Class_NoticeUnimarc())->setNotice(file_get_contents(__DIR__ . '/vagabond.mrc')), + $this->fixture('Class_IntBib', ['id' => 3])); + + $this->_thesaurus = reset($thesauri); + } + + + /** @test */ + public function thesaurusIdShouldBeMots0001() { + $this->assertEquals('MOTS0001', $this->_thesaurus->getIdThesaurus()); + } + + + /** @test */ + public function thesaurusLabelShouldBeManga() { + $this->assertEquals('Manga', $this->_thesaurus->getLibelle()); + } + + + /** @test */ + public function authorityShouldNotBeCreated() { + $this->assertEquals(1, Class_Notice::countBy(['type' => Class_Notice::TYPE_AUTHORITY])); + } + + + /** @test */ + public function authorityItemShouldNotBeCreated() { + $this->assertEquals(1, Class_Notice::find(14)->numberOfExemplaires()); + } + + + /** @test */ + public function authorityShouldHaveThesaurusFacet() { + $this->assertContains('HMOTS0001', Class_Notice::find(14)->getFacetCodes()); + } +} diff --git a/tests/scenarios/Authorities/developpement_local.mrc b/tests/scenarios/Authorities/developpement_local.mrc new file mode 100644 index 0000000000000000000000000000000000000000..9a3ff37b812d0f2bb1ae624afa6c0820b6ad6ac4 --- /dev/null +++ b/tests/scenarios/Authorities/developpement_local.mrc @@ -0,0 +1 @@ +00634 a2200205 450000500170000010000290001715200090004625000250005533000490008045000100012955000420013955000310018155000460021255000310025855000440028955000280033355000270036199900330038800100070042120171128140028.0 a20170831afrey50 ba0 bTESS aDéveloppement local aS'utilise lorsque le besoin s'en fait sentir 5zaDL 31853495gaAménagement du territoire 31892605haContrat de pays 31902545haSchéma de services collectifs 31911505haContrat de site 31888965haAide au développement local 31889335haActeur local 5zaActeur local encore 9tess:TESS/DEVELOPPEMENTLOCAL185611 \ No newline at end of file diff --git a/tests/scenarios/Authorities/vagabond.mrc b/tests/scenarios/Authorities/vagabond.mrc new file mode 100644 index 0000000000000000000000000000000000000000..f4d084d69a639e1ce0a4f450930ae8b33888f4d3 --- /dev/null +++ b/tests/scenarios/Authorities/vagabond.mrc @@ -0,0 +1 @@ +01499nam 2200361 4500001000400000003004700004010004700051020001700098021002000115039001900135090000800154091001900162099001300181100004100194101000800235102000700243105001800250106000600268200017600274210005600450215009700506461003300603610001000636619001800646676001000664700007200674702005000746702006100796702004000857801007000897930002900967995014100996869http://catalogue.bnf.fr/ark:/12148/cb37710769n a2-84580-144-0bbr.dPrix : 59 F : 8,99 EUR aFRb00201411 aFRbDL 01-54100 oOPLa027037083 a869 b20140822c1a2 eUZELtBD a20020103d2001 m y0frey50 ba1 afre aFR aa t 00|a| ar1 aVagabondbTexte impriméh4fTakehiko Inouégd'après l'oeuvre d'Eiji Yoshikawa, "Miyamoto Musashi"g[trad. du japonais par Jacques Lalloz]g[adapté par Philippe Marcel] aPariscÉd. Tonkamd2001e35-RennesgImpr. Oberthur aNon paginé [ca 206] p.cill. en noir et en coul., couv. ill., jaquette ill. en coul.d19 cm 0tVagabondv4aTakehiko Inoué aManga aManga9213399 a741.5 313527612935oISNI0000000121039965aInouebTakehikof1967-....4070 311929525936aYoshikawabEijif1892-19624100 312040286937oISNI0000000108815456aLallozbJacques4730 312320807938aMarcelbPhilippe4010 0aFRbFR-751131015c20020103gAFNORhFRBNF3771076900000002intermrc 5FR-751131010:2003-196584 fSTJ000095w2014-06-2630009117cMTRSTJ20kBD VAG 452012-09-07o0efiction adulte bande dessineesddcrBDm2014-06-19bMTRSTJ6MTRSTJ \ No newline at end of file diff --git a/tests/scenarios/SearchResult/SearchResultTest.php b/tests/scenarios/SearchResult/SearchResultTest.php index 007fe253fc6cf59b965e5fe8a1ffdfbe5665d41d..f68ffb45827511552d1e8774a69652c1f54750c9 100644 --- a/tests/scenarios/SearchResult/SearchResultTest.php +++ b/tests/scenarios/SearchResult/SearchResultTest.php @@ -252,7 +252,8 @@ class SearchResultWithDynamicFacetTest extends AbstractControllerTestCase { 'id_thesaurus' => 'DOCU', 'id_origine' => null, 'code' => 'DOCU', - 'rules' => '{"label":" 99$t "}']); + 'rule_zone' => '995', + 'rule_label_field' => 't']); $this->fixture('Class_CodifThesaurus', ['id' => 4, @@ -261,7 +262,8 @@ class SearchResultWithDynamicFacetTest extends AbstractControllerTestCase { 'id_thesaurus' => 'DOCU0001', 'id_origine' => null, 'code' => 'DOCU', - 'rules' => '{"label":" 99$t "}']); + 'rule_zone' => '995', + 'rule_label_field' => 't']); } diff --git a/tests/scenarios/Thesauri/ThesauriTest.php b/tests/scenarios/Thesauri/ThesauriTest.php index 51b032fc48b56363e8fe02e5852ec872806b3d68..3a5b4799466be5b7bb8260572c2ec13298aeef61 100644 --- a/tests/scenarios/Thesauri/ThesauriTest.php +++ b/tests/scenarios/Thesauri/ThesauriTest.php @@ -38,7 +38,8 @@ abstract class ThesauriTestCase extends Admin_AbstractControllerTestCase { 'id_thesaurus' => 'DOCU', 'id_origine' => null, 'code' => 'DOCU', - 'rules' => '{"label":" 99$t "}']); + 'rule_zone' => '099', + 'rule_label_field' => 't']); $this->_sifi = $this->fixture('Class_CodifThesaurus', ['id' => 4, @@ -85,8 +86,8 @@ class ThesauriIndexTest extends ThesauriTestCase { /** @test */ - public function rules99DollarTShouldBeDisplay() { - $this->assertXpathContentContains('//table', '99$t'); + public function rulesShouldBeDisplay() { + $this->assertXpathContentContains('//td', '{"LabelStartPos":1,"LabelLength":0,"Zone":"099","LabelField":"t"}'); } @@ -132,11 +133,9 @@ class ThesauriIndexChildrenTest extends ThesauriTestCase { /** @test */ - public function rules99DollarTShouldBeDisplay() { - $this->assertXpathContentContains('//table', '99$t'); + public function parentRulesShouldBeDisplay() { + $this->assertXpathContentContains('//table', '{"LabelStartPos":1,"LabelLength":0,"Zone":"099","LabelField":"t"',$this->_response->getBody()); } - - } @@ -238,6 +237,6 @@ class ThesauriEditTest extends ThesauriTestCase { /** @test */ public function thesauriShouldNotHaveBeenUpdated() { $this->postDispatch('/admin/thesauri/edit/id/3', ['rules' => 'brave']); - $this->assertEmpty(Class_CodifThesaurus::find(3)->getRuleslabel()); + $this->assertEquals('099', Class_CodifThesaurus::find(3)->getRuleZone()); } } \ No newline at end of file