diff --git a/FEATURES/104332 b/FEATURES/104332 new file mode 100644 index 0000000000000000000000000000000000000000..5b329a5eb2b027425da0a8c00574440c24815950 --- /dev/null +++ b/FEATURES/104332 @@ -0,0 +1,10 @@ + '104332' => + ['Label' => $this->_('Tableau des prêts PNB : ajout des genres et sections, sélection multiple'), + 'Desc' => $this->_('Tableau des prêts PNB : possibilité d\'afficher les genres et sections. Sélection multiple possible d\'album'), + 'Image' => '', + 'Video' => '', + 'Category' => '', + 'Right' => function($feature_description, $user) {return true;}, + 'Wiki' => 'http://wiki.bokeh-library-portal.org/index.php?title=Configuration_du_PNB_Dilicom#Tableau_de_bord', + 'Test' => '', + 'Date' => '2021-01-14'], \ No newline at end of file diff --git a/FEATURES/116562 b/FEATURES/116562 new file mode 100644 index 0000000000000000000000000000000000000000..b9bed85a8506c8b5ec7efb504cf2539e0c7367fa --- /dev/null +++ b/FEATURES/116562 @@ -0,0 +1,10 @@ + '116562' => + ['Label' => $this->_('Fournisseur de vignettes'), + 'Desc' => $this->_('Bokeh permet de spécifier les informations permettant l\'accès au service Electre REST API version 2'), + 'Image' => '', + 'Video' => '', + 'Category' => $this->_('Enrichissements'), + 'Right' => function($feature_description, $user) {return true;}, + 'Wiki' => 'http://wiki.bokeh-library-portal.org/index.php?title=Vignette#Fournisseur_de_vignettes', + 'Test' => '', + 'Date' => '2021-01-28'], \ No newline at end of file diff --git a/FEATURES/125727 b/FEATURES/125727 new file mode 100644 index 0000000000000000000000000000000000000000..2443168d39bcb49d5a9dce81f57b67bdbcfbce75 --- /dev/null +++ b/FEATURES/125727 @@ -0,0 +1,10 @@ + '125727' => + ['Label' => $this->_('Facette nouveauté en résultat de recherche'), + 'Desc' => $this->_('Ajout de la possibilité d\'afficher une facette "Nouveauté" oui/non basée sur la date de nouveauté la plus élevée parmis tous les exemplaires'), + 'Image' => '', + 'Video' => '', + 'Category' => $this->_('Recherche'), + 'Right' => function($feature_description, $user) {return true;}, + 'Wiki' => 'http://wiki.bokeh-library-portal.org/index.php?title=Facette_%27Nouveaut%C3%A9%27', + 'Test' => '', + 'Date' => '2021-01-14'], \ No newline at end of file diff --git a/VERSIONS_WIP/104332 b/VERSIONS_WIP/104332 new file mode 100644 index 0000000000000000000000000000000000000000..c285b1a43d58b5c56fdd656f448160ac64994407 --- /dev/null +++ b/VERSIONS_WIP/104332 @@ -0,0 +1 @@ + - ticket #104332 : Tableau des prêts PNB : ajout des genres et sections, sélection multiple \ No newline at end of file diff --git a/VERSIONS_WIP/116562 b/VERSIONS_WIP/116562 new file mode 100644 index 0000000000000000000000000000000000000000..6c5659d5b8883ce754ff297bff4416b7ceab306f --- /dev/null +++ b/VERSIONS_WIP/116562 @@ -0,0 +1 @@ + - ticket #116562 : Enrichissements : Ajout de la possibilité de définir les accès aux fournisseur de notices Electre Rest APIv2 pour récupération des vignettes \ No newline at end of file diff --git a/VERSIONS_WIP/124826 b/VERSIONS_WIP/124826 new file mode 100644 index 0000000000000000000000000000000000000000..339d10ff93d00b8c1c7fa971d04128921fed7851 --- /dev/null +++ b/VERSIONS_WIP/124826 @@ -0,0 +1 @@ + - ticket #124826 : Activités : Ajout de l'age maximum des enfants, ajout d'un envoi courriel de rappel par session d'activité, ajout de l'heure de début et de fin \ No newline at end of file diff --git a/VERSIONS_WIP/125727 b/VERSIONS_WIP/125727 new file mode 100644 index 0000000000000000000000000000000000000000..d3e051728ca258acc59923c01351521fcb5211ef --- /dev/null +++ b/VERSIONS_WIP/125727 @@ -0,0 +1 @@ + - ticket #125727 : Résultat de recherche : Ajout de la possibilité d'afficher une facette "Nouveauté" oui/non basée sur la date de nouveauté la plus élevée parmis tous les exemplaires \ No newline at end of file diff --git a/application/modules/admin/controllers/SessionActivityController.php b/application/modules/admin/controllers/SessionActivityController.php index 83253ce498c9622377717a8fa730ca81c6ab7809..2866d07ff0a869951c9896152eaf783eb952647f 100644 --- a/application/modules/admin/controllers/SessionActivityController.php +++ b/application/modules/admin/controllers/SessionActivityController.php @@ -53,21 +53,13 @@ class Admin_SessionActivityController extends ZendAfi_Controller_Action { ->addColumn('', 'value') ; - $content = $this->view - ->renderCsv($description, - [new Class_Entity(['Label' => $this->_('Activité'), - 'Value' => $session->getLibelleActivity()]), - new Class_Entity(['Label' => $this->_('Session'), - 'Value' => $this->view->humanDate($session->getDateDebut(), - 'd MMMM YYYY')]), - new Class_Entity(['Label' => $this->_('Durée'), - 'Value' => $session->getDuree() . 'h']), - new Class_Entity(['Label' => $this->_('Effectif'), - 'Value' => $session->getAttendeesMin() - . '-' . $session->getAttendeesMax()])]); + $content = $this->view->renderCsv($description, $session->getMetaDatas()); + + $description = (new Class_TableDescription_SessionActivityInscriptionsExport('')) + ->setAgeChildMax($session->getAgeChildMax()); $content .= "\n" - . $this->view->renderCsv((new Class_TableDescription_SessionActivityInscriptionsExport('')), + . $this->view->renderCsv($description, $session->getInscriptionsSortedByName()); $this->_helper->csv(sprintf('session_%d.csv', $session->getId()), diff --git a/cosmogramme/sql/patch/patch_396.php b/cosmogramme/sql/patch/patch_396.php new file mode 100644 index 0000000000000000000000000000000000000000..d127800ac629e9d5648192da4edc85c4519c193c --- /dev/null +++ b/cosmogramme/sql/patch/patch_396.php @@ -0,0 +1,19 @@ +<?php + +$adapter = Zend_Db_Table_Abstract::getDefaultAdapter(); + +try { + $adapter->query('ALTER TABLE `session_activity` ' + . 'ADD COLUMN `age_child_max` int(11) unsigned not null default 0,' + . 'ADD COLUMN `all_day` tinyint(1) unsigned not null default 1,' + . 'MODIFY `date_debut` datetime,' + . 'MODIFY `date_fin` datetime' + ); +} catch(Exception $e) {} + +try { + $adapter->query('ALTER TABLE `session_activity_inscriptions` ' + . 'ADD COLUMN `notified_at` datetime,' + . 'ADD KEY `notified_at` (`notified_at`)' + ); +} catch(Exception $e) {} diff --git a/cosmogramme/tests/php/classes/KohaPeriodiquesTest.php b/cosmogramme/tests/php/classes/KohaPeriodiquesTest.php index aa9e530cf645174aef5287228255c20b5f92f3de..6a0917953eeb48d8dadd20591485c828708d7ac5 100644 --- a/cosmogramme/tests/php/classes/KohaPeriodiquesTest.php +++ b/cosmogramme/tests/php/classes/KohaPeriodiquesTest.php @@ -659,7 +659,7 @@ class KohaPeriodiquesMatriculeAngesTest extends KohaPeriodiquesWithArticlesTestC $title->updateFacetsFromExemplaires(); - $this->assertEquals('D800 Lfre Tper_title B1 YCHYJR', + $this->assertEquals('D800 Lfre Tper_title B1 YCHYJR HNRNR0001', $title->getFacettes()); } diff --git a/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php b/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php index eb8932f3b92d7de859959eaab17011ccd5a0d44f..171fcb29a5cc0a205e29c67aed00fc07aba6af9c 100644 --- a/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php +++ b/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php @@ -233,7 +233,7 @@ class KohaRecordIntegrationFacetPresseTest extends KohaRecordIntegrationTestCase /** @test */ public function facettesShouldContainsT2AndHANNE0001AndHMOIS0001AndJOUR0001() { - $this->assertEquals('HANNE0001 HMOIS0001 HJOUR0001 Lfre T2 B1 YMEDSTMAR', + $this->assertEquals('HANNE0001 HMOIS0001 HJOUR0001 Lfre T2 B1 YMEDSTMAR HNRNR0001', Class_Notice::find(1) ->updateFacetsFromExemplaires() ->getFacettes()); @@ -242,7 +242,7 @@ class KohaRecordIntegrationFacetPresseTest extends KohaRecordIntegrationTestCase /** @test */ public function facettesForRecord25ShouldContainsT2AndHANNE0001AndHMOIS0001() { - $this->assertEquals('HANNE0001 HMOIS0007 HJOUR0006 Lfre T2 B1 YMEDSTMAR', + $this->assertEquals('HANNE0001 HMOIS0007 HJOUR0006 Lfre T2 B1 YMEDSTMAR HNRNR0001', Class_Notice::find(25) ->updateFacetsFromExemplaires() ->getFacettes()); diff --git a/cosmogramme/tests/php/classes/NoticeIntegrationTest.php b/cosmogramme/tests/php/classes/NoticeIntegrationTest.php index 7eb4afa2c5345eb4ed2c330b1c1e2c167f8f11d5..9dc927120c59e4c3df7bed2afc483e2e60ab4eae 100644 --- a/cosmogramme/tests/php/classes/NoticeIntegrationTest.php +++ b/cosmogramme/tests/php/classes/NoticeIntegrationTest.php @@ -1239,7 +1239,7 @@ class NoticeIntegrationArchivesAlsaceTest extends NoticeIntegrationTestCase { /** @test */ public function facettesWithExemplairesShouldContainsM1AndM2AndD1() { - $this->assertEquals('D94438 A1 M1 M2 Lfre T1 B1 YBibliothèque des Dominicains', + $this->assertEquals('D94438 A1 M1 M2 Lfre T1 B1 YBibliothèque des Dominicains HNRNR0001', Class_Notice::find(1)->updateFacetsFromExemplaires()->getFacettes()); } } diff --git a/library/Class/AdminVar.php b/library/Class/AdminVar.php index fa82bfa15922dcb1adea37aa7a784b114b1756a6..43188e543592dfd52643a493649226968c4f4ec2 100644 --- a/library/Class/AdminVar.php +++ b/library/Class/AdminVar.php @@ -140,6 +140,7 @@ class Class_AdminVarLoader extends Storm_Model_Loader { 'drive-checkout' => $this->_getDriveCheckoutVars(), 'journal' => $this->_getJournalVars(), 'activity' => $this->_getActivityVars(), + 'pellicule' => $this->_getPelliculeVars(), ]; } @@ -210,7 +211,9 @@ class Class_AdminVarLoader extends Storm_Model_Loader { 'DILICOM_PNB_HOLD_AVAILABLE_MAIL' => Class_AdminVar_Meta::newEditor($this->_('Email de notification de disponibilité de reservation numérique'), ['value'=>'Bonjour {user_name},<p>Le document <a href="{record_url}">{record_title}</a> vous est réservé pour emprunt jusqu\'au {hold_expiration_date}.</p>']), 'DILICOM_PNB_RECORD_MAX_HOLD_COUNT' => Class_AdminVar_Meta::newDefault($this->_('Nombre maximum de réservations par document numérique'), ['value' => 3]), - 'DILICOM_PNB_PATRON_MAX_HOLD_COUNT' => Class_AdminVar_Meta::newDefault($this->_('Nombre maximum de réservations par utilisateur'), ['value' => 2])]; + 'DILICOM_PNB_PATRON_MAX_HOLD_COUNT' => Class_AdminVar_Meta::newDefault($this->_('Nombre maximum de réservations par utilisateur'), ['value' => 2]), + 'DILICOM_PNB_BOARD_DISPLAY_SECTION' => Class_AdminVar_Meta::newOnOff($this->_('Affichage des sections et genres dans le tableau d\'administration des prêts PNB'))] + ; } @@ -571,6 +574,10 @@ class Class_AdminVarLoader extends Storm_Model_Loader { ]; } + protected function _getPelliculeVars() { + return ['PELLICULE_SETTINGS' => (new Class_AdminVar_PelliculeSettings)->meta()]; + } + protected function _getJournalVars() { $stormModels = new Class_AdminVar_JournalStormModels(); @@ -590,7 +597,11 @@ class Class_AdminVarLoader extends Storm_Model_Loader { protected function _getActivityVars() { return ['ACTIVITY' => Class_AdminVar_Meta::newOnOff($this->_('Activer ou désactiver le module d\'activité')), - 'ACTIVITY_SESSION_QUOTAS' => Class_AdminVar_Meta::newOnOff($this->_('Activer ou désactiver la gestion des quotas pour les activités'))]; + 'ACTIVITY_SESSION_QUOTAS' => Class_AdminVar_Meta::newOnOff($this->_('Activer ou désactiver la gestion des quotas pour les activités')), + 'ACTIVITY_NOTIFICATION_DELAY' => Class_AdminVar_Meta::newDefault($this->_('Délai d\'envoie des rappel pour les activités (en jours)'), ['value' => '0']), + 'ACTIVITY_NOTIFICATION_SUBJECT' => Class_AdminVar_Meta::newDefault($this->_('Sujet de l\'email de rappel pour les activités'), ['value'=> 'Rappel : {session.libelle_activity}']), + 'ACTIVITY_NOTIFICATION_BODY' => Class_AdminVar_Meta::newEditor($this->_('Contenu de l\'email de rappel pour les activités'), ['value' => '<p>Bonjour {stagiaire.nom_complet},</p><p>L\'activité {session.libelle_activity} à laquelle vous êtes inscrit, commencera le {session.date_debut_texte}.</p><p>Cordialement</p>']) + ]; } diff --git a/library/Class/AdminVar/PelliculeSettings.php b/library/Class/AdminVar/PelliculeSettings.php new file mode 100644 index 0000000000000000000000000000000000000000..73a6d3f3bb7f1c31d9862aa42e4784d343cc6650 --- /dev/null +++ b/library/Class/AdminVar/PelliculeSettings.php @@ -0,0 +1,90 @@ +<?php +/** + * Copyright (c) 2012-2020, 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_AdminVar_PelliculeSettings { + use Trait_Translator; + const + PROVIDER_KEY = 'Provider', + LOGIN_KEY = 'Login', + PASSWORD_KEY = 'Password', + + ELECTRE_REST_2 = 'electre_rest_2'; + + protected $_settings; + + public function headers() { + if ((!$settings = json_decode(Class_AdminVar::get('PELLICULE_SETTINGS'), true)) + || !isset($settings[static::PROVIDER_KEY]) + || !is_array($settings[static::PROVIDER_KEY])) + return []; + + $this->_settings = $settings; + + return array_filter(array_map([$this, '_header'], + $settings[static::PROVIDER_KEY], + array_keys($settings[static::PROVIDER_KEY]))); + } + + + public function meta() { + $options = ['fields' => [ + ['name' => static::PROVIDER_KEY, + 'label' => $this->_('Fournisseur'), + 'type' => 'select', + 'options' => [static::ELECTRE_REST_2 => $this->_('Electre v2 REST')], + ], + ['name' => static::LOGIN_KEY, + 'label' => $this->_('Identifiant')], + ['name' => static::PASSWORD_KEY, + 'label' => $this->_('Mot de passe') + ]], + + 'fixed' => true]; + + $label = $this->_('Identifiant auprès d\'un fournisseur de vignettes'); + + return Class_AdminVar_Meta::newMultiInput($label, ['options' => $options, 'value' => '']); + } + + + protected function _header($provider, $position) { + if ($provider + && ($credentials = $this->_credentialsFor($provider, $position))) + return ['Authorization'=> 'Pellicule ' . base64_encode(json_encode($credentials))]; + } + + + protected function _credentialsFor($provider, $position) { + if (($id = $this->_getAtPosition(static::LOGIN_KEY, $position)) + && ($secret = $this->_getAtPosition(static::PASSWORD_KEY, $position))) + return ['provider' => $provider, + 'client_id' => $id, + 'client_secret' => $secret]; + } + + + protected function _getAtPosition($key, $position) { + return isset($this->_settings[$key][$position]) + ? $this->_settings[$key][$position] + : null; + } +} diff --git a/library/Class/Album/Item.php b/library/Class/Album/Item.php index a8df06267be322a0f1d28d303e3903ddea480224..405267127439d458778814eab0235d3af2da3dd9 100644 --- a/library/Class/Album/Item.php +++ b/library/Class/Album/Item.php @@ -127,4 +127,18 @@ class Class_Album_Item extends Storm_Model_Abstract { $this->getUsageConstraints()->setLoanQuantity($quantity); return $this; } + + + public function getAlbumSectionIds() { + if ($album = $this->getAlbum()) + return explode(';',$album->getSections()); + return []; + } + + + public function getAlbumGenreIds() { + if ($album = $this->getAlbum()) + return explode(';',$album->getGenre()); + return []; + } } diff --git a/library/Class/Batch.php b/library/Class/Batch.php index ff78f8f303a901ba68983f6825847325b349fdfc..7c4aa6b984df3dfd1f771e5e7c04e1dec38f0fc7 100644 --- a/library/Class/Batch.php +++ b/library/Class/Batch.php @@ -44,6 +44,7 @@ class Class_BatchLoader extends Storm_Model_Loader { Class_Batch_ExternalAgenda::TYPE => new Class_Batch_ExternalAgenda(), Class_Batch_FederationReviewHarvest::TYPE => new Class_Batch_FederationReviewHarvest(), Class_Batch_SendRendezVousNotification::TYPE => new Class_Batch_SendRendezVousNotification(), + Class_Batch_ActivitiesNotifications::TYPE => new Class_Batch_ActivitiesNotifications(), ]); } diff --git a/library/Class/Batch/ActivitiesNotifications.php b/library/Class/Batch/ActivitiesNotifications.php new file mode 100644 index 0000000000000000000000000000000000000000..0aa9e7ec467aa804497720ee165e8164e8690bad --- /dev/null +++ b/library/Class/Batch/ActivitiesNotifications.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright (c) 2012-2020, 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_Batch_ActivitiesNotifications extends Class_Batch_Abstract { + + const TYPE = 'ACTIVITIES_NOTIFICATIONS'; + + public function run() { + $sessions = Class_SessionActivity::findAllNotifiable(); + foreach($sessions as $session) { + (new Class_SessionActivity_Notification($session)) + ->setLogger($this->getLogger()) + ->notify(); + } + } + + + public function isEnabled() { + return Class_AdminVar::isActivityEnabled(); + } + + + public function getLabel() { + return $this->_('Notifier les prochaines activités'); + } +} diff --git a/library/Class/Catalogue.php b/library/Class/Catalogue.php index c24c70ddb03ee2cb89cbc65119ab72f82a1c44a1..d3ee2453d3f0dda5cda05ec3eec0f8e27e89b0fd 100644 --- a/library/Class/Catalogue.php +++ b/library/Class/Catalogue.php @@ -1142,7 +1142,7 @@ class Class_Catalogue extends Storm_Model_Abstract { public function getThesaurusForId($thesaurus) { - $startWith = substr($thesaurus->getIdThesaurus(), 0, Class_Notice_Facette::NB_CHAR_THESAURUS); + $startWith = substr($thesaurus->getIdThesaurus(), 0, Class_CodifThesaurus::ID_KEY_LENGTH); $ids=''; $thesaurus_ids = explode(';',$this->getThesaurus()); diff --git a/library/Class/CodifThesaurus.php b/library/Class/CodifThesaurus.php index 96b7cf158636b228fe908a303cffa07d42efc0a9..309d09f80ea7701e0454467272026c4ce34d0773 100644 --- a/library/Class/CodifThesaurus.php +++ b/library/Class/CodifThesaurus.php @@ -69,6 +69,23 @@ class CodifThesaurusLoader extends Storm_Model_Loader { } + public function ensureRecordNovelty() { + $this->recordNoveltyFor(true); + $this->recordNoveltyFor(false); + } + + + /** @param $flag boolean */ + public function recordNoveltyFor($flag) { + $attributes = ((bool) $flag) + ? ['Id' => 1, 'Libelle' => $this->_('Oui')] + : ['Id' => 2, 'Libelle' => $this->_('Non')]; + + return $this->ensureForModelUnderRoot(new Class_Entity($attributes), + $this->_fixed['RecordNovelty']); + } + + public function ensureForModelUnderRoot($model, $definition) { return ($root = Class_CodifThesaurus::findRootOfId($definition->getId(), $definition->getCode(), @@ -213,7 +230,7 @@ class CodifThesaurusLoader extends Storm_Model_Loader { public function findParent($id_thesaurus) { - $parent_str=substr($id_thesaurus,0,strlen($id_thesaurus)-(4-strlen($id_thesaurus)%4)); + $parent_str = substr($id_thesaurus, 0, strlen($id_thesaurus) - (4 - strlen($id_thesaurus) % 4)); if (!$parent_str) return null; @@ -298,7 +315,7 @@ class CodifThesaurusLoader extends Storm_Model_Loader { public function getIndices($pere, $all = false ) { - if(Class_CodifThesaurus::CODE_ROOT != $pere) { + if (Class_CodifThesaurus::CODE_ROOT != $pere) { $pere = $this->getCodeSur4Chiffres($pere); $length = strlen($pere); @@ -306,17 +323,32 @@ class CodifThesaurusLoader extends Storm_Model_Loader { 'order'=> 'id_thesaurus']); } - $where = ''; - // while search result do not handle item novelty correctly - $to_exclude = [$this->fixedCodeOf('LibraryNovelty'), - $this->fixedCodeOf('AnnexeNovelty')]; + $to_exclude = [$this->fixedIdOf('LibraryNovelty'), + $this->fixedIdOf('AnnexeNovelty')]; if (!$all) - $to_exclude[] = $this->fixedCodeOf('Domain'); + $to_exclude[] = $this->fixedIdOf('Domain'); + + return $this->_findAllFromRootExcluding($to_exclude); + } + + + public function findAllForDomainCriteria() { + // novelty is a criteria in itself + // and no domains in domains + + return $this + ->_findAllFromRootExcluding([$this->fixedIdOf('RecordNovelty'), + $this->fixedIdOf('LibraryNovelty'), + $this->fixedIdOf('AnnexeNovelty'), + $this->fixedIdOf('Domain')]); + } - $where = sprintf('code not in ("%s") and ', implode('", "', $to_exclude)); - $where .= 'LENGTH(id_thesaurus) in (1,4)'; + protected function _findAllFromRootExcluding($to_exclude=[]) { + $where = sprintf('id_thesaurus not in ("%s") and LENGTH(id_thesaurus) in (1,%d)', + implode('", "', $to_exclude), + Class_CodifThesaurus::ID_KEY_LENGTH); return Class_CodifThesaurus::findAllBy(['where' => $where, 'order' => 'id_thesaurus']); diff --git a/library/Class/CodifThesaurusFixed.php b/library/Class/CodifThesaurusFixed.php index f71397a05ef6d01dc31f775e8a41b5ef449c1297..a8e25790274c75022b56f11740e7dcc5d3971852 100644 --- a/library/Class/CodifThesaurusFixed.php +++ b/library/Class/CodifThesaurusFixed.php @@ -27,6 +27,7 @@ class Class_CodifThesaurusFixed extends Class_Entity { 'CustomField' => ['CFCF', 'Custom fields', 'Champs personnalisés'], 'LibraryNovelty' => ['NNNN', 'Nouveauté par bibliothèque', 'Nouveauté par bibliothèque'], 'AnnexeNovelty' => ['NANA', 'Nouveauté par annexe', 'Nouveauté par annexe'], + 'RecordNovelty' => ['NRNR', 'Nouveauté', 'Nouveauté'], 'DigitalResources' => ['DRDR', 'Digital resources', 'Ressources numériques'], 'StreetName' => ['STRE', 'StreetName', 'Nom de rue'], 'LocationType' => ['LOCA', 'LocationType', 'Type de lieu'], diff --git a/library/Class/MultiSelection/Abstract.php b/library/Class/MultiSelection/Abstract.php index 6902ec1359d5d37bd34c06c35a0129a8baaa6b34..120705ace2b72809ec63409afbce94c437f67fdb 100644 --- a/library/Class/MultiSelection/Abstract.php +++ b/library/Class/MultiSelection/Abstract.php @@ -59,10 +59,7 @@ abstract class Class_MultiSelection_Abstract { public function isFullWith($values, $limit) { if(count($values) > $limit) return true; - - $temp_storage = clone($this->_getStorage()); - $temp_storage->addValues($values); - return count($temp_storage->getValues()) > $limit; + return (count($values) + $this->countAlreadySelected()) > $limit; } @@ -78,6 +75,11 @@ abstract class Class_MultiSelection_Abstract { } + public function countAlreadySelected() { + return $this->_getStorage()->count(); + } + + public function contains($id) { return $this->_getStorage()->contains($id); } diff --git a/library/Class/MultiSelection/AlbumItem.php b/library/Class/MultiSelection/AlbumItem.php new file mode 100644 index 0000000000000000000000000000000000000000..a9fc7f38705d10c329ac40c8f45068cfb3c0bf25 --- /dev/null +++ b/library/Class/MultiSelection/AlbumItem.php @@ -0,0 +1,46 @@ +<?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 Class_MultiSelection_AlbumItem extends Class_MultiSelection_Album { + + public function acceptActionsVisitor($visitor) { + $visitor + ->visitControllerName('album') + + ->visitLeafCondition(function($model) + { + return $this->isSelected($model->getAlbum()->getId()); + }) + + ->visitAddLeaf(function($model) + { + return $this->_('Ajouter %s à la sélection', $model->getTitre()); + }) + + ->visitRemoveLeaf(function($model) + { + return $this->_('Supprimer %s de la sélection', $model->getTitre()); + }); + + return $this; + } +} \ No newline at end of file diff --git a/library/Class/MultiSelection/SessionStorage.php b/library/Class/MultiSelection/SessionStorage.php index ae982ba321698722041b1c1134ae967476d503b8..3738bfceee05ae80de8b36563b060ef56b514341 100644 --- a/library/Class/MultiSelection/SessionStorage.php +++ b/library/Class/MultiSelection/SessionStorage.php @@ -46,6 +46,11 @@ class Class_MultiSelection_SessionStorage { } + public function count() { + return count($this->getValues()); + } + + public function addValues($values) { $call_back = function ($selected_models, $values) { $selected_models = array_merge($selected_models, $values); diff --git a/library/Class/Notice.php b/library/Class/Notice.php index 526a81eca2314d7f9d2f7935fc91beaa1c6f1545..eab5fa9fbece3a1173927f6ee1d51c722fae3237 100644 --- a/library/Class/Notice.php +++ b/library/Class/Notice.php @@ -153,15 +153,39 @@ class NoticeLoader extends Storm_Model_Loader { public function indexNoveltyFacets() { - $page = 1; - while($records = Class_Notice::findAllBy(['where' => 'match(facettes) against("+(HNNNN* HNANA*)" in boolean mode)', - 'limitPage' => [$page, 100]])) { - foreach($records as $record) - $record->updateNoveltyFacets(); - - $this->_cleanMemory(); - $page++; + $facets = ['HNNNN*', 'HNANA*']; + if ($novelty_thesaurus = Class_CodifThesaurus::recordNoveltyFor(true)) + $facets[] = $novelty_thesaurus->getFacetCode(); + $facets = implode(' ', $facets); + + $record_id = 0; + while ($records = $this->_findNoveltyRecordsFrom($facets, $record_id)) + $record_id = $this->_updateNovelty($records); + } + + + protected function _findNoveltyRecordsFrom($facets, $record_id) { + if (null === $record_id) + return []; + + $where = sprintf('match(facettes) against("+(%s)" in boolean mode) and id_notice > %d', + $facets, $record_id); + + return Class_Notice::findAllBy(['where' => $where, + 'order' => 'id_notice', + 'limit' => 100]); + } + + + protected function _updateNovelty($records) { + $record_id = null; + foreach($records as $record) { + $record->updateNoveltyFacets(); + $record_id = $record->getId(); } + $this->_cleanMemory(); + + return $record_id; } } @@ -1790,25 +1814,6 @@ class Class_Notice extends Storm_Model_Abstract { } - - public function getFacetCodesWithoutItemFacets() { - $filtered = [Class_Bib::CODE_FACETTE, - Class_CodifEmplacement::CODE_FACETTE, - Class_CodifSection::CODE_FACETTE, - Class_CodifAnnexe::CODE_FACETTE, - Class_CodifTypeDoc::CODE_FACETTE, - Class_Codification::CODE_DATE_NOUVEAUTE, - Class_Codification::CODE_AVAILABILITY]; - - return array_filter($this->getFacetCodes(), - function($code) use ($filtered) - { - return !in_array(substr($code, 0, 1), - $filtered); - }); - } - - protected function _fetchItemsToInjectInFacets() { if ($this->isPeriodiqueArticle() && ($linked_record = $this->getLinkedSerialRecord())) return $linked_record->getExemplaires(); @@ -1828,19 +1833,29 @@ class Class_Notice extends Storm_Model_Abstract { public function updateFacetsFromExemplaires() { - $facettes = $this->getFacetCodesWithoutItemFacets(); - $facettes []= Class_CodifTypeDoc::CODE_FACETTE. $this->getTypeDoc(); + $facets = Class_Notice_Facette::fromStringWithoutItemFacets($this->getFacettes()); + $facets = array_map(function($facet) { return $facet->getCle(); }, + $facets); + $facets[] = Class_CodifTypeDoc::CODE_FACETTE . $this->getTypeDoc(); + + $is_novelty = false; $date_nouveaute = ''; foreach($this->_fetchItemsToInjectInFacets() as $exemplaire) { - $facettes = array_merge($facettes, $exemplaire->getFacets()); + $facets = array_merge($facets, $exemplaire->getFacets()); + $date_nouveaute = ($exemplaire->getDateNouveaute() > $date_nouveaute) ? $exemplaire->getDateNouveaute() : $date_nouveaute; + + $is_novelty = $is_novelty || $exemplaire->isNouveaute(); } + if ($novelty_thesaurus = Class_CodifThesaurus::recordNoveltyFor($is_novelty)) + $facets[] = $novelty_thesaurus->getFacetCode(); + return $this - ->setFacettes(array_unique($facettes)) + ->setFacettes(array_unique($facets)) ->setDateCreation($date_nouveaute ? ($date_nouveaute . ' 00:00:00') : null); } @@ -1858,12 +1873,17 @@ class Class_Notice extends Storm_Model_Abstract { $this->deleteFacettes(implode(' ', $existings)); $facets = []; + $is_novelty = false; foreach($this->getExemplaires() as $item) if ($item->isNouveaute()) { $facets[] = Class_CodifThesaurus::findForItemLibraryNovelty($item); $facets[] = Class_CodifThesaurus::findForItemAnnexeNovelty($item); + $is_novelty = true; } + if ($novelty_thesaurus = Class_CodifThesaurus::recordNoveltyFor($is_novelty)) + $facets[] = $novelty_thesaurus->getFacetCode(); + $this->updateFacette(implode(' ', $facets))->save(); return $this; } diff --git a/library/Class/Notice/Facette.php b/library/Class/Notice/Facette.php index 7c8f320b8bffb4e03b15cf2205fb04c784c85c2e..96c33793baf6f484fc6c7378c47595aa8c6f69f8 100644 --- a/library/Class/Notice/Facette.php +++ b/library/Class/Notice/Facette.php @@ -19,13 +19,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ class Class_Notice_Facette { - const NB_CHAR_THESAURUS = 4; - protected static $_instances = []; protected $_cle, - $_rubrique; + $_rubrique, + $_group_code, + $_value; public static function fromStringFiltered($facet_string, $callback) { @@ -35,6 +35,12 @@ class Class_Notice_Facette { } + public static function fromStringWithoutItemFacets($facet_string) { + return static::fromStringFiltered($facet_string, + function($facet) { return !$facet->isItem(); }); + } + + public static function parseFacettesFromNoticeField($str_facettes) { $items = array_filter(explode(' ', trim($str_facettes))); $facettes = []; @@ -88,12 +94,16 @@ class Class_Notice_Facette { public function getValue() { - return substr($this->_cle, 1); + return $this->_value = $this->_value + ? $this->_value + : substr($this->_cle, 1); } protected function getGroupCodeFromKey() { - return static::extractCodeRubrique($this->_cle); + return $this->_group_code = $this->_group_code + ? $this->_group_code + : static::extractCodeRubrique($this->_cle); } @@ -122,55 +132,98 @@ class Class_Notice_Facette { public function isNovelty() { return in_array(substr($this->getGroupCodeFromKey(), 1), [Class_CodifThesaurus::fixedIdOf('LibraryNovelty'), - Class_CodifThesaurus::fixedIdOf('AnnexeNovelty')]); + Class_CodifThesaurus::fixedIdOf('AnnexeNovelty'), + Class_CodifThesaurus::fixedIdOf('RecordNovelty')]); } public function isAvailability() { - return Class_Codification::CODE_AVAILABILITY == $this->getGroupCodeFromKey(); + return $this->isGroupCode(Class_Codification::CODE_AVAILABILITY); } public function isAuthor() { - return Class_CodifAuteur::CODE_FACETTE == $this->getGroupCodeFromKey(); + return $this->isGroupCode(Class_CodifAuteur::CODE_FACETTE); } public function isMatter() { - return Class_CodifMatiere::CODE_FACETTE == $this->getGroupCodeFromKey(); + return $this->isGroupCode(Class_CodifMatiere::CODE_FACETTE); } public function isDynamicFacet() { - return Class_CodifThesaurus::CODE_FACETTE === substr($this->_cle, 0, 1) + return $this->isThesaurus() && strlen($this->getValue()) === (Class_CodifThesaurus::ID_KEY_LENGTH * 2); } public function isDynamicFacetRoot() { - return Class_CodifThesaurus::CODE_FACETTE === substr($this->_cle, 0, 1) + return $this->isThesaurus() && strlen($this->getValue()) === Class_CodifThesaurus::ID_KEY_LENGTH; } public function isDocTypeFacet() { - return Class_CodifTypeDoc::CODE_FACETTE == $this->getGroupCodeFromKey(); + return $this->isGroupCode(Class_CodifTypeDoc::CODE_FACETTE); } public function isAnnexeFacet() { - return Class_CodifAnnexe::CODE_FACETTE == $this->getGroupCodeFromKey(); + return $this->isGroupCode(Class_CodifAnnexe::CODE_FACETTE); } public function isLibraryFacet() { - return Class_Bib::CODE_FACETTE == $this->getGroupCodeFromKey(); + return $this->isGroupCode(Class_Bib::CODE_FACETTE); } public function isDomainFacet() { - $code = $this->getGroupCodeFromKey(); - return Class_Catalogue::CODE_FACETTE == $code - || Class_CodifThesaurus::CODE_FACETTE == $this->_cle[0]; + return $this->isGroupCode(Class_Catalogue::CODE_FACETTE) || $this->isThesaurus(); + } + + + public function isLocationFacet() { + return $this->isGroupCode(Class_CodifEmplacement::CODE_FACETTE); + } + + + public function isSectionFacet() { + return $this->isGroupCode(Class_CodifSection::CODE_FACETTE); + } + + + public function isThesaurus() { + return Class_CodifThesaurus::CODE_FACETTE === substr($this->_cle, 0, 1); + } + + + public function isRecordNoveltyFacet() { + return $this->isDynamicFacetUnder(Class_CodifThesaurus::fixedIdOf('RecordNovelty')); + } + + + public function isDynamicFacetUnder($root_code) { + return $this->isDynamicFacet() && substr($this->getGroupCodeFromKey(), 1) === $root_code; + } + + + public function isItem() { + return + $this->isLibraryFacet() + || $this->isLocationFacet() + || $this->isSectionFacet() + || $this->isAnnexeFacet() + || $this->isDocTypeFacet() + || $this->isGroupCode(Class_Codification::CODE_DATE_NOUVEAUTE) + || $this->isGroupCode(Class_Codification::CODE_AVAILABILITY) + || $this->isRecordNoveltyFacet() + ; + } + + + public function isGroupCode($code) { + return $this->getGroupCodeFromKey() === $code; } } \ No newline at end of file diff --git a/library/Class/SessionActivity.php b/library/Class/SessionActivity.php index 580a89a333f45f610fedaed88693426519e39ead..ee6b3c1be04a0e0e31dba365b3ea60ab74413df3 100644 --- a/library/Class/SessionActivity.php +++ b/library/Class/SessionActivity.php @@ -80,6 +80,15 @@ class SessionActivityLoader extends Storm_Model_Loader { ? Class_SessionActivity::findFirstBy(['article_id' => $article->getId()]) : null; } + + + public function findAllNotifiable() { + if (!$delay = (int)Class_AdminVar::get('ACTIVITY_NOTIFICATION_DELAY')) + return []; + + $date_clause = 'date_debut >= NOW() and DATEDIFF(date_debut, NOW()) <= ' . $delay; + return Class_SessionActivity::findAllBy(['where' => $date_clause]); + } } @@ -115,6 +124,8 @@ class Class_SessionActivity extends Storm_Model_Abstract { 'effectif_max' => 10, 'effectif_child_min' => 0, 'effectif_child_max' => 0, + 'age_child_max' => 0, + 'all_day' => 1, 'effectif_inscription_max' => 0, 'effectif_inscription_child_max' => 0, 'cout' => 0, @@ -272,35 +283,35 @@ class Class_SessionActivity extends Storm_Model_Abstract { } + public function getMetaDatas() { + return [new SessionActivity_MetaData($this->_('Activité'), $this->getLibelleActivity()), + new SessionActivity_MetaData($this->_('Session'), $this->getDateDebutTexte()), + new SessionActivity_MetaData($this->_('Durée'), $this->getDuree() . 'h'), + new SessionActivity_MetaData($this->_('Effectif'), + $this->getAttendeesMin() + . '-' . $this->getAttendeesMax())]; + } + + public function validate() { $this->checkAttribute("effectif_max", $this->getEffectifMin() <= $this->getEffectifMax(), $this->_("L'effectif maximum doit être supérieur ou égal à l'effectif minimum")); - $this->checkAttribute("effectif_max", - $this->getEffectifInscriptionMax() <= $this->getEffectifMax(), - $this->_("L'effectif maximum doit être supérieur ou égal à l'effectif maximum par inscription")); - - $this->checkAttribute("effectif_child_max", - $this->getEffectifChildMin() <= $this->getEffectifChildMax(), - $this->_("L'effectif enfants maximum doit être supérieur ou égal à l'effectif enfants minimum")); - - $this->checkAttribute("effectif_child_max", - $this->getEffectifInscriptionChildMax() <= $this->getEffectifChildMax(), - $this->_("L'effectif enfants maximum doit être supérieur ou égal à l'effectif enfants maximum par inscription")); - $this->checkAttribute("effectif_max", $this->numberOfAttendees() <= $this->getAttendeesMax(), $this->_("Le nombre d'inscrit.e.s ne peut dépasser l'effectif maximum")); + $this->_checkAttributesWithQuotas(); + foreach($this->getStagiaires() as $stagiaire) { $this->checkAttribute("effectif_max", $stagiaire->hasRightSuivreActivity(), $this->_("Le stagiaire %s n'a pas les droits suffisants pour suivre une activité", $stagiaire->getLogin())); } - $start_date = DateTime::createFromFormat('!Y-m-d', $this->getDateDebut()); - $this->checkAttribute('date_debut', $start_date, + $start_date = $this->_getFormatDate($this->getDateDebut()); + $this->checkAttribute('activity_range', $start_date, $this->_('La date de début est requise')); $limit_date = DateTime::createFromFormat('!Y-m-d', $this->getDateLimiteInscription()); @@ -312,12 +323,43 @@ class Class_SessionActivity extends Storm_Model_Abstract { $limit_date <= $start_date, $this->_("La date limite d'inscription doit être inférieure ou égale à la date de début")); - if ($this->hasDateFin() - && ($end_date = DateTime::createFromFormat('!Y-m-d', $this->getDateFin())) - && $start_date) - $this->checkAttribute('date_fin', - $end_date >= $start_date, - $this->_("La date de fin doit être supérieure ou égale à la date de début")); + if (!$this->hasDateFin()) + return; + + $this->checkAttribute('activity_range', + $start_date && ($end_date = $this->_getFormatDate($this->getDateFin())) && $end_date >= $start_date, + $this->_("La date de fin doit être supérieure ou égale à la date de début")); + } + + + protected function _checkAttributesWithQuotas() { + if (!Class_AdminVar::isActivitySessionQuotasEnabled()) + return; + + $this->checkAttribute("effectif_max", + $this->getEffectifInscriptionMax() <= $this->getEffectifMax(), + $this->_("L'effectif maximum doit être supérieur ou égal à l'effectif maximum par inscription")); + + $this->checkAttribute("effectif_child_max", + $this->getEffectifChildMin() <= $this->getEffectifChildMax(), + $this->_("L'effectif enfants maximum doit être supérieur ou égal à l'effectif enfants minimum")); + + $this->checkAttribute("effectif_child_max", + $this->getEffectifInscriptionChildMax() <= $this->getEffectifChildMax(), + $this->_("L'effectif enfants maximum doit être supérieur ou égal à l'effectif enfants maximum par inscription")); + + $this->checkAttribute('age_child_max', + $this->getEffectifChildMax() <= 0 || $this->getAgeChildMax() > 0, + $this->_("L'âge maximum pour les enfants doit être renseigné")); + + $this->checkAttribute("effectif_inscription_max", + $this->getEffectifMax() <= 0 || $this->getEffectifInscriptionMax() > 0, + $this->_("Adultes maximum par inscription doit être renseigné")); + + $this->checkAttribute("effectif_inscription_child_max", + $this->getEffectifChildMax() <= 0 + || $this->getEffectifInscriptionChildMax() > 0, + $this->_("Enfants maximum par inscription doit être renseigné")); } @@ -405,6 +447,14 @@ class Class_SessionActivity extends Storm_Model_Abstract { } + protected function _getFormatDate($date) { + if (!$date || strlen($date) < 10) + return false; + + return DateTime::createFromFormat('!Y-m-d', substr($date, 0, 10)); + } + + protected function _getHumanDate($date) { return strftime(static::HUMAN_DATE_FORMAT, strtotime($date)); } @@ -503,6 +553,7 @@ class Class_SessionActivity extends Storm_Model_Abstract { + class Class_SessionActivity_Article extends Storm_Model_Association_HasOne { use Trait_Translator; @@ -564,11 +615,15 @@ class Class_SessionActivity_Article protected function _synchronize($model, $dependent, $force_content=false) { $dependent ->setTitre($model->getLibelleActivity()) - ->setEventsDebut($this->_replaceDateInto($dependent->getEventsDebut(), $model->getDateDebut())) + ->setEventsDebut($this->_replaceDateInto($dependent->getEventsDebut(), + $model->getDateDebut(), + $model->getAllDay())) ->setEventsFin($this->_replaceDateInto($dependent->getEventsFin(), $model->hasDateFin() ? $model->getDateFin() - : $model->getDateDebut())) + : $model->getDateDebut(), + $model->getAllDay())) + ->setAllDay($model->getAllDay()) ->setLieu($model->getLieu()); if (!$dependent->getContenu() || $force_content) @@ -579,15 +634,19 @@ class Class_SessionActivity_Article } - protected function _replaceDateInto($old_datetime, $new_date) { - return $new_date - . (10 < strlen($old_datetime) ? substr($old_datetime, 10) : ''); + protected function _replaceDateInto($old_datetime, $new_date, $is_all_day) { + return $is_all_day + ? $new_date . (10 < strlen($old_datetime) ? substr($old_datetime, 10) : '') + : $new_date; } protected function _contentFrom($model) { - return - $model->getActivityDescription() + $content = ($content = $model->getContenu()) + ? $content + : $model->getActivityDescription(); + + return $content . $this->_getInformations($model) . $this->_getRegisterLink($model); } @@ -661,4 +720,30 @@ class Class_SessionActivity_Article 'id' => $model->getId()]) . '">' . $this->_('S\'inscrire') . '</a></p>'; } +} + + + + +class SessionActivity_MetaData { + use Trait_GetterByAttributeName; + + protected + $_label, + $_value; + + public function __construct($label, $value) { + $this->_label = $label; + $this->_value = $value; + } + + + public function getLabel() { + return $this->_label; + } + + + public function getValue() { + return $this->_value; + } } \ No newline at end of file diff --git a/library/Class/SessionActivity/Notification.php b/library/Class/SessionActivity/Notification.php new file mode 100644 index 0000000000000000000000000000000000000000..18ee64db23d5ba4cb3abdb35f268d713047b8709 --- /dev/null +++ b/library/Class/SessionActivity/Notification.php @@ -0,0 +1,87 @@ +<?php +/** + * Copyright (c) 2012-2020, 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_SessionActivity_Notification { + use Trait_Logger, Trait_Translator, Trait_TimeSource; + + protected + $_session_activity, + $_sent_count = 0, + $_errors = []; + + public function __construct($session) { + $this->_session_activity = $session; + } + + + public function notify() { + foreach($this->_session_activity->getSessionActivityInscriptions() as $inscription) + $this->_notifyOne($inscription); + + $this->getLogger()->log($this->_('%s : %s rappel(s) envoyé(s)', + $this->_session_activity->getLibelleActivity(), + $this->_sent_count)); + + foreach($this->_errors as $message) + $this->getLogger()->error($message); + + return $this; + } + + + protected function _notifyOne($inscription) { + if ($inscription->hasNotifiedAt()) + return $this; + + $stagiaire = $inscription->getStagiaire(); + $mailer = new Class_MailHtml(); + if (!$mailer->isMailValid($stagiaire->getMail())) + return $this; + + if (true === $result = $mailer->mail($stagiaire->getMail(), + $this->_fusion($stagiaire, 'ACTIVITY_NOTIFICATION_SUBJECT'), + $this->_fusion($stagiaire, 'ACTIVITY_NOTIFICATION_BODY'))) { + $this->_sent_count++; + $inscription->setNotifiedAt($this->getCurrentDateTime()) + ->saveWithoutValidation(); + } + + return $this->_error($result); + } + + + protected function _fusion($stagiaire, $var_key) { + return (new Class_ModeleFusion()) + ->setContenu(Class_AdminVar::getValueOrDefault($var_key)) + ->setDataSource(['session' => $this->_session_activity, + 'stagiaire' => $stagiaire]) + ->getContenuFusionne(); + } + + + protected function _error($message) { + if ($message && !in_array($message, $this->_errors)) + $this->_errors[] = $message; + + return $this; + } +} diff --git a/library/Class/SessionActivityInscription.php b/library/Class/SessionActivityInscription.php index 1f3c9d6d1a1996142c05d68bf2fbc3d88175126f..a819e359361591b52400303f8f822728f99e646d 100644 --- a/library/Class/SessionActivityInscription.php +++ b/library/Class/SessionActivityInscription.php @@ -76,7 +76,8 @@ class Class_SessionActivityInscription extends Storm_Model_Abstract { $_default_attribute_values = ['presence' => false, 'adults' => 0, 'children' => 0, - 'stagiaire_id' => null]; + 'stagiaire_id' => null, + 'notified_at' => null]; public function validate() { diff --git a/library/Class/TableDescription.php b/library/Class/TableDescription.php index a523d8e647fb5ed4889249203dc69e6b53378055..082a4e18beab906f1211a10093a96e99c2d30ee4 100644 --- a/library/Class/TableDescription.php +++ b/library/Class/TableDescription.php @@ -271,6 +271,11 @@ class Class_TableDescription_Columns { } + public function isEmpty() { + return $this->_columns->isEmpty(); + } + + /** @return Class_TableDescription_ColumnAbstract subclass */ public function add($column) { $this->_columns->append($column); diff --git a/library/Class/TableDescription/PNBItems.php b/library/Class/TableDescription/PNBItems.php index 33944e92a1d5c3f4adf5246d83df6f5fc450bd6e..c630484111aa1ad0f16b4171930748793baf2481 100644 --- a/library/Class/TableDescription/PNBItems.php +++ b/library/Class/TableDescription/PNBItems.php @@ -33,14 +33,32 @@ class Class_TableDescription_PNBItems extends Class_TableDescription { }) ->addColumn($this->_('Durée de prêt en jours'), 'duration') ->addColumn($this->_('Nombre de jours restant sur la licence'), 'license_expiration') - ->addColumn($this->_('Date de commande'), 'order_date') - ->addRowAction(['url' => ['module' => 'admin', - 'controller' => 'album', - 'action' => 'edit_album', - 'id' => '%s'], - 'id' => function($model) { return $model->getAlbumId(); }, - 'anchorOptions' => ['data-popup' => 'true'], - 'label' => $this->_('Voir l\'album'), - 'icon' => 'view']); + ->addColumn($this->_('Date de commande'), 'order_date'); + + if (Class_AdminVar::get('DILICOM_PNB_BOARD_DISPLAY_SECTION')) + $this->addColumn($this->_('Genre'), 'genre') + ->addColumn($this->_('Section'), 'section'); + + $this->addRowAction(['url' => ['module' => 'admin', + 'controller' => 'album', + 'action' => 'edit_album', + 'id' => '%s'], + 'id' => function($model) { return $model->getAlbumId(); }, + 'anchorOptions' => ['data-popup' => 'true'], + 'label' => $this->_('Voir l\'album'), + 'icon' => 'view']); + return $this->_addMultiSelectionAction(); + } + + + protected function _addMultiSelectionAction() { + $multi_selection = new Class_MultiSelection_AlbumItem(); + + foreach( (new ZendAfi_Controller_Plugin_MultiSelection_LeafActions($multi_selection)) + ->getActions() as $action) { + $action['id'] = function($model) { return $model->getAlbumId(); }; + $this->addRowAction($action); + } + return $this; } } diff --git a/library/Class/TableDescription/PNBItemsRenderer.php b/library/Class/TableDescription/PNBItemsRenderer.php index 69e0e25adab68a89496f0bfc605498b16a9ded7b..d66e6c085415d71e46ca2985379b6e9006186925 100644 --- a/library/Class/TableDescription/PNBItemsRenderer.php +++ b/library/Class/TableDescription/PNBItemsRenderer.php @@ -52,6 +52,20 @@ class Class_TableDescription_PNBItemsRenderer { } + public function getSection() { + if ($sections = $this->_item->getAlbumSectionIds()) + return implode(', ',Class_CodifSection::labelsOfIds($sections)->getArrayCopy()); + return ''; + } + + + public function getGenre() { + if ($genre = $this->_item->getAlbumGenreIds()) + return implode(', ',Class_CodifGenre::labelsOfIds($genre)->getArrayCopy()); + return ''; + } + + public function quantityOrInfinite($value) { return $this->isInfinite($value) ? '∞' diff --git a/library/Class/TableDescription/SessionActivityInscriptionsExport.php b/library/Class/TableDescription/SessionActivityInscriptionsExport.php index b22f3db822fe12e7b6bd73effa754ba99177ff4b..a21f9463407fb1995516533827dded3c78922f0a 100644 --- a/library/Class/TableDescription/SessionActivityInscriptionsExport.php +++ b/library/Class/TableDescription/SessionActivityInscriptionsExport.php @@ -22,19 +22,38 @@ class Class_TableDescription_SessionActivityInscriptionsExport extends Class_TableDescription { - public function init() { - parent::init(); + protected $_age_child_max; + public function setAgeChildMax($age_child_max) { + $this->_age_child_max = $age_child_max; + return $this; + } + + + public function columnsCollect($callback) { + if ($this->_columns->isEmpty()) + $this->_initColumns(); + + return parent::columnsCollect($callback); + } + + + protected function _initColumns() { $this->addColumn($this->_('Nom'), 'nom') ->addColumn($this->_('Prénom'), 'prenom') ->addColumn($this->_('Identifiant'), 'login') ->addColumn($this->_('Mail'), 'mail') ->addColumn($this->_('Bibliothèque'), 'libelle_bib'); - if (!Class_AdminVar::isActivitySessionQuotasEnabled()) - return; + if (Class_AdminVar::isActivitySessionQuotasEnabled()) + $this->addColumn($this->_('Adultes'), 'adults') + ->addColumn($this->_getChildrenLabel(), 'children'); + } + - $this->addColumn($this->_('Adultes'), 'adults') - ->addColumn($this->_('Enfants'), 'children'); + protected function _getChildrenLabel() { + return $this->_age_child_max + ? $this->_('Enfants (âge max %s)', $this->_age_child_max) + : $this->_('Enfants'); } } diff --git a/library/Class/User/SessionActivity.php b/library/Class/User/SessionActivity.php index 51398eed8fad30462f275b362ee0b46bdacf1c4e..7d67b0725a0a15cf10c038ee39a4919876dc9637 100644 --- a/library/Class/User/SessionActivity.php +++ b/library/Class/User/SessionActivity.php @@ -76,6 +76,11 @@ class Class_User_SessionActivity { public function getNextChildrenMax() { return $this->_session_activity->getNextChildrenMaxFor($this->_inscription); } + + + public function getAgeChildMax() { + return $this->_session_activity->getAgeChildMax(); + } } diff --git a/library/Class/WebService/AllServices.php b/library/Class/WebService/AllServices.php index a64a48b9c07d55ebb9281e3aaa1140d2fa859e1f..e7d4f9934114f5c01304f6c458b6400421c75f5d 100644 --- a/library/Class/WebService/AllServices.php +++ b/library/Class/WebService/AllServices.php @@ -84,41 +84,45 @@ class Class_WebService_AllServices { public static function runServiceAfiBiographie($args) { - return self::runServiceAfi(static::SVC_GET_BIOGRAPHY, $args); + return static::runServiceAfi(static::SVC_GET_BIOGRAPHY, $args); } public static function runServiceAfiVideo($args) { - return self::runServiceAfi(static::SVC_GET_VIDEO, $args); + return static::runServiceAfi(static::SVC_GET_VIDEO, $args); } public static function runServiceAfiInterviews($args) { - return self::runServiceAfi(static::SVC_GET_INTERVIEW, $args); + return static::runServiceAfi(static::SVC_GET_INTERVIEW, $args); } public static function runServiceAfiUploadVignette($args) { - return self::runServiceAfi(static::SVC_UPLOAD_THUMBNAIL, $args); + return static::runServiceAfi(static::SVC_UPLOAD_THUMBNAIL, $args); } public static function runServiceAfiUploadBiographie($args) { - return self::runServiceAfi(static::SVC_SET_BIOGRAPHY, $args); + return static::runServiceAfi(static::SVC_SET_BIOGRAPHY, $args); } + public static function runServiceAfiUploadTrailer($args) { - return self::runServiceAfi(static::SVC_SET_TRAILER, $args); + return static::runServiceAfi(static::SVC_SET_TRAILER, $args); } public static function runServiceGetUrlVignette($args) { - return self::runServiceAfi(static::SVC_GET_THUMBNAIL, $args); + if ($headers = (new Class_AdminVar_PelliculeSettings)->headers()) + $args['headers'] = $headers; + + return static::runServiceAfi(static::SVC_GET_THUMBNAIL, $args); } public static function setHttpClient($client) { - self::$_http_client = $client; + static::$_http_client = $client; } @@ -132,7 +136,7 @@ class Class_WebService_AllServices { 'image' => $url, 'numero' => $notice->getTomeAlpha(), 'clef_chapeau' => $notice->getClefChapeau()])); - if (self::RETOUR_SERVICE_OK != $result['statut_recherche']) + if (static::RETOUR_SERVICE_OK != $result['statut_recherche']) return $result['erreur']; $notice @@ -150,7 +154,7 @@ class Class_WebService_AllServices { 'auteur' => $auteur, 'clef_oeuvre' => Class_Notice_WorkKey::legacy()->keyString($notice)]); $result = static::runServiceAfiUploadBiographie($args); - if (self::RETOUR_SERVICE_OK != $result['statut_recherche']) + if (static::RETOUR_SERVICE_OK != $result['statut_recherche']) return $result['message']; } @@ -171,7 +175,7 @@ class Class_WebService_AllServices { 'clef_oeuvre' => Class_Notice_WorkKey::legacy()->keyString($record), 'language' => $lang, 'biography_disabled' => ($status == static::BIO_DISABLED) ? 1 : 0]); - if (self::RETOUR_SERVICE_OK != $result['statut_recherche']) + if (static::RETOUR_SERVICE_OK != $result['statut_recherche']) return $result['message']; } @@ -188,31 +192,41 @@ class Class_WebService_AllServices { if (!isset($result['statut_recherche'])) return $this->_('Le service n\'a pas répondu'); - if (self::RETOUR_SERVICE_OK != $result['statut_recherche']) + if (static::RETOUR_SERVICE_OK != $result['statut_recherche']) return $result['message']; } public static function httpGet($url, $args) { - if (!isset(self::$_http_client)) - self::$_http_client = new Class_WebService_SimpleWebClient(); - return self::$_http_client->open_url($url.'?'.http_build_query($args)); + if (!isset(static::$_http_client)) + static::$_http_client = new Class_WebService_SimpleWebClient(); + + $options = isset($args['headers']) + ? ['headers' => $args['headers']] + : []; + unset($args['headers']); + + $call_params = [$url . '?' . http_build_query($args)]; + if ($options) + $call_params[] = $options; + + return call_user_func_array([static::$_http_client, 'open_url'], $call_params); } - public static function runServiceAfi($service,$args) { + public static function runServiceAfi($service, $args) { if (!$url_service = Class_CosmoVar::get('url_services')) return false; if (!$args) $args = array(); - $args['src'] = self::createSecurityKey(); - $args['api'] = self::SVC_API; + $args['src'] = static::createSecurityKey(); + $args['api'] = static::SVC_API; $args['action'] = $service; - $response = json_decode(self::httpGet($url_service, $args), true); + $response = json_decode(static::httpGet($url_service, $args), true); if ($ig = Zend_Controller_Front::getInstance() ->getPlugin('ZendAfi_Controller_Plugin_InspectorGadget')) diff --git a/library/ZendAfi/Controller/Plugin/Manager/SessionActivity.php b/library/ZendAfi/Controller/Plugin/Manager/SessionActivity.php index 784db9d518a97aa8b9073a91a67c454a0c8ae03c..0626c416951b6d7ba5da3b6e2354ca8123bb236a 100644 --- a/library/ZendAfi/Controller/Plugin/Manager/SessionActivity.php +++ b/library/ZendAfi/Controller/Plugin/Manager/SessionActivity.php @@ -25,12 +25,24 @@ class ZendAfi_Controller_Plugin_Manager_SessionActivity public function _getPost($key = null, $default = null) { $post = parent::_getPost($key, $default); - foreach(['date_debut', 'date_fin', 'date_limite_inscription'] as $field) - $post[$field] = $this->_readPostDate($this->_request->getPost($field)); + foreach(['date_debut', 'date_fin'] as $field) + $post[$field] = $this->_readPostActivityDate($this->_request->getPost($field)); + + $post['date_limite_inscription'] = $this->_readPostDate($this->_request->getPost('date_limite_inscription')); return $post; } + protected function _readPostActivityDate($date) { + $date_explode = explode(' ', $date); + + if (1 === count($date_explode)) + return Class_Date::frToIso($date); + + return Class_Date::frToIso($date_explode[0]) . ' ' . $date_explode[1]; + } + + protected function _readPostDate($date) { return Class_Date::frToIso($date); } diff --git a/library/ZendAfi/Controller/Plugin/MultiSelection/Abstract.php b/library/ZendAfi/Controller/Plugin/MultiSelection/Abstract.php index f9bc12403253e6832a0f20673843108de9a0c5f3..9a57a23ad1e639b85f367a67064b095bd7e96f5e 100644 --- a/library/ZendAfi/Controller/Plugin/MultiSelection/Abstract.php +++ b/library/ZendAfi/Controller/Plugin/MultiSelection/Abstract.php @@ -40,6 +40,30 @@ abstract class ZendAfi_Controller_Plugin_MultiSelection_Abstract extends ZendAfi } + public function addModelToSelectionAjaxAction() { + $values = $this->_getValuesFromParams(); + $limit = (int) Class_AdminVar::getValueOrDefault('LIMIT_MULTIPLE_SELECTION'); + + if($this->_getMultiSelection()->isFullWith($values, $limit)) { + return $this->_helper->json(['selection' => $this->renderWidget(), + 'response' => $this->_('Il n\'est pas possible de sélectionner plus de %d éléments', + $limit)]); + } + + $this->_multi_selection = $this->_getMultiSelection()->addValues($values); + return $this->_helper->json(['selection' => $this->renderWidget(), + 'response' => 'ok']); + } + + + public function removeModelFromSelectionAjaxAction() { + $this->_getMultiSelection()->removeValues($this->_getValuesFromParams()); + + return $this->_helper->json(['selection' => $this->renderWidget(), + 'response' => 'ok']); + } + + public function removeModelFromSelectionAction() { $this->_getMultiSelection()->removeValues($this->_getValuesFromParams()); return $this->_redirectToReferer(); @@ -48,7 +72,7 @@ abstract class ZendAfi_Controller_Plugin_MultiSelection_Abstract extends ZendAfi public function clearModelsSelectionAction() { $this->_multi_selection->clear(); - $this->_redirect($this->_view->absoluteUrl(['action' => 'index'])); + return $this->_redirectToReferer(); } @@ -161,13 +185,19 @@ abstract class ZendAfi_Controller_Plugin_MultiSelection_Abstract extends ZendAfi public function render() { if (('index' == $this->_request->getActionName()) - || ('edit-multiple' == $this->_request->getActionName())) - return $this->_view->Plugin_MultiSelection_Widget($this->_multi_selection); + || ('edit-multiple' == $this->_request->getActionName()) + || ('dilicom' == $this->_request->getActionName())) + return $this->renderWidget(); return ''; } + public function renderWidget() { + return $this->_view->Plugin_MultiSelection_Widget($this->_getMultiSelection()); + } + + public function visitGetForm($callback) { $this->_get_form = $callback; return $this; diff --git a/library/ZendAfi/Controller/Plugin/MultiSelection/LeafActions.php b/library/ZendAfi/Controller/Plugin/MultiSelection/LeafActions.php index 77cebd917db043f7430aaa7d61ebe4013f4ea762..f39a5f6c77855a4553ab00a93d9be2170660f8ef 100644 --- a/library/ZendAfi/Controller/Plugin/MultiSelection/LeafActions.php +++ b/library/ZendAfi/Controller/Plugin/MultiSelection/LeafActions.php @@ -26,6 +26,8 @@ class ZendAfi_Controller_Plugin_MultiSelection_LeafActions extends ZendAfi_Contr ['url' => ['controller' => $this->_controller_name, 'action' => 'remove-model-from-selection', 'select_id' => '%s'], + 'anchorOptions' => ['onclick' => 'addMultiSelection(\'selected-%s\');return false;', + 'class' => 'selected-%s'], 'icon' => 'cancel', 'label' => $this->_remove_leaf, 'condition' => $this->_leaf_condition], @@ -35,6 +37,10 @@ class ZendAfi_Controller_Plugin_MultiSelection_LeafActions extends ZendAfi_Contr 'select_id' => '%s'], 'icon' => 'basket', 'label' => $this->_add_leaf, + + 'anchorOptions' => ['onclick' => 'addMultiSelection(\'selected-%s\');return false;', + 'class' => 'selected-%s'], + 'condition' => function($model) { return !call_user_func($this->_leaf_condition, $model); diff --git a/library/ZendAfi/Form/Admin/AdminVar/MultiInput.php b/library/ZendAfi/Form/Admin/AdminVar/MultiInput.php index 6318a64c4085cd1e29e9373365574c19e4992021..318da985aa4ca385f7f2b6956c74e806f3a9ac7b 100644 --- a/library/ZendAfi/Form/Admin/AdminVar/MultiInput.php +++ b/library/ZendAfi/Form/Admin/AdminVar/MultiInput.php @@ -21,7 +21,9 @@ class ZendAfi_Form_Admin_AdminVar_MultiInput extends ZendAfi_Form_Admin_AdminVar { - protected $_fields = []; + protected + $_fields = [], + $_fixed = false; public function setFields($fields) { @@ -30,11 +32,18 @@ class ZendAfi_Form_Admin_AdminVar_MultiInput extends ZendAfi_Form_Admin_AdminVar } + public function setFixed($flag) { + $this->_fixed = $flag; + return $this; + } + + public function addVariableEditElement() { $this->addElement('multiInput', 'valeur', ['label' => $this->_('Liste de valeurs'), - 'fields' => $this->_fields]); + 'fields' => $this->_fields, + 'fixed' => $this->_fixed]); } diff --git a/library/ZendAfi/Form/Admin/SessionActivity.php b/library/ZendAfi/Form/Admin/SessionActivity.php index 13947999e7367eab3dd3104489f8f6bee7595a21..6195d41f33e9dfc72e8e85cf9240a7d54d23bdb1 100644 --- a/library/ZendAfi/Form/Admin/SessionActivity.php +++ b/library/ZendAfi/Form/Admin/SessionActivity.php @@ -21,6 +21,15 @@ class ZendAfi_Form_Admin_SessionActivity extends ZendAfi_Form { + + public static function newWith($datas = [], $custom_form = null) { + $form = parent::newWith($datas, $custom_form); + $form->_addDates($datas['all_day'], $datas['date_debut'], $datas['date_fin']); + + return $form; + } + + public function init() { parent::init(); @@ -40,13 +49,20 @@ class ZendAfi_Form_Admin_SessionActivity extends ZendAfi_Form { $this ->setAttrib('id', 'sessionForm') ->setMethod('post') - ->addElement('datePicker', 'date_debut', ['label' => $this->_('Date début'), - 'size' => 10, - 'required' => true, - 'allowEmpty' => false]) + ->addElement('dateRangePicker', + 'activity_range', + ['label' => $this->_("Date de l'activitée"), + 'required' => true, + 'start' => ['name' => 'date_debut', + 'allowEmpty' => false, + 'dateOnly' => false, + 'toggleAllDay' => 'all_day'], + 'end' => ['name' => 'date_fin', + 'dateOnly' => false, + 'toggleAllDay' => 'all_day']]) - ->addElement('datePicker', 'date_fin', ['label' => $this->_('Date fin'), - 'size' => 10]) + ->addElement('checkbox', 'all_day', + ['label' => $this->_("L'activitée dure toute la journée")]) ->addElement('datePicker', 'date_limite_inscription', ['label' => $this->_('Date limite d\'inscription'), @@ -104,9 +120,21 @@ class ZendAfi_Form_Admin_SessionActivity extends ZendAfi_Form { } + protected function _addDates($all_day, $start, $end) { + $activity_range = $this->getElement('activity_range'); + $activity_range->setStartValue($start)->setEndValue($end); + + if (!$all_day) + return $this; + + $activity_range->setDateOnly(true); + return $this; + } + + protected function _addChildrenEffectifs() { - $elements = ['date_debut', - 'date_fin', + $elements = ['activity_range', + 'all_day', 'date_limite_inscription', 'effectif_min', 'effectif_max', @@ -128,6 +156,7 @@ class ZendAfi_Form_Admin_SessionActivity extends ZendAfi_Form { ->_addNumber('effectif_max', $this->_('Adultes maximum')) ->_addNumber('effectif_child_min', $this->_('Enfants minimum')) ->_addNumber('effectif_child_max', $this->_('Enfants maximum')) + ->_addNumber('age_child_max', $this->_('Âge maximum des enfants')) ->_addNumber('effectif_inscription_max', $this->_('Adultes maximum par inscription')) ->_addNumber('effectif_inscription_child_max', $this->_('Enfants maximum par inscription')); @@ -145,6 +174,7 @@ class ZendAfi_Form_Admin_SessionActivity extends ZendAfi_Form { 'effectif_max', 'effectif_child_min', 'effectif_child_max', + 'age_child_max', 'effectif_inscription_max', 'effectif_inscription_child_max'], 'quotas', diff --git a/library/ZendAfi/Form/Configuration/Domain.php b/library/ZendAfi/Form/Configuration/Domain.php index 805b247c442f592b930a2184620cca0a50bc0431..99eaa12bdb3086885d065b99fa62bd2b23d331a3 100644 --- a/library/ZendAfi/Form/Configuration/Domain.php +++ b/library/ZendAfi/Form/Configuration/Domain.php @@ -160,7 +160,7 @@ class ZendAfi_Form_Configuration_Domain extends ZendAfi_Form { ; $thesaurus_elements = []; - foreach(Class_CodifThesaurus::getIndices('root') as $thesaurus) { + foreach(Class_CodifThesaurus::findAllForDomainCriteria() as $thesaurus) { $name = $thesaurus->getIdThesaurus(); $this->addElement('listeSuggestion', $name, diff --git a/library/ZendAfi/Form/SessionActivityInscription.php b/library/ZendAfi/Form/SessionActivityInscription.php index 8bc92bbe8fd6ebccb475f6d2fd69dcb0f6b01356..6b15526019405a9c7aa188464d9bec596ae2b54e 100644 --- a/library/ZendAfi/Form/SessionActivityInscription.php +++ b/library/ZendAfi/Form/SessionActivityInscription.php @@ -32,8 +32,7 @@ class ZendAfi_Form_SessionActivityInscription extends ZendAfi_Form { 'min' => 0, 'max' => 0]) ->addElement('number', 'children', - ['label' => $this->_('Nombre d\'enfants'), - 'value' => 0, + ['value' => 0, 'min' => 0, 'max' => 0]) @@ -58,6 +57,17 @@ class ZendAfi_Form_SessionActivityInscription extends ZendAfi_Form { : $this->getElement('children') ->setAttrib('max', $session->getNextChildrenMax()); + $this->_updateChildrenlabel($session); + return parent::populate($datas); } + + + protected function _updateChildrenlabel($session) { + if (!$element_children = $this->getElement('children')) + return; + + $element_children->setLabel($this->_('Nombre d\'enfants (âge max %s)', + $session->getAgeChildMax())); + } } diff --git a/library/ZendAfi/View/Helper/Abonne/AvailableActivities.php b/library/ZendAfi/View/Helper/Abonne/AvailableActivities.php index 178f49cfc6ccc3d23d6867b7a375706ffa973ac3..f4ba61ac119fc1f62ad1607e1cfa5252721dbb2b 100644 --- a/library/ZendAfi/View/Helper/Abonne/AvailableActivities.php +++ b/library/ZendAfi/View/Helper/Abonne/AvailableActivities.php @@ -80,9 +80,9 @@ class ZendAfi_View_Helper_Abonne_AvailableActivities extends ZendAfi_View_Helper $model->getLabel())]]; if (($user = Class_Users::getIdentity()) && $user->hasRightRegisterActivity()) - $items[] = ['url' => $this->_admin_link . '/id/%s', + $items[] = ['url' => $this->_admin_link . '/id/%s/search_session_activity_subscription_status/all', 'icon' => 'users', - 'label' => $this->_('Gérer les inscriptions'), + 'label' => $this->_('Nouvelle inscription'), 'anchorOptions' => ['target' => '_blank', 'class' => 'menu_admin_front_anchor']]; diff --git a/library/ZendAfi/View/Helper/Plugin/MultiSelection/Widget.php b/library/ZendAfi/View/Helper/Plugin/MultiSelection/Widget.php index a2e18f5390059cc37c19784b8f9e339e572f1611..78db27f53d698252edeac70d1232d70e728a092a 100644 --- a/library/ZendAfi/View/Helper/Plugin/MultiSelection/Widget.php +++ b/library/ZendAfi/View/Helper/Plugin/MultiSelection/Widget.php @@ -35,11 +35,34 @@ class ZendAfi_View_Helper_Plugin_MultiSelection_Widget extends ZendAfi_View_Help $_category_label; public function Plugin_MultiSelection_Widget($multi_selection) { + $this->_current_skin = Class_Admin_Skin::current(); + + $icon_add = $this->_current_skin->renderActionIconOn('basket', + $this->view, + ['alt' => $this->_('Ajouter à la sélection'), + 'title' => $this->_('Ajouter'), + 'class' => 'ico']); + $icon_remove = $this->_current_skin->renderActionIconOn('cancel', + $this->view, + ['alt' => $this->_('Supprimer de la sélection'), + 'title' => $this->_('Supprimer'), + 'class' => 'ico']); + + + Class_ScriptLoader::getInstance() + ->addInlineScript(" + var icon_basket = '".$icon_add."'; + var icon_delete = '".$icon_remove."';") + + ->addAdminScript('multi_selection/multi_selection.js'); + if(!$multi_selection) return ''; if(0 == count($multi_selection->getModels())) - return ''; + return $this->_tag('div', + $this->_tag('div', '', + ['class' => 'selected_items_widget show'])); $multi_selection->acceptWidgetVisitor($this); return $this->_render(); diff --git a/library/ZendAfi/View/Helper/RenderModelAction.php b/library/ZendAfi/View/Helper/RenderModelAction.php index 8b35b1094267d11a48dfc2205416af64eef16d9f..1e4b08798ba992f3c168699a002673178c68ecb8 100644 --- a/library/ZendAfi/View/Helper/RenderModelAction.php +++ b/library/ZendAfi/View/Helper/RenderModelAction.php @@ -62,7 +62,7 @@ class ZendAfi_View_Helper_RenderModelAction extends ZendAfi_View_Helper_BaseHelp $url = $this->_initUrl($model); $icon = $this->_initIcon($model); - $anchorOptions = $this->_initAnchorOptions($model->getId(), $url); + $anchorOptions = $this->_initAnchorOptions($this->_getModelId($model), $url); $title = $this->_initTitle($model); @@ -131,6 +131,7 @@ class ZendAfi_View_Helper_RenderModelAction extends ZendAfi_View_Helper_BaseHelp && (false === strpos($url, $_SERVER['REQUEST_URI']))) return $attribs; + isset($attribs['class']) ? ($attribs['class'] .= ' selected') : ($attribs['class'] = 'selected'); diff --git a/library/ZendAfi/View/Helper/TagSessionActivityInscription.php b/library/ZendAfi/View/Helper/TagSessionActivityInscription.php index c77091dc6d084e09e46da79d71e72df908675044..91948df558eaa46db6cea07c3da7fd79b75aee22 100644 --- a/library/ZendAfi/View/Helper/TagSessionActivityInscription.php +++ b/library/ZendAfi/View/Helper/TagSessionActivityInscription.php @@ -85,10 +85,11 @@ class ZendAfi_View_Helper_TagSessionActivityInscription extends ZendAfi_View_Hel return ' ' . $this->_tagAnchor($this->_url(['module' => 'admin', 'controller' => 'session-activity', 'action' => 'inscriptions', - 'id' => $this->_session_activity->getId() + 'id' => $this->_session_activity->getId(), + 'search_session_activity_subscription_status' => 'all' ], null, true), - $this->_('Gérer les inscriptions'), + $this->_('Nouvelle inscription'), ['target' => '_blank', 'class' => 'menu_admin_front_anchor']); } diff --git a/library/templates/Intonation/Library/Link/AdminSessionActivityRegistrations.php b/library/templates/Intonation/Library/Link/AdminSessionActivityRegistrations.php index 32526cd97cde6437c2ebc79bf21b61066673a1a1..9465eaf81da8283f56bf1addcbd86af2a0712beb 100644 --- a/library/templates/Intonation/Library/Link/AdminSessionActivityRegistrations.php +++ b/library/templates/Intonation/Library/Link/AdminSessionActivityRegistrations.php @@ -34,10 +34,11 @@ class Intonation_Library_Link_AdminSessionActivityRegistrations extends Intonati ->setUrl($view->url(['module' => 'admin', 'controller' => 'session-activity', 'action' => 'inscriptions', - 'id' => $session->getId()], + 'id' => $session->getId(), + 'search_session_activity_subscription_status' => 'all'], null, true)) - ->setText($t->_('Gérer les inscriptions')) - ->setTitle($t->_('Gérer les inscriptions de l\'activité %s', + ->setText($t->_('Nouvelle inscription')) + ->setTitle($t->_('Nouvelle inscription à l\'activité %s', $session->getLibelleActivity())) ->setImage(Class_Template::current()->getIco($view, 'team', 'library')) ->setAttribs(['target' => '_blank']) diff --git a/public/admin/js/multi_selection/multi_selection.js b/public/admin/js/multi_selection/multi_selection.js new file mode 100644 index 0000000000000000000000000000000000000000..586046a6b56d63322fbc255042fbe6caad163d69 --- /dev/null +++ b/public/admin/js/multi_selection/multi_selection.js @@ -0,0 +1,45 @@ +/** + * 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 + */ + + +function addMultiSelection(id) { + var url = $('a.'+id+':first').attr('href'); + $.getJSON(url.replace('-selection','-selection-ajax',url), function(data) { + $('.selected_items_widget:first').html(data['selection']); + if (data['response'] != 'ok' ) { + $('.selected_items_widget:first').html(data['selection']+"<div class=\"popup_notification\">"+data['response']+"</div>"); + $('.popup_notification:first').dialog(); + return ; + } + var is_basket = url.indexOf('add-model')>-1; + var icon = (is_basket ? icon_delete : icon_basket); + + var url_href = (is_basket + ? url.replace(/add-model-to/g,'remove-model-from',url) + : url.replace(/remove-model-from/g,'add-model-to',url)); + + $('a.'+id).each (function() { + $(this).attr('href', url_href); + $(this).html(icon); + }); + + }); + return false; +} diff --git a/public/admin/js/multi_selection/test.js b/public/admin/js/multi_selection/test.js new file mode 100644 index 0000000000000000000000000000000000000000..4ccafbea056667d84a6a24b93e10eecfd1981b8c --- /dev/null +++ b/public/admin/js/multi_selection/test.js @@ -0,0 +1,62 @@ +/** + * 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 + */ + +var ajax_calls = []; + +$.getJSON = function(url, callback, c) { + ajax_calls.push(url); + return callback({'selection':'my selection', 'response':'ok'}); +}; + + +test('call url with ajax', function() { + $('#first').click(); + equal(ajax_calls[0], '/admin/cms/add-model-to-selection-ajax/page/1/id_cat/7', 'URL has been called ' + ajax_calls[0]); +}); + + +test('change basket to remove all links and images', function() { + var first= $("#first"); + $('#first').click(); + $('#first').click(); + var second= $("#first"); + equal(first.attr("href"), '/admin/cms/remove-model-from-selection/page/1/id_cat/7' ); + equal(second.attr("href"), '/admin/cms/remove-model-from-selection/page/1/id_cat/7' ); + var img= $("#first> img"); + equal(img.attr("src"), "/public/admin/skins/bokeh74/icons/actions/cancel_24.png"); + + var img_two= $("#second> img"); + equal(img_two.attr("src"), "/public/admin/skins/bokeh74/icons/actions/cancel_24.png"); + +}); + + + +test('scenario with 3 clicks', function() { + $('#first').click(); + var myanchor= $("#first"); + equal(myanchor.attr("href"), '/admin/cms/add-model-to-selection/page/1/id_cat/7' ); + $('#first').click(); + equal(myanchor.attr("href"), '/admin/cms/remove-model-from-selection/page/1/id_cat/7' ); + $('#first').click(); + equal(myanchor.attr("href"), '/admin/cms/add-model-to-selection/page/1/id_cat/7' ); +}); + + diff --git a/public/admin/js/multi_selection/tests.html b/public/admin/js/multi_selection/tests.html new file mode 100644 index 0000000000000000000000000000000000000000..0d43492e1c14c53f5ac75238409f353a68adec27 --- /dev/null +++ b/public/admin/js/multi_selection/tests.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<!-- +/** + * 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 + */ +--> +<html> +<head> + <meta charset="utf-8"> + <title>QUnit tests</title> + <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css"> +</head> +<body> + <div id="qunit"></div> + <div id="qunit-fixture"></div> + <script type="text/javascript" src="../jquery-3.2.1.min.js"></script> + + <script src="multi_selection.js"></script> + <script src="http://code.jquery.com/qunit/qunit-1.13.0.js"></script> + <script src="test.js"></script> + <script> var icon_basket = '<img src="/public/admin/skins/bokeh74/icons/actions/panier_24.png" alt="Ajouter à la sélection" title="Ajouter" class="ico">'; + var icon_delete = '<img src="/public/admin/skins/bokeh74/icons/actions/cancel_24.png" alt="Supprimer de la sélection" title="Supprimer" class="ico">';</script> + <a class="select-111" id="first" href="/admin/cms/add-model-to-selection/page/1/id_cat/7" onclick="addMultiSelection('select-111');return false;"><img src="" alt="Ajouter"> </a> + <a class="select-111" id="second" href="/admin/cms/add-model-to-selection/page/1/id_cat/7" onclick="addMultiSelection('select-111');return false;"><img src="" alt="Ajouter"> </a> +</body> +</html> diff --git a/scripts/reindex_local_items_facets.php b/scripts/reindex_local_items_facets.php new file mode 100644 index 0000000000000000000000000000000000000000..e1f660ec9c263aa5cb183712495e21ee2749dc17 --- /dev/null +++ b/scripts/reindex_local_items_facets.php @@ -0,0 +1,59 @@ +<?php +error_reporting(E_ALL^E_DEPRECATED); +require __DIR__ . '/../console.php'; + +echo "\n\nWelcome to the iReindex Items Facets 2000 X tool by @patbator, proudly RTed by @lla \n\n"; + +echo "\n\nWill update items facets of " . Class_Notice::count() . " records in database\n\n"; + +class Script_ItemsFacets_Updater { + use Trait_MemoryCleaner; + + protected + $_adapter, + $_last_id = 0, + $_page = 1; + + public function __construct() { + $this->_adapter = Zend_Db_Table_Abstract::getDefaultAdapter(); + } + + + public function run() { + while ($records = Class_Notice::findAllBy(['where' => 'id_notice > ' . (int)$this->_last_id, + 'limit' => '1000'])) + $this->_runPage($records); + + return $this; + } + + + protected function _runPage($records) { + echo "\npage: ". $this->_page ."\n"; + $this->_page++; + + foreach($records as $record) + $this->_runOne($record); + + $this->_last_id = $record->getId(); + $this->_cleanMemory(); + return $this; + } + + + protected function _runOne($record) { + $old = $record->getFacettes(); + $record->updateFacetsFromExemplaires(); + if ($old != $record->getFacettes()) + $record->save(); + + echo '.'; + + return $this; + } +} + +$updater = new Script_ItemsFacets_Updater; +$updater->run(); + +echo "\n\nDONE !!!!\n\n"; diff --git a/tests/application/modules/admin/controllers/ActivityControllerTest.php b/tests/application/modules/admin/controllers/ActivityControllerTest.php index 8d36bbf1b1cff3e1068dcaa98a086ca94b93032d..f6ba0cde41ad0f459cffffb33900804556f4370b 100644 --- a/tests/application/modules/admin/controllers/ActivityControllerTest.php +++ b/tests/application/modules/admin/controllers/ActivityControllerTest.php @@ -787,7 +787,9 @@ class Admin_ActivityControllerEditSessionLearningJavaFevrierTest extends Admin_ -class Admin_ActivityControllerEditSessionLearningJavaMars27Test extends Admin_ActivityControllerTestCase { +class Admin_ActivityControllerEditSessionLearningJavaMars27Test + extends Admin_ActivityControllerTestCase { + public function setUp() { parent::setUp(); $this->dispatch('/admin/session-activity/edit/id/32', true); @@ -808,11 +810,17 @@ class Admin_ActivityControllerEditSessionLearningJavaMars27Test extends Admin_A /** @test */ - function inputDateFinShouldContains28_03_2012() { + function inputDateFinShouldContains29_03_2012() { $this->assertXPath('//form[@id="sessionForm"]//input[@name="date_fin"][@value="29/03/2012"]'); } + /** @test */ + function inputCheckboxAlldayShouldBePresent() { + $this->assertXPath('//form[@id="sessionForm"]//input[@name="all_day"][@value="1"]'); + } + + /** @test */ function inputDateLimiteInscriptionShouldContains05_03_2012() { $this->assertXPath('//form[@id="sessionForm"]//input[@name="date_limite_inscription"][@value="05/03/2012"]'); @@ -860,7 +868,9 @@ class Admin_ActivityControllerEditSessionLearningJavaMars27Test extends Admin_A -class Admin_ActivityControllerDeleteSessionLearningJavaMars27Test extends Admin_ActivityControllerTestCase { +class Admin_ActivityControllerDeleteSessionLearningJavaMars27Test + extends Admin_ActivityControllerTestCase { + public function setUp() { parent::setUp(); $this->dispatch('/admin/session-activity/delete/year/2012/id/32', true); @@ -884,7 +894,9 @@ class Admin_ActivityControllerDeleteSessionLearningJavaMars27Test extends Admin -class Admin_ActivityControllerDeleteActivityLearningJavaTest extends Admin_ActivityControllerTestCase { +class Admin_ActivityControllerDeleteActivityLearningJavaTest + extends Admin_ActivityControllerTestCase { + public function setUp() { parent::setUp(); $this->dispatch('/admin/activity/delete/id/3/year/2012'); @@ -1141,7 +1153,9 @@ class Admin_ActivityControllerPostSessionLearnJavaTest extends Admin_ActivityCon -class Admin_ActivityControllerPostSessionLearnJavaWithInvalidDataTest extends Admin_ActivityControllerTestCase { +class Admin_ActivityControllerPostSessionLearnJavaWithInvalidDataTest + extends Admin_ActivityControllerTestCase { + public function setUp() { parent::setUp(); $this->postDispatch('/admin/session-activity/edit/id/32', @@ -1174,12 +1188,68 @@ class Admin_ActivityControllerPostSessionLearnJavaWithInvalidDataTest extends A public function errorsShouldContainsDateLimiteInscriptionAfterDateDebut() { $this->assertXPathContentContains('//ul[@class="errors"]//li', "La date de début est requise"); } + + + /** @test */ + public function pageShouldNotContainsInscriptionMaxAdultesRequired() { + $this->assertNotXPathContentContains('//ul[@class="errors"]//li', + "Adultes maximum par inscription doit être renseigné"); + } + + + /** @test */ + public function pageShouldNotContainsInscriptionMaxEnfantsRequired() { + $this->assertNotXPathContentContains('//ul[@class="errors"]//li', + "Enfants maximum par inscription doit être renseigné"); + } +} + + + + +class Admin_ActivityControllerPostSessionLearnJavaWithAllDayFalseTest + extends Admin_ActivityControllerTestCase { + + public function setUp() { + parent::setUp(); + Class_SessionActivity::find(32) + ->setDateDebut('2012-03-27 08:00') + ->setDateFin('2012-03-27 18:00') + ->setAllDay(0); + $this->dispatch('/admin/session-activity/edit/id/32'); + } + + + /** @test */ + function inputDateDebutShouldContains27_03_2012_0800() { + $this->assertXPath('//form[@id="sessionForm"]//input[@name="date_debut"][@value="27/03/2012 08:00"]'); + } + + + /** @test */ + function inputDateFinShouldContains27_03_2012_1800() { + $this->assertXPath('//form[@id="sessionForm"]//input[@name="date_fin"][@value="27/03/2012 18:00"]'); + } + + + /** @test */ + function inputCheckboxAlldayShouldBePresent() { + $this->assertXPath('//form[@id="sessionForm"]//input[@name="all_day"][@value="0"]'); + } + + + /** @test */ + public function javascriptRangePickerShouldBePresent() { + $this->assertXPathContentContains('//script', '$("#all_day").click(function()'); + } } -class Admin_ActivityControllerPostSessionLearnJavaWithInvalidDateFinTest extends Admin_ActivityControllerTestCase { +class Admin_ActivityControllerPostSessionLearnJavaWithInvalidDateFinTest + extends Admin_ActivityControllerTestCase { + public function setUp() { parent::setUp(); $this->postDispatch('/admin/session-activity/edit/id/32', @@ -1304,7 +1374,8 @@ class Admin_ActivityControllerPostAddSessionToActivityLearningPythonTest /** @test */ function getActivityShouldReturnActivityLearnPython() { - $this->assertEquals($this->_learn_python->getLibelle(), $this->session->getActivity()->getLibelle()); + $this->assertEquals($this->_learn_python->getLibelle(), + $this->session->getActivity()->getLibelle()); } @@ -1384,7 +1455,7 @@ class Admin_ActivityControllerPostAddSessionToActivityLearningPythonTest public function linkedArticleContentChecks() { - return [['<p>Discover Python language</p>'], + return [['On charme les serpents'], ['<dd class="registration_limitdate">10 février 2010</dd>'], ['<dd class="session_hours">9h - 18h</dd>'], ['<dd class="session_length">3 h</dd>'], @@ -1406,7 +1477,9 @@ class Admin_ActivityControllerPostAddSessionToActivityLearningPythonTest -class Admin_ActivityControllerPostAddSessionToActivityLearningPythonWithWrongIntervenantsTest extends Admin_ActivityControllerTestCase { +class Admin_ActivityControllerPostAddSessionToActivityLearningPythonWithWrongIntervenantsTest + extends Admin_ActivityControllerTestCase { + /** @test */ public function sessionSaveShoulNotHaveBeenCalled() { $this->postDispatch('/admin/session-activity/add/activity_id/12', @@ -1953,26 +2026,47 @@ class ActivityControllerRefusTestCase extends ActivityControllerImpressionsTestC -class Admin_ActivityControllerLinkedArticleWithoutArticleActionTest +abstract class Admin_ActivityControllerLinkedArticleTestCase extends Admin_ActivityControllerTestCase { + protected $_linked_article; + public function setUp() { parent::setUp(); // fixtures generate article on save, // we want to ensure real life case with no existing linked article - Class_SessionActivity::find(32)->getArticle()->delete(); + $this->_updateModels(); + $this->_session_java_mars->getArticle()->delete(); Class_SessionActivity::clearCache(); Class_Article::clearCache(); - $this->dispatch('/admin/session-activity/linked-article/id/32', true); - $this->article = Class_SessionActivity::find(32)->getArticle(); + $this->dispatch('/admin/session-activity/linked-article/id/32'); + $this->_linked_article = Class_SessionActivity::find(32)->getArticle(); + } + + + protected function _updateModels() { + } +} + + + + +class Admin_ActivityControllerLinkedArticleWithoutArticleActionTest + extends Admin_ActivityControllerLinkedArticleTestCase { + + protected function _updateModels() { + $this->_session_java_mars + ->setContenu('') + ->save(); } /** @test */ public function linkToEditShouldBePresent() { - $this->assertXpath('//a[contains(@href, "/admin/cms/edit/id/' . $this->article->getId() . '")][@data-popup="true"]'); + $this->assertXpath('//a[contains(@href, "/admin/cms/edit/id/' + . $this->_linked_article->getId() . '")][@data-popup="true"]'); } @@ -1980,6 +2074,70 @@ class Admin_ActivityControllerLinkedArticleWithoutArticleActionTest public function linkToRegenerateShouldBePresent() { $this->assertXpath('//a[contains(@href, "/admin/session-activity/linked-article-regenerate/id/32")]'); } + + + /** @test */ + public function linkedArticleShouldHaveAlldayChecked() { + $this->assertEquals(1, $this->_linked_article->getAllDay()); + } + + + /** @test */ + public function linkedArticleEventsDebutShouldBe2012_03_27() { + $this->assertEquals('2012-03-27', $this->_linked_article->getEventsDebut()); + } + + + /** @test */ + public function linkedArticleEventsFinShouldBe2012_03_29() { + $this->assertEquals('2012-03-29', $this->_linked_article->getEventsFin()); + } + + + /** @test */ + public function linkedArticleContenuShouldContainsActivityDescription() { + $this->assertContains('Here you will learn some old and boring stuff', + $this->_linked_article->getContenu()); + } +} + + + + +class Admin_ActivityControllerLinkedArticleWithoutArticleAndAllDayActionTest + extends Admin_ActivityControllerLinkedArticleTestCase { + + protected function _updateModels() { + $this->_session_java_mars + ->setAllDay(0) + ->setDateDebut('2012-03-27 08:00') + ->setDateFin('2012-03-29 18:00') + ->save(); + } + + + /** @test */ + public function linkedArticleShouldHaveAlldayUnchecked() { + $this->assertEquals(0, $this->_linked_article->getAllDay()); + } + + + /** @test */ + public function linkedArticleEventsDebutShouldBe2012_03_27_0800() { + $this->assertEquals('2012-03-27 08:00', $this->_linked_article->getEventsDebut()); + } + + + /** @test */ + public function linkedArticleEventsFinShouldBe2012_03_29_1800() { + $this->assertEquals('2012-03-29 18:00', $this->_linked_article->getEventsFin()); + } + + + /** @test */ + public function linkedArticleContenuShouldContainsSessionActivityContenu() { + $this->assertContains('Intro à la syntaxe', $this->_linked_article->getContenu()); + } } diff --git a/tests/application/modules/admin/controllers/CatalogueControllerTest.php b/tests/application/modules/admin/controllers/CatalogueControllerTest.php index 4275650e7e8098756e4ede6a8a045895836e7328..11f6cbf10560ed1f9ba7dd8d02fcf12d947f8785 100644 --- a/tests/application/modules/admin/controllers/CatalogueControllerTest.php +++ b/tests/application/modules/admin/controllers/CatalogueControllerTest.php @@ -698,12 +698,12 @@ class CatalogueControllerEditCatalogueTest extends AdminCatalogueControllerTestC $this->onLoaderOfModel('Class_CodifThesaurus') ->whenCalled('findAllBy') - ->with(['where' => 'code not in ("Nouveauté par bibliothèque", "Nouveauté par annexe", "Catalogue") and LENGTH(id_thesaurus) in (1,4)', + ->with(['where' => 'id_thesaurus not in ("NRNR", "NNNN", "NANA", "CCCC") and LENGTH(id_thesaurus) in (1,4)', 'order' => 'id_thesaurus']) - ->answers([Class_CodifThesaurus::find(1), - Class_CodifThesaurus::find(2)]); + ->answers([Class_CodifThesaurus::find(1), Class_CodifThesaurus::find(2)]) + ; - $this->dispatch('/admin/catalogue/edit/id_catalogue/6', true); + $this->dispatch('/admin/catalogue/edit/id_catalogue/6'); } diff --git a/tests/application/modules/admin/controllers/SessionActivityControllerTest.php b/tests/application/modules/admin/controllers/SessionActivityControllerTest.php index 99e371d2ffa82f595c96be04b07ccbecd49b2bd9..4da7ec70e6aa01a8bf55f114cebb4534a2cb5270 100644 --- a/tests/application/modules/admin/controllers/SessionActivityControllerTest.php +++ b/tests/application/modules/admin/controllers/SessionActivityControllerTest.php @@ -107,6 +107,7 @@ abstract class Admin_SessionActivityControllerTestCase extends Admin_AbstractCon 'effectif_max' => 25, 'effectif_child_min' => 1, 'effectif_child_max' => 5, + 'age_child_max' => 5, 'effectif_inscription_max' => 2, 'effectif_inscription_child_max' => 3, 'duree'=> 8, @@ -221,193 +222,11 @@ class Admin_SessionActivityControllerInscriptionsSessionMarsJavaTest -class Admin_SessionActivityControllerInscriptionsSessionMarsJavaWithQuotasTest - extends Admin_SessionActivityControllerInscriptionsSessionMarsJavaTestCase { - - protected function _fixtureQuotas() { - parent::_fixtureQuotas(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', '1'); - } - - - /** @test */ - public function pageShouldContainsCounters() { - $this->assertXPathContentContains('//a[contains(@href, "/session-activity/inscriptions/id/32")]', - '3 / 6-30', - $this->_response->getBody()); - } - - - /** @test */ - public function pageShouldContainsParticipantsColumn() { - $this->assertXPathContentContains('//th', 'Participants'); - } - - - /** @test */ - public function pageShouldContainsAttendees() { - $this->assertXPathContentContains('//td', '1 adulte, 2 enfants'); - } - - - /** @test */ - public function pageShouldContainsLinkToEditAttendees() { - $this->assertXPath('//a[contains(@href, "/admin/session-activity-inscription/edit/id/165")]'); - } - - - /** @test */ - public function pageShouldContainsLinkToSubscribePistache() { - $this->assertXPath('//a[contains(@href, "/admin/session-activity-inscription/subscribe/id/32/stagiaire_id/10")][not(@onclick)][@data-popup]'); - } -} - - - - -class Admin_SessionActivityControllerInscriptionsSessionMarsJavaWithQuotasAndLegacyRegistrationTest - extends Admin_SessionActivityControllerInscriptionsSessionMarsJavaTestCase { - - protected function _fixtureQuotas() { - parent::_fixtureQuotas(); - - $legacy_registration = $this->fixture('Class_SessionActivityInscription', - ['id' => 38839, - 'session_activity_id' => 32, - 'stagiaire_id' => 999838]); - Class_SessionActivity::find(32) - ->addSessionActivityInscription($legacy_registration); - - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', '1'); - } - - - /** @test */ - public function pageShouldContainsCountersWithLegacyRegistration() { - $this->assertXPathContentContains('//a[contains(@href, "/session-activity/inscriptions/id/32")]', - '4 / 6-30'); - } -} - - - - class Admin_SessionActivityControllerEditQuotasTest extends Admin_SessionActivityControllerTestCase { - public function quotasElements() { - return [['effectif_min'], - ['effectif_child_min'], - ['effectif_max'], - ['effectif_child_max'], - ['effectif_inscription_max'], - ['effectif_inscription_child_max']]; - } - - - /** - * @test - * @dataProvider quotasElements - */ - public function withQuotasFormShouldContainsElement($element) { - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', '1'); - $this->dispatch('/admin/session-activity/edit/id/32'); - $this->assertXPath('//fieldset[@id="fieldset-quotas"]//input[@name="' . $element . '"][@required="required"][@type="number"][@min="0"]'); - } - - /** @test */ public function withoutQuotasFormShouldNotContainChildrenElement() { $this->dispatch('/admin/session-activity/edit/id/32'); $this->assertNotXPath('//input[@name="effectif_child_min"][@required="required"][@type="number"]'); } } - - - - -class Admin_SessionActivityControllerInvalidPostQuotasTest - extends Admin_SessionActivityControllerTestCase { - - protected $_post_values = ['effectif_child_min' => 'chaine', - 'effectif_child_max' => 'chaine', - 'effectif_min' => 'chaine', - 'effectif_max' => 'chaine', - 'effectif_inscription_max' => 'chaine', - 'effectif_inscription_child_max' => 'chaine']; - - - public function setUp() { - parent::setUp(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', '1'); - } - - - public function quotasElements() { - return array_map(function($name) { return [$name]; }, - array_keys($this->_post_values)); - } - - - /** - * @test - * @dataProvider quotasElements - */ - public function pageShouldContainErrorNotIntegerFor($element) { - $this->postDispatch('admin/session-activity/edit/id/32', $this->_post_values); - $this->assertXPathContentContains('//ul[preceding-sibling::input[@name="' . $element . '"]][@class="errors"]', - "'chaine' n'est pas un nombre entier"); - } - - - /** @test */ - public function minGreaterThanMaxShouldDisplayError() { - $this->postDispatch('admin/session-activity/edit/id/32', ['effectif_child_min' => 30, - 'effectif_child_max' => 10]); - $this->assertXPathContentContains('//ul[@class="errors"]', - 'L\'effectif enfants maximum doit être supérieur ou égal à l\'effectif enfants minimum'); - } - - - /** @test */ - public function inscriptionMaxGreaterThanMaxShouldDisplayError() { - $this->postDispatch('admin/session-activity/edit/id/32', ['effectif_inscription_max' => 30, - 'effectif_max' => 10]); - $this->assertXPathContentContains('//ul[@class="errors"]', - 'L\'effectif maximum doit être supérieur ou égal à l\'effectif maximum par inscription'); - } - - - /** @test */ - public function inscriptionChildMaxGreaterThanMaxShouldDisplayError() { - $this->postDispatch('admin/session-activity/edit/id/32', ['effectif_inscription_child_max' => 10, - 'effectif_child_max' => 5]); - $this->assertXPathContentContains('//ul[@class="errors"]', - 'L\'effectif enfants maximum doit être supérieur ou égal à l\'effectif enfants maximum par inscription'); - } -} - - - - -class Admin_SessionActivityControllerExportInscriptionsWithQuotasTest - extends Admin_SessionActivityControllerTestCase { - - public function setUp() { - parent::setUp(); - Class_SessionActivity::find(32)->resetAttendees(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - $this->dispatch('/admin/session-activity/exportinscriptions/id/32'); - } - - - /** @test */ - public function exportShouldContainsEffectif6_30() { - $this->assertContains('Effectif;6-30', $this->_response->getBody()); - } - - - /** @test */ - public function exportShouldContainsAdultsAndChildrenNumber() { - $this->assertContains('Barroca;Patrick;Pat;user@server.org;;1;2', $this->_response->getBody()); - } -} \ No newline at end of file diff --git a/tests/application/modules/admin/controllers/SessionActivityInscriptionControllerTest.php b/tests/application/modules/admin/controllers/SessionActivityInscriptionControllerTest.php index a1bca6a6de62e12b193accb9d6332ad1a6a39fa1..7180c847cd8d4736517f36d9492386975e2a27a3 100644 --- a/tests/application/modules/admin/controllers/SessionActivityInscriptionControllerTest.php +++ b/tests/application/modules/admin/controllers/SessionActivityInscriptionControllerTest.php @@ -101,6 +101,7 @@ abstract class Admin_SessionActivityInscriptionControllerTestCase 'effectif_max' => 25, 'effectif_child_min' => 1, 'effectif_child_max' => 5, + 'age_child_max' => 5, 'effectif_inscription_max' => 2, 'effectif_inscription_child_max' => 2, 'duree'=> 8, @@ -294,282 +295,4 @@ class Admin_SessionActivityInscriptionControllerUnsubscribePatSessionMarsJavaTes public function removableShouldBeNotified() { $this->assertFlashMessengerContentContains('L\'utilisateur a bien été désinscrit'); } -} - - - - -class Admin_SessionActivityInscriptionControllerSubscribeWithQuotasTest - extends Admin_SessionActivityInscriptionControllerTestCase { - - public function setUp() { - parent::setUp(); - Class_SessionActivity::find(32)->resetAttendees(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - $this->dispatch('/admin/session-activity-inscription/subscribe/id/32/stagiaire_id/10'); - } - - - /** @test */ - public function pageShouldContainsSessionNavigation() { - $this->assertXPathContentContains('//div[contains(@class, "activities")]', - 'Learn Java'); - } - - - /** @test */ - public function inputAdultsShouldBePresent() { - $this->assertXPath('//input[@name="adults"]'); - } - - - /** @test */ - public function inputChildrenShouldBePresent() { - $this->assertXPath('//input[@name="children"]'); - } - - - /** @test */ - public function backButtonUrlShouldContainsSessionActivity32() { - $this->assertXPath('//button[contains(@data-url, "/admin/session-activity/inscriptions/id/32")]'); - } -} - - - - -class Admin_SessionActivityInscriptionControllerSubscribeWithQuotasPopupTest - extends Admin_SessionActivityInscriptionControllerTestCase { - - public function setUp() { - parent::setUp(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - $this->dispatch('/admin/session-activity-inscription/subscribe/id/32/stagiaire_id/10/render/popup'); - } - - - /** @test */ - public function popupShouldNotContainsSessionNavigation() { - $this->assertNotXPathContentContains('//div[contains(@class, "activities")]', - 'Learn Java'); - } -} - - - - -class Admin_SessionActivityInscriptionControllerPostWithQuotasTest - extends Admin_SessionActivityInscriptionControllerTestCase { - - public function setUp() { - parent::setUp(); - Class_SessionActivity::find(32)->resetAttendees(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - $this->postDispatch('/admin/session-activity-inscription/subscribe/id/32/stagiaire_id/10', - ['adults' => 1, - 'children' => 2]); - } - - - /** @test */ - public function shouldRedirectToActivityInscriptions() { - $this->assertRedirectTo('/admin/session-activity/inscriptions/id/32'); - } - - - /** @test */ - public function pistacheShouldBeSubscribed() { - $this - ->assertNotNull(Class_SessionActivityInscription::findFirstBy(['stagiaire_id' => 10, - 'session_activity_id' => 32])); - } -} - - - - -class Admin_SessionActivityInscriptionControllerSubscribePostWithQuotasMaxOverloadTest - extends Admin_SessionActivityInscriptionControllerTestCase { - - public function setUp() { - parent::setUp(); - Class_SessionActivity::find(32)->resetAttendees(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - $this->postDispatch('/admin/session-activity-inscription/subscribe/id/32/stagiaire_id/10', - ['adults' => 3, - 'children' => 3]); - } - - - /** @test */ - public function shouldRedirectToActivityInscriptions() { - $this->assertRedirectTo('/admin/session-activity/inscriptions/id/32'); - } - - - /** @test */ - public function pistacheShouldBeSubscribed() { - $this - ->assertNotNull(Class_SessionActivityInscription::findFirstBy(['stagiaire_id' => 10, - 'session_activity_id' => 32, - 'adults' => 3, - 'children' => 3])); - } -} - - - - -class Admin_SessionActivityInscriptionControllerEditWithQuotasTest - extends Admin_SessionActivityInscriptionControllerTestCase { - - public function setUp() { - parent::setUp(); - Class_SessionActivity::find(32)->resetAttendees(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - $this->dispatch('/admin/session-activity-inscription/edit/id/165'); - } - - - /** @test */ - public function pageShouldContainsSessionNavigation() { - $this->assertXPathContentContains('//div[contains(@class, "activities")]', - 'Learn Java'); - } - - - /** @test */ - public function inputAdultsShouldBePresent() { - $this->assertXPath('//input[@name="adults"][@value="1"]'); - } - - - /** @test */ - public function inputChildrenShouldBePresent() { - $this->assertXPath('//input[@name="children"][@value="2"]'); - } - - - /** @test */ - public function backButtonUrlShouldContainsSessionActivity32() { - $this->assertXPath('//button[contains(@data-url, "/admin/session-activity/inscriptions/id/32")]'); - } -} - - - - -class Admin_SessionActivityInscriptionControllerEditPostWithQuotasTest - extends Admin_SessionActivityInscriptionControllerTestCase { - - public function setUp() { - parent::setUp(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - $this->postDispatch('/admin/session-activity-inscription/edit/id/165', - ['adults' => 2, - 'children' => 2]); - - Class_SessionActivityInscription::clearCache(); - } - - - /** @test */ - public function shouldRedirectToActivityInscriptions() { - $this->assertRedirectTo('/admin/session-activity/inscriptions/id/32'); - } - - - /** @test */ - public function patRegistrationAdultsShouldBecome2() { - $this->assertEquals(2, Class_SessionActivityInscription::find(165)->getAdults()); - } - - - /** @test */ - public function patRegistrationChildrenShouldBecome2() { - $this->assertEquals(2, Class_SessionActivityInscription::find(165)->getChildren()); - } -} - - - - -class Admin_SessionActivityInscriptionControllerEditPostWithQuotasOverloadTest - extends Admin_SessionActivityInscriptionControllerTestCase { - - public function setUp() { - parent::setUp(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - $this->postDispatch('/admin/session-activity-inscription/edit/id/165', - ['adults' => 3, - 'children' => 3]); - - Class_SessionActivityInscription::clearCache(); - } - - - /** @test */ - public function shouldRedirectToActivityInscriptions() { - $this->assertRedirectTo('/admin/session-activity/inscriptions/id/32'); - } - - - /** @test */ - public function patRegistrationAdultsShouldBecome3() { - $this->assertEquals(3, Class_SessionActivityInscription::find(165)->getAdults()); - } - - - /** @test */ - public function patRegistrationChildrenShouldBecome3() { - $this->assertEquals(3, Class_SessionActivityInscription::find(165)->getChildren()); - } -} - - - - -class Admin_SessionActivityInscriptionControllerEditWithQuotasFullChildrenTest - extends Admin_SessionActivityInscriptionControllerTestCase { - - public function setUp() { - parent::setUp(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - Class_SessionActivity::find(32)->resetAttendees(); - Class_SessionActivity::find(32)->setEffectifChildMax(2); - $this->dispatch('/admin/session-activity-inscription/edit/id/165'); - } - - - /** @test */ - public function inputAdultsShouldBePresent() { - $this->assertXPath('//input[@name="adults"][@value="1"]'); - } - - - /** @test */ - public function inputChildrenShouldBePresent() { - $this->assertXPath('//input[@name="children"][@value="2"]'); - } -} - - - - -class Admin_SessionActivityInscriptionControllerSubscribeWithQuotasFullChildrenTest - extends Admin_SessionActivityInscriptionControllerTestCase { - - public function setUp() { - parent::setUp(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - Class_SessionActivity::find(32)->resetAttendees(); - Class_SessionActivity::find(32)->setEffectifChildMax(2); - $this->dispatch('/admin/session-activity-inscription/subscribe/id/32/stagiaire_id/10'); - } - - - /** @test */ - public function pageShouldContainNoMoreChildrenRoomMessage() { - $this->assertXPathContentContains('//div', 'Aucune place enfant disponible'); - } } \ No newline at end of file diff --git a/tests/application/modules/opac/controllers/AbonneControllerActivitiesTest.php b/tests/application/modules/opac/controllers/AbonneControllerActivitiesTest.php index 10268c58cc3ec08421e1e50cc0255ceabc4dd39f..2a220bdbd9728ac1a88e2408abfdbf4b4169bf6d 100644 --- a/tests/application/modules/opac/controllers/AbonneControllerActivitiesTest.php +++ b/tests/application/modules/opac/controllers/AbonneControllerActivitiesTest.php @@ -483,7 +483,8 @@ class AbonneControllerActivitiesListWithRightRegisterTest /** @test */ public function pageShouldContainsLinkToAdminSessionActivityInscriptions() { - $this->assertXPath('//a[contains(@href, "/admin/session-activity/inscriptions/id/31")]'); + $this->assertXPathContentContains('//a[contains(@href, "admin/session-activity/inscriptions/id/31/search_session_activity_subscription_status/all")][@target="_blank"]', + 'Nouvelle inscription'); } } @@ -614,174 +615,6 @@ class AbonneControllerActivitiesRegisteredActionTest -class AbonneControllerActivitiesRegisteredWithQuotasActionTest - extends AbstractAbonneControllerActivitiesTestCase { - - public function setUp() { - parent::setUp(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - $this->dispatch('/abonne/activities-registered'); - } - - - /** @test */ - public function adultsCountShouldBePresent() { - $this->assertXPathContentContains('//td', '1 adulte'); - } - - - /** @test */ - public function childrenCountShouldBePresent() { - $this->assertXPathContentContains('//td', '1 enfant'); - } - - - /** @test */ - public function rowShouldContainEditButton() { - $this->assertXPath('//td//a[contains(@href, "/abonne/edit-session/id/1")]'); - } -} - - - - -abstract class AbonneControllerActivitiesEditSessionWithQuotasTestCase - extends AbstractAbonneControllerActivitiesTestCase { - - protected $_inscription, - $_other_inscription; - - public function setUp() { - parent::setUp(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - $this->_session_python_juillet - ->resetAttendees() - ->setEffectifMax(5) - ->setEffectifChildMax(15) - ->setEffectifInscriptionMax(3) - ->setEffectifInscriptionChildMax(12); - - $this->_other_inscription = $this->_register(1, 1); - $this->_inscription = $this->_register(1, 1); - $this->_inscription->setStagiaire($this->_amadou) - ->assertSave(); - } - - - protected function _register($adults, $children) { - $inscription = Class_SessionActivityInscription::newInstance(['session_activity_id' => 121, - 'adults' => $adults, - 'children' => $children]); - $inscription->assertSave(); - - $this->_session_python_juillet->addSessionActivityInscription($inscription); - return $inscription; - } -} - - - - -class AbonneControllerActivitiesEditSessionWithQuotasActionTest - extends AbonneControllerActivitiesEditSessionWithQuotasTestCase { - - public function setUp() { - parent::setUp(); - $this->dispatch('/abonne/edit-session/id/' . $this->_inscription->getId()); - } - - - /** @test */ - public function inputAdultsShouldHaveValueOneAndMaxThree() { - $this->assertXPath('//input[@name="adults"][@value="1"][@max="3"]'); - } - - - /** @test */ - public function inputChildrenShouldHaveValueOneAndMaxTwelve() { - $this->assertXPath('//input[@name="children"][@value="1"][@max="12"]'); - } -} - - - - -class AbonneControllerActivitiesEditSessionWithQuotasPostTest - extends AbonneControllerActivitiesEditSessionWithQuotasTestCase { - - public function setUp() { - parent::setUp(); - $url = $_SERVER['HTTP_REFERER'] = '/abonne/edit-session/id/' . $this->_inscription->getId(); - - $this->postDispatch($url, ['adults' => 2, 'children' => 3]); - $this->_inscription = Class_SessionActivityInscription::find($this->_inscription->getId()); - } - - - /** @test */ - public function inscriptionAdultsShouldBeTwo() { - $this->assertEquals(2, $this->_inscription->getAdults()); - } - - - /** @test */ - public function inscriptionChildrenShouldBeThree() { - $this->assertEquals(3, $this->_inscription->getChildren()); - } - - - /** @test */ - public function shouldRedirectToActivities() { - $this->assertRedirectContains('/abonne/activities-registered'); - } -} - - - - -class AbonneControllerActivitiesEditSessionWithQuotasErrorsPostTest - extends AbonneControllerActivitiesEditSessionWithQuotasTestCase { - - public function setUp() { - parent::setUp(); - $this->postDispatch('/abonne/edit-session/id/' - . $this->_inscription->getId(), ['adults' => 5, 'children' => 15]); - } - - - /** @test */ - public function editAdultsShouldHaveErrorThreeMorePlace() { - $this->assertXPathContentContains('//ul[@class="errors"]', '(3 restantes)'); - } - - - /** @test */ - public function editChildrenShouldHaveErrorTwelvePlace() { - $this->assertXPathContentContains('//ul[@class="errors"]', '(12 restantes)'); - } -} - - - - -class AbonneControllerActivitiesEditSessionBadUserWithQuotasTest - extends AbonneControllerActivitiesEditSessionWithQuotasTestCase { - - public function setUp() { - parent::setUp(); - $this->dispatch('/abonne/edit-session/id/' . $this->_other_inscription->getId()); - } - - - /** @test */ - public function shouldRedirectToActivities() { - $this->assertRedirectContains('/activities'); - } -} - - - - class AbonneControllerActivitiesDoneActionTest extends AbstractAbonneControllerActivitiesTestCase { @@ -1024,312 +857,6 @@ class AbonneControllerActivitiesAmadouInscritSessionFebruaryJavaOpenTest extends -class AbonneControllerActivitiesRegisterSessionWithQuotasTest - extends AbstractAbonneControllerActivitiesTestCase { - - public function setUp() { - parent::setUp(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - $this->_session_java_fevrier - ->resetAttendees() - ->setEffectifMax(5) - ->setEffectifChildMax(15) - ->setEffectifInscriptionMax(5) - ->setEffectifInscriptionChildMax(15); - - $inscription = Class_SessionActivityInscription::newInstance(['session_activity_id' => 31, - 'adults' => 1, - 'children' => 1]); - $inscription->assertSave(); - - $this->_session_java_fevrier->addSessionActivityInscription($inscription); - - $this->dispatch('/opac/abonne/inscrire-session/id/31'); - } - - - public function quotasElements() { - return [['adults', 4], ['children', 14]]; - } - - - /** - * @test - * @dataProvider quotasElements - */ - public function pageShouldContainsElementCount($element, $count) { - $this->assertXPath('//input[@type="number"][@min="0"][@max="' - . $count . '"][@name="' - . $element . '"]'); - } -} - - - - -abstract class AbonneControllerActivitiesRegisterSessionWithQuotasPostTestCase - extends AbstractAbonneControllerActivitiesTestCase { - - public function setUp() { - parent::setUp(); - Class_SessionActivity::find(31)->resetAttendees(); - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - } - - - protected function _postAdultsAndChildren($adults, $children) { - $this->postDispatch('/opac/abonne/inscrire-session/id/31', - ['adults' => $adults, 'children' => $children]); - } - - - protected function _alreadyRegisteredAdultsAndChildren($adults, $children) { - $inscription = Class_SessionActivityInscription::newInstance(['session_activity_id' => 31, - 'adults' => $adults, - 'children' => $children]); - $inscription->assertSave(); - - $this->_session_java_fevrier->addSessionActivityInscription($inscription); - return $this; - } -} - - - - -class AbonneControllerActivitiesRegisterSessionWithQuotasPostTest - extends AbonneControllerActivitiesRegisterSessionWithQuotasPostTestCase { - - public function setUp() { - parent::setUp(); - $this->_session_java_fevrier - ->setEffectifMax(10) - ->setEffectifChildMax(20) - ->setEffectifInscriptionMax(5) - ->setEffectifInscriptionChildMax(15); - - $this->_postAdultsAndChildren(1, 3); - } - - - /** @test */ - public function inscriptionShouldBeCreated() { - $inscription = Class_SessionActivityInscription::findFirstBy(['session_activity_id' => 31]); - $this->assertNotNull($inscription); - return $inscription; - } - - - /** - * @test - * @depends inscriptionShouldBeCreated - */ - public function inscriptionAdultsShouldBeOne($inscription) { - $this->assertEquals(1, $inscription->getAdults()); - } - - - /** - * @test - * @depends inscriptionShouldBeCreated - */ - public function inscriptionChildrenShouldBeThree($inscription) { - $this->assertEquals(3, $inscription->getChildren()); - } - - - /** @test */ - public function shouldRedirectToActivities() { - $this->assertRedirectTo('/activities'); - } - - - /** @test */ - public function shouldNotifyRegistered() { - $this->assertFlashMessengerContentContains('Vous êtes inscrit'); - } -} - - - - -class AbonneControllerActivitiesRegisterSessionWithQuotasZerosPostTest - extends AbonneControllerActivitiesRegisterSessionWithQuotasPostTestCase { - - public function setUp() { - parent::setUp(); - $this->_session_java_fevrier - ->setEffectifMax(10) - ->setEffectifChildMax(20) - ->setEffectifInscriptionMax(5) - ->setEffectifInscriptionChildMax(15); - - $this->_postAdultsAndChildren(0, 0); - } - - - /** @test */ - public function shouldDisplayAtLeastOnePersonError() { - $this->assertXPathContentContains('//ul[@class="errors"]', 'Au moins un adulte ou un enfant doit s\'inscrire'); - } -} - - - - -class AbonneControllerActivitiesRegisterSessionWithMaxQuotasErrorsPostTest - extends AbonneControllerActivitiesRegisterSessionWithQuotasPostTestCase { - - public function setUp() { - parent::setUp(); - $this->_session_java_fevrier - ->setEffectifInscriptionMax(1) - ->setEffectifInscriptionChildMax(2) - ->setEffectifMax(10) - ->setEffectifChildMax(20); - - $this->_postAdultsAndChildren(2, 3); - } - - - /** @test */ - public function shouldDisplayTooManyAdults() { - $this->assertXPathContentContains('//ul[@class="errors"]', 'Le nombre d\'adultes est supérieur au nombre de places adultes disponibles (1 restante)'); - } - - - /** @test */ - public function shouldDisplayTooManyChildren() { - $this->assertXPathContentContains('//ul[@class="errors"]', 'Le nombre d\'enfants est supérieur au nombre de places enfants disponibles (2 restantes)'); - } -} - - - - -class AbonneControllerActivitiesRegisterSessionWithNoMoreRoomAtAllErrorsPostTest - extends AbonneControllerActivitiesRegisterSessionWithQuotasPostTestCase { - - public function setUp() { - parent::setUp(); - $this->_session_java_fevrier - ->setEffectifInscriptionMax(1) - ->setEffectifInscriptionChildMax(2) - ->setEffectifMax(1) - ->setEffectifChildMax(2); - - $this->_alreadyRegisteredAdultsAndChildren(1, 2) - ->_postAdultsAndChildren(1, 2); - } - - - /** @test */ - public function shouldDisplayNoMoreRoomMessage() { - $this->assertFlashMessengerContentContains('Inscription impossible, plus de place disponible.'); - } - - - /** @test */ - public function sessionShouldStillHaveOnlyOneRegistration() { - $this->assertEquals(1, Class_SessionActivityInscription::countBy(['session_activity_id' => 31])); - } - - - /** @test */ - public function shouldRedirect() { - $this->assertRedirectTo('/activities'); - } -} - - - - -class AbonneControllerActivitiesRegisterSessionWithNoMoreAdultsPostTest - extends AbonneControllerActivitiesRegisterSessionWithQuotasPostTestCase { - - public function setUp() { - parent::setUp(); - $this->_session_java_fevrier - ->setEffectifInscriptionMax(1) - ->setEffectifInscriptionChildMax(2) - ->setEffectifMax(1) - ->setEffectifChildMax(2); - - $this->_alreadyRegisteredAdultsAndChildren(1, 1) - ->_postAdultsAndChildren(1, 2); - } - - - /** @test */ - public function pageShouldContainsNoMoreAdultsRoom() { - $this->assertXPathContentContains('//span', 'Aucune place adulte disponible'); - } - - - /** @test */ - public function inputAdultsShouldNotDisplay() { - $this->assertNotXPath('//input[@name="adults"]'); - } - - - /** @test */ - public function pageShouldContainsTooManyChildrenError() { - $this->assertXPathContentContains('//ul[@class="errors"]', 'Le nombre d\'enfants est supérieur au nombre de places enfants disponibles (1 restante)'); - } - - - /** @test */ - public function sessionShouldStillHaveOnlyOneRegistration() { - $this->assertEquals(1, Class_SessionActivityInscription::countBy(['session_activity_id' => 31])); - } -} - - - - -class AbonneControllerActivitiesRegisterSessionWithNoMoreChildrenPostTest - extends AbonneControllerActivitiesRegisterSessionWithQuotasPostTestCase { - - public function setUp() { - parent::setUp(); - $this->_session_java_fevrier - ->setEffectifInscriptionMax(2) - ->setEffectifInscriptionChildMax(3) - ->setEffectifMax(2) - ->setEffectifChildMax(3); - - $this->_alreadyRegisteredAdultsAndChildren(1, 3) - ->_postAdultsAndChildren(2, 2); - } - - - /** @test */ - public function pageShouldContainsNoMoreChildrenRoom() { - $this->assertXPathContentContains('//span', 'Aucune place enfant disponible'); - } - - - /** @test */ - public function inputChildrenShouldNotDisplay() { - $this->assertNotXPath('//input[@name="children"]'); - } - - - /** @test */ - public function pageShouldContainsTooManyAdultsError() { - $this->assertXPathContentContains('//ul[@class="errors"]', 'Le nombre d\'adultes est supérieur au nombre de places adultes disponibles (1 restante)'); - } - - - /** @test */ - public function sessionShouldStillHaveOnlyOneRegistration() { - $this->assertEquals(1, Class_SessionActivityInscription::countBy(['session_activity_id' => 31])); - } -} - - - - class AbonneControllerActivitiesAmadouWithoutMailInscritSessionFebruaryJavaOpenTest extends AbstractAbonneControllerActivitiesTestCase { protected $_mails; diff --git a/tests/application/modules/opac/controllers/NoticeAjaxControllerPelliculeTest.php b/tests/application/modules/opac/controllers/NoticeAjaxControllerPelliculeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b7a5b703b7dc95d6efd3c17c118c4be68b41745e --- /dev/null +++ b/tests/application/modules/opac/controllers/NoticeAjaxControllerPelliculeTest.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright (c) 2012-2021, 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 NoticeAjaxControllerPelliculeActiveTest extends AbstractControllerTestCase { + protected + $_storm_default_to_volatile = true, + $_http_client; + + public function setUp() { + parent::setUp(); + Class_CosmoVar::set('url_services', 'http://cache.org'); + Class_AdminVar::set('PELLICULE_SETTINGS', + json_encode(['Provider' => [Class_AdminVar_PelliculeSettings::ELECTRE_REST_2], + 'Login' => ['mylogin'], + 'Password' => ['mys3cr3t']])); + + Class_Exemplaire::clearCache(); + Class_Notice::clearCache(); + + $this->fixture('Class_Notice', + ['id' => 1, + 'titre' => 'Pomme et Ananas', + 'titre_principal' => 'Journey in Satchidananda', + 'auteur_principal' => 'Jacques Audiard', + 'isbn' => '978225316403610', + 'ean' => '978225316403610', + 'clef_alpha' => 'POMMEETANANAS', + 'facettes' => 'A1 Q9', + 'date_maj' => '01/01/2015', + 'type_doc' => Class_TypeDoc::LIVRE, + 'url_vignette' => '', + 'url_image' => '', + 'exemplaires' => [$this->fixture('Class_Exemplaire', + ['id' => 2, + 'id_origine' => '9939_SSIRTE'])] + ]); + + $this->_http_client = $this->mock() + ->whenCalled('open_url') + ->answers(null); + + Class_WebService_AllServices::setHttpClient($this->_http_client); + $this->dispatch('/noticeajax/notice/id/1'); + } + + + /** @test */ + public function requestShouldContainsAuthorizationHeader() { + $headers = [['Authorization' => "Pellicule eyJwcm92aWRlciI6ImVsZWN0cmVfcmVzdF8yIiwiY2xpZW50X2lkIjoibXlsb2dpbiIsImNsaWVudF9zZWNyZXQiOiJteXMzY3IzdCJ9"]]; + + $call_params = $this->_http_client->getAttributesForLastCallOn('open_url'); + $this->assertEquals($headers, $call_params[1]['headers']); + } +} diff --git a/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php b/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php index b635191cad7c62466af342eb8f0e959986d4bc02..c765327b5792dc527caa91cde1e296bf0ae9ddd6 100644 --- a/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php +++ b/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php @@ -834,8 +834,9 @@ class NoticeAjaxControllerExemplairesWithOtherAnnexTestCase extends AbstractCont /** @test */ public function facetsShouldBeUpdatedWithAnnex21() { - $this->dispatch('noticeajax/exemplaires/id/123', true); - $this->assertEquals('D78092 A3029 A9751 A117014 A117015 M37414 G464 HNNNN0002 HNANA0002 T0 B6 SA9 Eemplacement de test Y21 V6', Class_notice::find(123)->getFacettes()); + $this->dispatch('noticeajax/exemplaires/id/123'); + $this->assertEquals('D78092 A3029 A9751 A117014 A117015 M37414 G464 HNNNN0002 HNANA0002 T0 B6 SA9 Eemplacement de test Y21 V6 HNRNR0001', + Class_notice::find(123)->getFacettes()); } } diff --git a/tests/db/UpgradeDBTest.php b/tests/db/UpgradeDBTest.php index e9d58b412ab53fd5f127f4babbb4e4659f535344..02776e4c46188ffa2b79bb079c0e944723696a46 100644 --- a/tests/db/UpgradeDBTest.php +++ b/tests/db/UpgradeDBTest.php @@ -3470,3 +3470,53 @@ class UpgradeDB_395_Test extends UpgradeDBTestCase { $this->assertFieldType('session_activity_inscriptions', 'children', 'int(11) unsigned'); } } + + + + +class UpgradeDB_396_Test extends UpgradeDBTestCase { + + public function prepare() { + $this->dropFieldFrom('session_activity', 'age_child_max') + ->dropFieldFrom('session_activity', 'all_day') + ->dropFieldFrom('session_activity_inscriptions', 'notified_at'); + $this->silentQuery('ALTER TABLE `session_activity` MODIFY `date_debut` date'); + $this->silentQuery('ALTER TABLE `session_activity` MODIFY `date_fin` date'); + } + + + /** @test */ + public function sessionActivityShouldContainsAgeChildMaxColumn() { + $this->assertFieldType('session_activity', 'age_child_max', 'int(11) unsigned'); + } + + + /** @test */ + public function sessionActivityShouldContainsAlldayColumn() { + $this->assertFieldType('session_activity', 'all_day', 'tinyint(1) unsigned'); + } + + + /** @test */ + public function sessionActivityAllDayDefaultShouldBeOne() { + $this->assertFieldDefault('session_activity', 'all_day', 1); + } + + + /** @test */ + public function sessionActivityColumDateDebutShouldBeDatetime() { + $this->assertFieldType('session_activity', 'date_debut', 'datetime'); + } + + + /** @test */ + public function sessionActivityColumDateFinShouldBeDatetime() { + $this->assertFieldType('session_activity', 'date_fin', 'datetime'); + } + + + /** @test */ + public function sessionActivityInscriptionColumNotifiedAtShouldBeDatetime() { + $this->assertFieldType('session_activity_inscriptions', 'notified_at', 'datetime'); + } +} \ No newline at end of file diff --git a/tests/js/MultiSelectionTest.php b/tests/js/MultiSelectionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cff8067164ae26bc9707056f9912e4bd3f9263e7 --- /dev/null +++ b/tests/js/MultiSelectionTest.php @@ -0,0 +1,30 @@ +<?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 MultiSelectionTest extends PHPUnit_Framework_TestCase { + + /** @test */ + public function multiSelectJstestShouldSuccess() { + exec('phantomjs ' . ROOT_PATH . 'tests_js/lib/qunit-phantomjs-runner/runner.js ' . ROOT_PATH . 'public/admin/js/multi_selection/tests.html', $output, $result); + $this->assertEquals(0, $result, implode("\n", $output)); + } +} \ No newline at end of file diff --git a/tests/library/Class/CodifThesaurusTest.php b/tests/library/Class/CodifThesaurusTest.php index 8957f4d7e1d614747fdb26c063f3228ceaf82e35..88166946bbbac6de5a56eb8d15fc1a41ca5bc7db 100644 --- a/tests/library/Class/CodifThesaurusTest.php +++ b/tests/library/Class/CodifThesaurusTest.php @@ -171,8 +171,8 @@ class CodifThesaurusGetIndicesRootTest extends ModelTestCase { /** @test */ public function shouldExcludeNoveltyAndDomains() { - Class_CodifThesaurus::getIndices('root', false); - $expected_params = ['where' => 'code not in ("Nouveauté par bibliothèque", "Nouveauté par annexe", "Catalogue") and LENGTH(id_thesaurus) in (1,4)', + Class_CodifThesaurus::getIndices('root'); + $expected_params = ['where' => 'id_thesaurus not in ("NNNN", "NANA", "CCCC") and LENGTH(id_thesaurus) in (1,4)', 'order' => 'id_thesaurus']; $this->assertEquals($expected_params, @@ -183,7 +183,7 @@ class CodifThesaurusGetIndicesRootTest extends ModelTestCase { /** @test */ public function shouldExcludeNoveltyButNotDomain() { Class_CodifThesaurus::getIndices('root', true); - $expected_params = ['where' => 'code not in ("Nouveauté par bibliothèque", "Nouveauté par annexe") and LENGTH(id_thesaurus) in (1,4)', + $expected_params = ['where' => 'id_thesaurus not in ("NNNN", "NANA") and LENGTH(id_thesaurus) in (1,4)', 'order' => 'id_thesaurus']; $this->assertEquals($expected_params, Class_CodifThesaurus::getFirstAttributeForLastCallOn('findAllBy')); } diff --git a/tests/library/Class/NoticeNoveltyTest.php b/tests/library/Class/NoticeNoveltyTest.php index b13299a566fa9bbe6cbb8989c4ed643a9df48c27..92683e8fe15c8874f734db0a6dd92e9af377f2bf 100644 --- a/tests/library/Class/NoticeNoveltyTest.php +++ b/tests/library/Class/NoticeNoveltyTest.php @@ -38,33 +38,42 @@ class NoticeNoveltyTest extends ModelTestCase{ 'libelle' => 'My Annexe']); - $this + $record_12 = $this ->fixture('Class_Notice', ['id' => 12, 'facettes' => 'T1 B4', - 'date_creation' => '2017-02-28']) - ->addExemplaire($this->fixture('Class_Exemplaire', - ['id' => 90000, - 'id_bib' => 4, - 'annexe' => 2, - 'date_nouveaute' => '2017-02-28'])) - ->assertSave(); - - $this + 'date_creation' => '2017-02-28']); + $record_12->addExemplaire($this->fixture('Class_Exemplaire', + ['id' => 90000, + 'id_bib' => 4, + 'annexe' => 2, + 'date_nouveaute' => '2017-02-28'])) + ->assertSave(); + + $record_15 = $this ->fixture('Class_Notice', ['id' => 15, 'facettes' => 'T1 B4 HNNNN0001', - 'date_creation' => '']) - ->addExemplaire($this->fixture('Class_Exemplaire', - ['id' => 99999, - 'id_bib' => 4, - 'annexe' => 2, - 'date_nouveaute' => '2015-02-28'])) - ->assertSave(); + 'date_creation' => '']); + $record_15->addExemplaire($this->fixture('Class_Exemplaire', + ['id' => 99999, + 'id_bib' => 4, + 'annexe' => 2, + 'date_nouveaute' => '2015-02-28'])) + ->assertSave(); - $this->onLoaderOfModel('Class_Notice'); Class_Notice::setMemoryCleaner(function() {}); + $this->onLoaderOfModel('Class_Notice') + ->whenCalled('findAllBy') + ->willDo(function($params) use($record_12, $record_15) + { + if ($params['where'] == 'match(facettes) against("+(HNNNN* HNANA* HNRNR0001)" in boolean mode) and id_notice > 0') + return [$record_12, $record_15]; + + return []; + }); + Class_Notice::indexNoveltyFacets(); } @@ -72,21 +81,22 @@ class NoticeNoveltyTest extends ModelTestCase{ /** @test */ public function record12ShouldHaveNoveltyFacet() { Class_Notice::find(12)->updateNoveltyFacets(); - $this->assertEquals('T1 B4 HNNNN0001 HNANA0001', + $this->assertEquals('T1 B4 HNNNN0001 HNANA0001 HNRNR0001', Class_Notice::find(12)->getFacettes()); } /** @test */ public function record15ShouldNotHaveNoveltyFacet() { - $this->assertEquals('T1 B4', Class_Notice::find(15)->getFacettes()); + $this->assertEquals('T1 B4 HNRNR0002', Class_Notice::find(15)->getFacettes()); } /** @test */ public function indexShouldNotFetchAllRecords() { - $this->assertEquals(['where' => 'match(facettes) against("+(HNNNN* HNANA*)" in boolean mode)', - 'limitPage' => [2, 100]], + $this->assertEquals(['where' => 'match(facettes) against("+(HNNNN* HNANA* HNRNR0001)" in boolean mode) and id_notice > 15', + 'order' => 'id_notice', + 'limit' => 100], Class_Notice::getFirstAttributeForLastCallOn('findAllBy')); } } diff --git a/tests/library/Class/NoticeTest.php b/tests/library/Class/NoticeTest.php index c4aaec6e53e004df6b0b535ec3e54ba8f5b79858..27b66076346771be2f696676235ccbaea499f4bf 100644 --- a/tests/library/Class/NoticeTest.php +++ b/tests/library/Class/NoticeTest.php @@ -1010,7 +1010,8 @@ class NoticeUpdateFacetsFromItemsTest extends ModelTestCase { /** @test */ public function recordFacetsShouldContainsNoveltyForRoubaixAndNoveltyForLille() { - $this->assertEquals('T0 B10 YROUB HNNNN0001 HNANA0001 B11 HNNNN0002', Class_Notice::find(5)->getFacettes()); + $this->assertEquals('T0 B10 YROUB HNNNN0001 HNANA0001 B11 HNNNN0002 HNRNR0001', + Class_Notice::find(5)->getFacettes()); } } diff --git a/tests/library/ZendAfi/View/Helper/Accueil/ActivitiesWidgetTest.php b/tests/library/ZendAfi/View/Helper/Accueil/ActivitiesWidgetTest.php index f9eb501bc8f5905c201a763e434f935bad451c7a..e8f1ba9fcce78b867803dc814bbbefb0d15c99de 100644 --- a/tests/library/ZendAfi/View/Helper/Accueil/ActivitiesWidgetTest.php +++ b/tests/library/ZendAfi/View/Helper/Accueil/ActivitiesWidgetTest.php @@ -411,28 +411,6 @@ class ZendAfi_View_Helper_Accueil_SortAndDisplayActivitiesWidgetTest } - /** @test */ - public function activitieShouldBeDisplayedByYearWithQuotas() { - foreach(Class_SessionActivity::findAll() as $activity) - $activity->resetAttendees(); - - Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); - $this->renderWidget( - ['division' => 1, - 'type_module' => 'ACTIVITIES_WIDGET', - 'preferences' => ['selected_activities' => '3-1-5', - 'display_order' => 'creation', - 'display_group_mode' => 'ByYear', - 'display_mode' =>'Block']]); - - $this->assertXPathContentContains($this->_html, - '//dd[@class="training_contributors"][preceding-sibling::dt[text()="Nombre d\'inscrits"]]', - '2', $this->_html); - - $this->assertXPathContentContains($this->_html, '//h2[1]' , '2010'); - } - - /** @test */ public function sessionShouldBeDisplayedEvenIfNotEndedDate() { $this->renderWidget( diff --git a/tests/scenarios/Activities/AbonneControllerWithQuotasTest.php b/tests/scenarios/Activities/AbonneControllerWithQuotasTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5a16dfddb49fc3bee03e7755c67919e1cbc30515 --- /dev/null +++ b/tests/scenarios/Activities/AbonneControllerWithQuotasTest.php @@ -0,0 +1,741 @@ +<?php +/** + * Copyright (c) 2012-2020, 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 AbonneControllerWithQuotasTestCase extends AbstractControllerTestCase { + + protected + $_storm_default_to_volatile = true, + $_amadou, + $_learn_java, + $_learn_python, + $_learn_smalltalk, + $_session_smalltalk_janvier, + $_session_smalltalk_juillet, + $_session_java_mars, + $_session_java_fevrier, + $_session_java_septembre, + $_session_python_juillet, + $_gallice_cafe, + $_bib_romains, + $_bonlieu, + $_mail_transport; + + + public function setUp() { + parent::setUp(); + + $_SERVER['HTTP_REFERER'] = '/activities'; + + $test_time = new TimeSourceForTest('2014-05-01 14:00:00'); + + Class_Activity::setTimeSource($test_time); + Class_SessionActivity::setTimeSource($test_time); + + Class_AdminVar::set('ACTIVITY', '1'); + Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); + Class_AdminVar::set('NOM_DOMAINE', 'bokeh.fr'); + + $this->_mail_transport = new MockMailTransport(); + Zend_Mail::setDefaultTransport($this->_mail_transport); + + $this->_amadou = $this->fixture('Class_Users', + ['id' => 435, + 'nom' => 'Dou', + 'prenom' => 'Ama', + 'login' => 'Amadou', + 'password' => 'pwd', + 'mail' => 'amadou@afi-sa.fr', + 'bib' => $this->fixture('Class_Bib', + ['id' => 1, + 'libelle' => 'annecy']), + 'idabon' => 435]); + $this->_amadou + ->beAbonneSIGB() + ->setUserGroups([$this->fixture('Class_UserGroup',['id' => 23])->addRightSuivreActivity()]) + ->assertSave(); + + ZendAfi_Auth::getInstance()->logUser($this->_amadou); + + $this->_gallice_cafe = $this->fixture('Class_Lieu', + ['id' => 98, + 'libelle' => 'Galice']); + + + $this->_bib_romains = $this->fixture('Class_Lieu', + ['id' => '99', + 'libelle' => 'Bibliothèque des romains']); + + + $this->_bonlieu = $this->fixture('Class_Lieu', + ['id' => 100, + 'libelle' => 'Bonlieu', + 'adresse' => "1, rue Jean-Jaures\nBP 294", + 'code_postal' => 74007, + 'ville' => 'Annecy', + 'latitude' => '45.902179', + 'longitude' => '6.128715']); + + $this->_learn_smalltalk = $this + ->fixture('Class_Activity', + ['id' => 1, + 'libelle' => 'Learn Smalltalk']); + + $this->_session_smalltalk_janvier = $this + ->fixture('Class_SessionActivity', + ['id' => 11, + 'activity' => $this->_learn_smalltalk, + 'effectif_min' => 1, + 'effectif_max' => 10, + 'effectif_inscription_max' => 5, + 'lieu' => $this->_gallice_cafe, + 'date_debut' => '2015-01-10', + 'date_fin' => '2015-01-10', + 'date_limite_inscription' => '2015-01-10', + 'stagiaires' => []]); + + $this->_session_smalltalk_juillet = $this + ->fixture('Class_SessionActivity', + ['id' => 12, + 'activity' => $this->_learn_smalltalk, + 'effectif_min' => 1, + 'effectif_max' => 10, + 'effectif_inscription_max' => 5, + 'lieu' => $this->_gallice_cafe, + 'stagiaires' => [], + 'date_debut' => '2014-07-11', + 'date_fin' => '2014-07-15', + 'date_limite_inscription' => '2014-07-11']); + + $this->_learn_smalltalk + ->setSessions([$this->_session_smalltalk_janvier, + $this->_session_smalltalk_juillet]) + ->assertSave(); + + + $this->_learn_java = $this->fixture('Class_Activity', + ['id' => 3, + 'libelle' => 'Learn Java', + 'description' => 'whaaat ?']); + + + $this->_session_java_fevrier = $this->fixture('Class_SessionActivity', + ['id' => 31, + 'activity' => $this->_learn_java, + 'effectif_min' => 2, + 'effectif_max' => 5, + 'effectif_inscription_max' => 5, + 'lieu' => $this->_bonlieu, + 'date_debut' => '2015-02-10', + 'date_fin' => '2015-02-20', + 'stagiaires' => [], + 'date_limite_inscription' => '2015-01-20']); + + $this->_session_java_fevrier->setArticle($this->fixture('Class_Article', + ['id' => 10, + 'titre' => 'Java est mort, vive python !', + 'contenu' => 'Java has been']) + ->setDateMaj('2020-04-11 08:00:00') + ->setEventsDebut('2020-04-11 12:00:00') + ->setEventsFin('2020-04-11 17:00:00')) + ->save(); + + + $this->_session_java_mars = $this->fixture('Class_SessionActivity', + ['id' => 32, + 'activity' => $this->_learn_java, + 'effectif_min' => 2, + 'effectif_max' => 5, + 'effectif_inscription_max' => 5, + 'lieu' => $this->_gallice_cafe, + 'date_debut' => '2015-03-01', + 'stagiaires' => [], + 'date_limite_inscription' => '2015-03-01']); + + $this->_session_java_septembre = $this->fixture('Class_SessionActivity', + ['id' => 30, + 'activity' => $this->_learn_java, + 'effectif_min' => 2, + 'effectif_max' => 5, + 'effectif_inscription_max' => 5, + 'date_debut' => '2014-09-10', + 'date_fin' => '2014-09-10', + 'stagiaires' => [], + 'lieu' => $this->_gallice_cafe, + 'date_limite_inscription' => '2014-09-10']); + $this->_session_java_septembre->beAnnule(); + + $this->_learn_java + ->setSessions([$this->_session_java_mars, + $this->_session_java_septembre, + $this->_session_java_fevrier]) + ->assertSave(); + + + $this->_learn_python = $this->fixture('Class_Activity', + ['id' => 12, + 'libelle' => 'Learn Python']); + + $this->_session_python_juillet = $this + ->fixture('Class_SessionActivity', + ['id' => 121, + 'activity' => $this->_learn_python, + 'date_debut' => '2014-07-10', + 'date_fin' => '2014-07-14', + 'date_limite_inscription' => '2014-04-29', + 'contenu' => 'Introduction a la syntaxe', + 'objectif' => 'Ecrire un premier programme', + 'effectif_min' => 1, + 'effectif_max' => 150, + 'effectif_inscription_max' => 5, + 'effectif_child_min' => 0, + 'effectif_child_max' => 5, + 'effectif_inscription_child_max' => 5, + 'age_child_max' => 12, + 'duree' => 36, + 'horaires' => '8h-12h, 14h-18h', + 'lieu' => $this->_bib_romains, + 'stagiaires' => [$this->_amadou], + 'intervenants' => [$this->fixture('Class_Users', + ['id' =>76, + 'login' => 'jpp', + 'password' => 'pwd', + 'nom' => 'Pirant', + 'prenom' => 'Jean-Paul', + 'mail' => 'jp@bokeh.fr']), + $this->fixture('Class_users', + ['id' => 77, + 'login' => 'cc', + 'password' => 'pwd', + 'nom' => 'Cerisier', + 'prenom' => 'Christophe', + 'mail' => 'cc@bokeh.fr']) + ]]); + + $this->_learn_python + ->setSessions([$this->_session_python_juillet]) + ->assertSave(); + + $inscription_amadou_python = $this + ->fixture('Class_SessionActivityInscription', + ['id' => 1, + 'stagiaire' => $this->_amadou, + 'session_activity' => $this->_session_python_juillet, + 'adults' => 1, + 'children' => 1]); + + $this->_amadou->setSessionActivityInscriptions([$inscription_amadou_python]); + } +} + + + + +class Activities_AbonneControllerWithQuotasRegisteredActionTest + extends AbonneControllerWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + $this->dispatch('/abonne/activities-registered'); + } + + + /** @test */ + public function adultsCountShouldBePresent() { + $this->assertXPathContentContains('//td', '1 adulte'); + } + + + /** @test */ + public function childrenCountShouldBePresent() { + $this->assertXPathContentContains('//td', '1 enfant'); + } + + + /** @test */ + public function rowShouldContainEditButton() { + $this->assertXPath('//td//a[contains(@href, "/abonne/edit-session/id/1")]'); + } +} + + + + +abstract class AbonneControllerWithQuotasEditSessionTest + extends AbonneControllerWithQuotasTestCase { + + protected $_inscription, + $_other_inscription; + + public function setUp() { + parent::setUp(); + Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); + $this->_session_python_juillet + ->resetAttendees() + ->setEffectifMax(5) + ->setEffectifChildMax(15) + ->setEffectifInscriptionMax(3) + ->setEffectifInscriptionChildMax(12); + + $this->_other_inscription = $this->_register(1, 1); + $this->_inscription = $this->_register(1, 1); + $this->_inscription->setStagiaire($this->_amadou) + ->assertSave(); + } + + + protected function _register($adults, $children) { + $inscription = Class_SessionActivityInscription::newInstance(['session_activity_id' => 121, + 'adults' => $adults, + 'children' => $children]); + $inscription->assertSave(); + + $this->_session_python_juillet->addSessionActivityInscription($inscription); + return $inscription; + } +} + + + + +class Activities_AbonneControllerWithQuotasEditSessionActionTest + extends AbonneControllerWithQuotasEditSessionTest { + + public function setUp() { + parent::setUp(); + $this->dispatch('/abonne/edit-session/id/' . $this->_inscription->getId()); + } + + + /** @test */ + public function inputAdultsShouldHaveValueOneAndMaxThree() { + $this->assertXPath('//input[@name="adults"][@value="1"][@max="3"]'); + } + + + /** @test */ + public function inputChildrenShouldHaveValueOneAndMaxTwelve() { + $this->assertXPath('//input[@name="children"][@value="1"][@max="12"]'); + } +} + + + + +class Activities_AbonneControllerWithQuotasEditPostTest + extends AbonneControllerWithQuotasEditSessionTest { + + public function setUp() { + parent::setUp(); + $url = $_SERVER['HTTP_REFERER'] = '/abonne/edit-session/id/' . $this->_inscription->getId(); + + $this->postDispatch($url, ['adults' => 2, 'children' => 3]); + $this->_inscription = Class_SessionActivityInscription::find($this->_inscription->getId()); + } + + + /** @test */ + public function inscriptionAdultsShouldBeTwo() { + $this->assertEquals(2, $this->_inscription->getAdults()); + } + + + /** @test */ + public function inscriptionChildrenShouldBeThree() { + $this->assertEquals(3, $this->_inscription->getChildren()); + } + + + /** @test */ + public function shouldRedirectToActivities() { + $this->assertRedirectContains('/abonne/activities-registered'); + } +} + + + + +class Activities_AbonneControllerWithQuotasErrorPostTest + extends AbonneControllerWithQuotasEditSessionTest { + + public function setUp() { + parent::setUp(); + $this->postDispatch('/abonne/edit-session/id/' + . $this->_inscription->getId(), ['adults' => 5, 'children' => 15]); + } + + + /** @test */ + public function editAdultsShouldHaveErrorThreeMorePlace() { + $this->assertXPathContentContains('//ul[@class="errors"]', '(3 restantes)'); + } + + + /** @test */ + public function editChildrenShouldHaveErrorTwelvePlace() { + $this->assertXPathContentContains('//ul[@class="errors"]', '(12 restantes)'); + } +} + + + + +class Activities_AbonneControllerWithQuotasBadUserTest + extends AbonneControllerWithQuotasEditSessionTest { + + public function setUp() { + parent::setUp(); + $this->dispatch('/abonne/edit-session/id/' . $this->_other_inscription->getId()); + } + + + /** @test */ + public function shouldRedirectToActivities() { + $this->assertRedirectContains('/activities'); + } +} + + + + +class Activities_AbonneControllerWithQuotasRegisterSessionTest + extends AbonneControllerWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + $this->_session_java_fevrier + ->resetAttendees() + ->setEffectifMax(5) + ->setEffectifChildMax(15) + ->setEffectifInscriptionMax(5) + ->setEffectifInscriptionChildMax(15); + + $inscription = Class_SessionActivityInscription::newInstance(['session_activity_id' => 31, + 'adults' => 1, + 'children' => 1]); + $inscription->assertSave(); + + $this->_session_java_fevrier->addSessionActivityInscription($inscription); + + $this->dispatch('/opac/abonne/inscrire-session/id/31'); + } + + + public function quotasElements() { + return [['adults', 4], ['children', 14]]; + } + + + /** + * @test + * @dataProvider quotasElements + */ + public function pageShouldContainsElementCount($element, $count) { + $this->assertXPath('//input[@type="number"][@min="0"][@max="' + . $count . '"][@name="' + . $element . '"]'); + } +} + + + + +abstract class AbonneControllerWithQuotasRegisterSessionPostTestCase + extends AbonneControllerWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + Class_SessionActivity::find(31)->resetAttendees(); + } + + + protected function _postAdultsAndChildren($adults, $children) { + $this->postDispatch('/opac/abonne/inscrire-session/id/31', + ['adults' => $adults, 'children' => $children]); + } + + + protected function _alreadyRegisteredAdultsAndChildren($adults, $children) { + $inscription = Class_SessionActivityInscription::newInstance(['session_activity_id' => 31, + 'adults' => $adults, + 'children' => $children]); + $inscription->assertSave(); + + $this->_session_java_fevrier->addSessionActivityInscription($inscription); + return $this; + } +} + + + + +class Activities_AbonneControllerWithQuotasRegisterSessionPostTest + extends AbonneControllerWithQuotasRegisterSessionPostTestCase { + + public function setUp() { + parent::setUp(); + $this->_session_java_fevrier + ->setEffectifMax(10) + ->setEffectifChildMax(20) + ->setEffectifInscriptionMax(5) + ->setEffectifInscriptionChildMax(15); + + $this->_postAdultsAndChildren(1, 3); + } + + + /** @test */ + public function inscriptionShouldBeCreated() { + $inscription = Class_SessionActivityInscription::findFirstBy(['session_activity_id' => 31]); + $this->assertNotNull($inscription); + return $inscription; + } + + + /** + * @test + * @depends inscriptionShouldBeCreated + */ + public function inscriptionAdultsShouldBeOne($inscription) { + $this->assertEquals(1, $inscription->getAdults()); + } + + + /** + * @test + * @depends inscriptionShouldBeCreated + */ + public function inscriptionChildrenShouldBeThree($inscription) { + $this->assertEquals(3, $inscription->getChildren()); + } + + + /** @test */ + public function shouldRedirectToActivities() { + $this->assertRedirectTo('/activities'); + } + + + /** @test */ + public function shouldNotifyRegistered() { + $this->assertFlashMessengerContentContains('Vous êtes inscrit'); + } +} + + + + +class Activities_AbonneControllerWithQuotasRegisterSessionZerosPostTest + extends AbonneControllerWithQuotasRegisterSessionPostTestCase { + + public function setUp() { + parent::setUp(); + $this->_session_java_fevrier + ->setEffectifMax(10) + ->setEffectifChildMax(20) + ->setEffectifInscriptionMax(5) + ->setEffectifInscriptionChildMax(15); + + $this->_postAdultsAndChildren(0, 0); + } + + + /** @test */ + public function shouldDisplayAtLeastOnePersonError() { + $this->assertXPathContentContains('//ul[@class="errors"]', 'Au moins un adulte ou un enfant doit s\'inscrire'); + } +} + + + + +class Activities_AbonneControllerWithQuotasRegisterSessionMaxQuotasErrosPostTest + extends AbonneControllerWithQuotasRegisterSessionPostTestCase { + + public function setUp() { + parent::setUp(); + $this->_session_java_fevrier + ->setEffectifInscriptionMax(1) + ->setEffectifInscriptionChildMax(2) + ->setEffectifMax(10) + ->setEffectifChildMax(20); + + $this->_postAdultsAndChildren(2, 3); + } + + + /** @test */ + public function shouldDisplayTooManyAdults() { + $this->assertXPathContentContains('//ul[@class="errors"]', 'Le nombre d\'adultes est supérieur au nombre de places adultes disponibles (1 restante)'); + } + + + /** @test */ + public function shouldDisplayTooManyChildren() { + $this->assertXPathContentContains('//ul[@class="errors"]', 'Le nombre d\'enfants est supérieur au nombre de places enfants disponibles (2 restantes)'); + } +} + + + + +class Activities_AbonneControllerWithQuotasRegisterSessionChildAgeMaxPostTest + extends AbonneControllerWithQuotasRegisterSessionPostTestCase { + + /** @test */ + public function nombreEnfantsShouldContainAgeMax() { + Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); + $this->_session_java_mars + ->setEffectifInscriptionMax(5) + ->setEffectifInscriptionChildMax(10) + ->setEffectifMax(10) + ->setEffectifChildMax(10) + ->setAgeChildMax(12) + ->resetAttendees() + ->assertSave(); + $this->dispatch('/abonne/inscrire-session/id/32'); + $this->assertXPathContentContains('//table//td//label[@data-name="children"]', + 'Nombre d\'enfants (âge max 12)'); + } +} + + + + +class Activities_AbonneControllerWithQuotasRegisterSessionWithNoMoreRoomAllErrorsPostTest + extends AbonneControllerWithQuotasRegisterSessionPostTestCase { + + public function setUp() { + parent::setUp(); + $this->_session_java_fevrier + ->setEffectifInscriptionMax(1) + ->setEffectifInscriptionChildMax(2) + ->setEffectifMax(1) + ->setEffectifChildMax(2); + + $this->_alreadyRegisteredAdultsAndChildren(1, 2) + ->_postAdultsAndChildren(1, 2); + } + + + /** @test */ + public function shouldDisplayNoMoreRoomMessage() { + $this->assertFlashMessengerContentContains('Inscription impossible, plus de place disponible.'); + } + + + /** @test */ + public function sessionShouldStillHaveOnlyOneRegistration() { + $this->assertEquals(1, Class_SessionActivityInscription::countBy(['session_activity_id' => 31])); + } + + + /** @test */ + public function shouldRedirect() { + $this->assertRedirectTo('/activities'); + } +} + + + + +class Activities_AbonneControllerWithQuotasRegisterSessionWithNoMoreAdultsPostTest + extends AbonneControllerWithQuotasRegisterSessionPostTestCase { + + public function setUp() { + parent::setUp(); + $this->_session_java_fevrier + ->setEffectifInscriptionMax(1) + ->setEffectifInscriptionChildMax(2) + ->setEffectifMax(1) + ->setEffectifChildMax(2); + + $this->_alreadyRegisteredAdultsAndChildren(1, 1) + ->_postAdultsAndChildren(1, 2); + } + + + /** @test */ + public function pageShouldContainsNoMoreAdultsRoom() { + $this->assertXPathContentContains('//span', 'Aucune place adulte disponible'); + } + + + /** @test */ + public function inputAdultsShouldNotDisplay() { + $this->assertNotXPath('//input[@name="adults"]'); + } + + + /** @test */ + public function pageShouldContainsTooManyChildrenError() { + $this->assertXPathContentContains('//ul[@class="errors"]', 'Le nombre d\'enfants est supérieur au nombre de places enfants disponibles (1 restante)'); + } + + + /** @test */ + public function sessionShouldStillHaveOnlyOneRegistration() { + $this->assertEquals(1, Class_SessionActivityInscription::countBy(['session_activity_id' => 31])); + } +} + + + + +class Activities_AbonneControllerWithQuotasRegisterSessionWithNoMoreChildrenPostTest + extends AbonneControllerWithQuotasRegisterSessionPostTestCase { + + public function setUp() { + parent::setUp(); + $this->_session_java_fevrier + ->setEffectifInscriptionMax(2) + ->setEffectifInscriptionChildMax(3) + ->setEffectifMax(2) + ->setEffectifChildMax(3); + + $this->_alreadyRegisteredAdultsAndChildren(1, 3) + ->_postAdultsAndChildren(2, 2); + } + + + /** @test */ + public function pageShouldContainsNoMoreChildrenRoom() { + $this->assertXPathContentContains('//span', 'Aucune place enfant disponible'); + } + + + /** @test */ + public function inputChildrenShouldNotDisplay() { + $this->assertNotXPath('//input[@name="children"]'); + } + + + /** @test */ + public function pageShouldContainsTooManyAdultsError() { + $this->assertXPathContentContains('//ul[@class="errors"]', 'Le nombre d\'adultes est supérieur au nombre de places adultes disponibles (1 restante)'); + } + + + /** @test */ + public function sessionShouldStillHaveOnlyOneRegistration() { + $this->assertEquals(1, Class_SessionActivityInscription::countBy(['session_activity_id' => 31])); + } +} diff --git a/tests/scenarios/Activities/AdminControllerInscriptionWithQuotasTest.php b/tests/scenarios/Activities/AdminControllerInscriptionWithQuotasTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c2365c1b314df909a9f27b769ef0eea9d25f344f --- /dev/null +++ b/tests/scenarios/Activities/AdminControllerInscriptionWithQuotasTest.php @@ -0,0 +1,391 @@ +<?php +/** + * Copyright (c) 2012-2020, 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 AdminControllerInscriptionWithQuotasTestCase + extends Admin_AbstractControllerTestCase { + + protected + $_storm_default_to_volatile = true, + $_group_profs, + $_groupe_stagiaires, + $_prof_laurent, + $_amandine, + $_patrick, + $_salle_reunion, + $_learn_java; + + + public function setUp() { + parent::setUp(); + + Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); + + $this->_group_profs = $this->fixture('Class_UserGroup', + ['id' => 344, + 'libelle' => 'Profs', + 'rights' => [Class_UserGroup::RIGHT_DIRIGER_ACTIVITY]]); + + $this->_groupe_stagiaires = $this->fixture('Class_UserGroup', + ['id' => 12, + 'libelle' => 'Stagiaires', + 'rights' => [Class_UserGroup::RIGHT_SUIVRE_ACTIVITY]]); + + $this->_prof_laurent = $this->fixture('Class_users', + ['id' => 34, + 'nom' => 'Laffont', + 'prenom' => 'Laurent', + 'login' => 'lla', + 'password' => 'pwd', + 'user_groups' => [$this->_group_profs]]); + + $this->_amandine = $this->fixture('Class_Users', + ['id' => 10, + 'nom' => 'Pistache', + 'prenom' => 'Amandine', + 'login' => 'Amd', + 'password' => 'fx9k', + 'mail' => 'pist@che.io', + 'user_groups' => [$this->_groupe_stagiaires]]); + + $this->_patrick = $this->fixture('Class_Users', + ['id' => 5, + 'id_site' => 12, + 'login' => 'Pat', + 'password' => '123', + 'prenom' => 'Patrick', + 'nom' => 'Barroca', + 'mail' => 'user@server.org', + 'user_groups' => [$this->_groupe_stagiaires]]); + + $this->_salle_reunion = $this->fixture('Class_Lieu', + ['id' => 12, + 'libelle' => 'Salle reunion AFI']); + + $this->_learn_java = $this->fixture('Class_Activity', + ['id' => 3, + 'libelle' => 'Learn Java', + 'description' => 'Here you will learn some old and boring stuff']); + + $this->fixture('Class_SessionActivity', + ['id' => 32, + 'activity' => $this->_learn_java, + 'date_debut' => '2012-03-27', + 'date_fin' => '2012-03-29', + 'effectif_min' => 5, + 'effectif_max' => 25, + 'effectif_child_min' => 1, + 'effectif_child_max' => 5, + 'age_child_max' => 5, + 'effectif_inscription_max' => 2, + 'effectif_inscription_child_max' => 2, + 'duree'=> 8, + 'contenu' => 'Intro à la syntaxe', + 'horaires' => '9h - 12h, 13h - 18h', + 'lieu' => $this->_salle_reunion, + 'date_limite_inscription'=>'2012-03-05', + 'intervenants' => [$this->_prof_laurent], + ]); + + $inscription = $this->fixture('Class_SessionActivityInscription', + ['id' => 165, + 'stagiaire_id' => 5, + 'session_activity_id' => 32, + 'adults' => 1, + 'children' => 2, + ]); + + Class_SessionActivity::find(32) + ->setSessionActivityInscriptions([$inscription]) + ->assertSave(); + } +} + + + + +class Activities_AdminControllerInscriptionWithQuotasSubscribeTest + extends AdminControllerInscriptionWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + Class_SessionActivity::find(32)->resetAttendees(); + $this->dispatch('/admin/session-activity-inscription/subscribe/id/32/stagiaire_id/10'); + } + + + /** @test */ + public function pageShouldContainsSessionNavigation() { + $this->assertXPathContentContains('//div[contains(@class, "activities")]', + 'Learn Java'); + } + + + /** @test */ + public function inputAdultsShouldBePresent() { + $this->assertXPath('//input[@name="adults"]'); + } + + + /** @test */ + public function inputChildrenShouldBePresent() { + $this->assertXPath('//input[@name="children"]'); + } + + + /** @test */ + public function backButtonUrlShouldContainsSessionActivity32() { + $this->assertXPath('//button[contains(@data-url, "/admin/session-activity/inscriptions/id/32")]'); + } +} + + + + +class Activities_AdminControllerInscriptionWithQuotasSubscribePopupTest + extends AdminControllerInscriptionWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/session-activity-inscription/subscribe/id/32/stagiaire_id/10/render/popup'); + } + + + /** @test */ + public function popupShouldNotContainsSessionNavigation() { + $this->assertNotXPathContentContains('//div[contains(@class, "activities")]', + 'Learn Java'); + } +} + + + + +class Activities_AdminControllerInscriptionWithQuotasPostTest + extends AdminControllerInscriptionWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + Class_SessionActivity::find(32)->resetAttendees(); + $this->postDispatch('/admin/session-activity-inscription/subscribe/id/32/stagiaire_id/10', + ['adults' => 1, + 'children' => 2]); + } + + + /** @test */ + public function shouldRedirectToActivityInscriptions() { + $this->assertRedirectTo('/admin/session-activity/inscriptions/id/32'); + } + + + /** @test */ + public function pistacheShouldBeSubscribed() { + $this + ->assertNotNull(Class_SessionActivityInscription::findFirstBy(['stagiaire_id' => 10, + 'session_activity_id' => 32])); + } +} + + + + +class Activities_AdminControllerInscriptionWithQuotasPostMaxOverloadTest + extends AdminControllerInscriptionWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + Class_SessionActivity::find(32)->resetAttendees(); + $this->postDispatch('/admin/session-activity-inscription/subscribe/id/32/stagiaire_id/10', + ['adults' => 3, + 'children' => 3]); + } + + + /** @test */ + public function shouldRedirectToActivityInscriptions() { + $this->assertRedirectTo('/admin/session-activity/inscriptions/id/32'); + } + + + /** @test */ + public function pistacheShouldBeSubscribed() { + $this + ->assertNotNull(Class_SessionActivityInscription::findFirstBy(['stagiaire_id' => 10, + 'session_activity_id' => 32, + 'adults' => 3, + 'children' => 3])); + } +} + + + + +class Activities_AdminControllerInscriptionWithQuotasEditTest + extends AdminControllerInscriptionWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + Class_SessionActivity::find(32)->resetAttendees(); + $this->dispatch('/admin/session-activity-inscription/edit/id/165'); + } + + + /** @test */ + public function pageShouldContainsSessionNavigation() { + $this->assertXPathContentContains('//div[contains(@class, "activities")]', + 'Learn Java'); + } + + + /** @test */ + public function inputAdultsShouldBePresent() { + $this->assertXPath('//input[@name="adults"][@value="1"]'); + } + + + /** @test */ + public function inputChildrenShouldBePresent() { + $this->assertXPath('//input[@name="children"][@value="2"]'); + } + + + /** @test */ + public function backButtonUrlShouldContainsSessionActivity32() { + $this->assertXPath('//button[contains(@data-url, "/admin/session-activity/inscriptions/id/32")]'); + } +} + + + + +class Activities_AdminControllerInscriptionWithQuotasEditPostTest + extends AdminControllerInscriptionWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + $this->postDispatch('/admin/session-activity-inscription/edit/id/165', + ['adults' => 2, + 'children' => 2]); + + Class_SessionActivityInscription::clearCache(); + } + + + /** @test */ + public function shouldRedirectToActivityInscriptions() { + $this->assertRedirectTo('/admin/session-activity/inscriptions/id/32'); + } + + + /** @test */ + public function patRegistrationAdultsShouldBecome2() { + $this->assertEquals(2, Class_SessionActivityInscription::find(165)->getAdults()); + } + + + /** @test */ + public function patRegistrationChildrenShouldBecome2() { + $this->assertEquals(2, Class_SessionActivityInscription::find(165)->getChildren()); + } +} + + + + +class Activities_AdminControllerInscriptionWithQuotasEditPostOverloadTest + extends AdminControllerInscriptionWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + $this->postDispatch('/admin/session-activity-inscription/edit/id/165', + ['adults' => 3, + 'children' => 3]); + + Class_SessionActivityInscription::clearCache(); + } + + + /** @test */ + public function shouldRedirectToActivityInscriptions() { + $this->assertRedirectTo('/admin/session-activity/inscriptions/id/32'); + } + + + /** @test */ + public function patRegistrationAdultsShouldBecome3() { + $this->assertEquals(3, Class_SessionActivityInscription::find(165)->getAdults()); + } + + + /** @test */ + public function patRegistrationChildrenShouldBecome3() { + $this->assertEquals(3, Class_SessionActivityInscription::find(165)->getChildren()); + } +} + + + + +class Activities_AdminControllerInscriptionWithQuotasEditFullChildrenTest + extends AdminControllerInscriptionWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + Class_SessionActivity::find(32) + ->resetAttendees() + ->setEffectifChildMax(2); + $this->dispatch('/admin/session-activity-inscription/edit/id/165'); + } + + + /** @test */ + public function inputAdultsShouldBePresent() { + $this->assertXPath('//input[@name="adults"][@value="1"]'); + } + + + /** @test */ + public function inputChildrenShouldBePresent() { + $this->assertXPath('//input[@name="children"][@value="2"]'); + } +} + + + + +class Activities_AdminControllerInscriptionWithQuotasSubscribeFullChildrenTest + extends AdminControllerInscriptionWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + Class_SessionActivity::find(32) + ->resetAttendees() + ->setEffectifChildMax(2); + $this->dispatch('/admin/session-activity-inscription/subscribe/id/32/stagiaire_id/10'); + } + + + /** @test */ + public function pageShouldContainNoMoreChildrenRoomMessage() { + $this->assertXPathContentContains('//div', 'Aucune place enfant disponible'); + } +} \ No newline at end of file diff --git a/tests/scenarios/Activities/AdminControllerWithQuotasTest.php b/tests/scenarios/Activities/AdminControllerWithQuotasTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ba87312794057089eb838bfa8709a1ff26cd237a --- /dev/null +++ b/tests/scenarios/Activities/AdminControllerWithQuotasTest.php @@ -0,0 +1,363 @@ +<?php +/** + * Copyright (c) 2012-2020, 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 AdminControllerWithQuotasTestCase extends Admin_AbstractControllerTestCase { + + protected + $_storm_default_to_volatile = true, + $_group_profs, + $_groupe_stagiaires, + $_prof_laurent, + $_amandine, + $_patrick, + $_salle_reunion, + $_learn_java, + $_legacy_registration; + + public function setUp() { + parent::setUp(); + + $this->_legacy_registration = $this->fixture('Class_SessionActivityInscription', + ['id' => 38839, + 'session_activity_id' => 32, + 'stagiaire_id' => 999838]); + + Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', '1'); + + $this->_group_profs = $this->fixture('Class_UserGroup', + ['id' => 344, + 'libelle' => 'Profs', + 'rights' => [Class_UserGroup::RIGHT_DIRIGER_ACTIVITY]]); + + $this->_groupe_stagiaires = $this->fixture('Class_UserGroup', + ['id' => 12, + 'libelle' => 'Stagiaires', + 'rights' => [Class_UserGroup::RIGHT_SUIVRE_ACTIVITY]]); + + $this->_prof_laurent = $this->fixture('Class_users', + ['id' => 34, + 'nom' => 'Laffont', + 'prenom' => 'Laurent', + 'login' => 'lla', + 'password' => 'pwd', + 'user_groups' => [$this->_group_profs]]); + + $this->_amandine = $this->fixture('Class_Users', + ['id' => 10, + 'nom' => 'Pistache', + 'prenom' => 'Amandine', + 'login' => 'Amd', + 'password' => 'fx9k', + 'mail' => 'pist@che.io', + 'user_groups' => [$this->_groupe_stagiaires]]); + + $this->_patrick = $this->fixture('Class_Users', + ['id' => 5, + 'id_site' => 12, + 'login' => 'Pat', + 'password' => '123', + 'prenom' => 'Patrick', + 'nom' => 'Barroca', + 'mail' => 'user@server.org', + 'user_groups' => [$this->_groupe_stagiaires]]); + + $this->_salle_reunion = $this->fixture('Class_Lieu', + ['id' => 12, + 'libelle' => 'Salle reunion AFI']); + + $this->_learn_java = $this->fixture('Class_Activity', + ['id' => 3, + 'libelle' => 'Learn Java', + 'description' => 'Here you will learn some old and boring stuff']); + + $this->fixture('Class_SessionActivity', + ['id' => 32, + 'activity' => $this->_learn_java, + 'date_debut' => '2012-03-27', + 'date_fin' => '2012-03-29', + 'effectif_min' => 5, + 'effectif_max' => 25, + 'effectif_child_min' => 1, + 'effectif_child_max' => 5, + 'age_child_max' => 5, + 'effectif_inscription_max' => 2, + 'effectif_inscription_child_max' => 3, + 'duree'=> 8, + 'contenu' => 'Intro à la syntaxe', + 'horaires' => '9h - 12h, 13h - 18h', + 'lieu' => $this->_salle_reunion, + 'date_limite_inscription'=>'2012-03-05', + 'intervenants' => [$this->_prof_laurent], + ]); + + $inscription = $this->fixture('Class_SessionActivityInscription', + ['id' => 165, + 'stagiaire_id' => 5, + 'session_activity_id' => 32, + 'children' => 2, + 'adults' => 1, + ]); + + Class_SessionActivity::find(32) + ->setSessionActivityInscriptions([$inscription]) + ->assertSave(); + + Zend_Registry::set('sql', + $this->mock() + ->whenCalled('fetchAll') + ->with('select user_id as id from user_group_memberships where user_group_id=12') + ->answers([['id' => 5]]) + + ->whenCalled('fetchAll') + ->with('select user_id as id from user_group_memberships where user_group_id=344') + ->answers([]) + + ->whenCalled('fetchAll') + ->with('select stagiaire_id as id from session_activity_inscriptions where session_activity_id=32') + ->answers([['id' => 5]]) + ); + } +} + + + + +class Activities_AdminControllerWithQuotasInscriptionTest extends AdminControllerWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/session-activity/inscriptions/id/32/search_session_activity_subscription_status/all'); + } + + + /** @test */ + public function pageShouldContainsCounters() { + $this->assertXPathContentContains('//a[contains(@href, "/session-activity/inscriptions/id/32")]', + '3 / 6-30'); + } + + + /** @test */ + public function pageShouldContainsParticipantsColumn() { + $this->assertXPathContentContains('//th', 'Participants'); + } + + + /** @test */ + public function pageShouldContainsAttendees() { + $this->assertXPathContentContains('//td', '1 adulte, 2 enfants'); + } + + + /** @test */ + public function pageShouldContainsLinkToEditAttendees() { + $this->assertXPath('//a[contains(@href, "/admin/session-activity-inscription/edit/id/165")]'); + } + + + /** @test */ + public function pageShouldContainsLinkToSubscribePistache() { + $this->assertXPath('//a[contains(@href, "/admin/session-activity-inscription/subscribe/id/32/stagiaire_id/10")][not(@onclick)][@data-popup]'); + } +} + + + + +class Activities_AdminControllerWithQuotasInscriptionLegacyTest + extends AdminControllerWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + Class_SessionActivity::find(32) + ->addSessionActivityInscription($this->_legacy_registration) + ->resetAttendees() + ->assertSave(); + $this->dispatch('/admin/session-activity/inscriptions/id/32/search_session_activity_subscription_status/all'); + } + + + /** @test */ + public function pageShouldContainsCountersWithLegacyRegistration() { + $this->assertXPathContentContains('//a[contains(@href, "/session-activity/inscriptions/id/32")]', + '4 / 6-30'); + } +} + + + + +class Activities_AdminControllerWithQuotasInscriptionOngletEffectifTest + extends AdminControllerWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/session-activity/inscriptions/id/32/search_session_activity_subscription_status/all'); + } + + + public function quotasElements() { + return [['effectif_min'], + ['effectif_child_min'], + ['effectif_max'], + ['effectif_child_max'], + ['effectif_inscription_max'], + ['effectif_inscription_child_max'], + ['age_child_max']]; + } + + + /** + * @test + * @dataProvider quotasElements + */ + public function withQuotasFormShouldContainsElement($element) { + $this->dispatch('/admin/session-activity/edit/id/32'); + $this->assertXPath('//fieldset[@id="fieldset-quotas"]//input[@name="' + . $element . '"][@required="required"][@type="number"][@min="0"]'); + } +} + + + + +class Activities_AdminControllerWithQuotasInscriptionInvalidPostTest + extends AdminControllerWithQuotasTestCase { + + protected $_post_values = ['effectif_child_min' => 'chaine', + 'effectif_child_max' => 'chaine', + 'age_child_max' => 'chaine', + 'effectif_min' => 'chaine', + 'effectif_max' => 'chaine', + 'effectif_inscription_max' => 'chaine', + 'effectif_inscription_child_max' => 'chaine']; + + + public function setUp() { + parent::setUp(); + } + + + public function quotasElements() { + return array_map(function($name) { return [$name]; }, + array_keys($this->_post_values)); + } + + + /** + * @test + * @dataProvider quotasElements + */ + public function pageShouldContainErrorNotIntegerFor($element) { + $this->postDispatch('admin/session-activity/edit/id/32', $this->_post_values); + $this->assertXPathContentContains('//ul[preceding-sibling::input[@name="' . $element . '"]][@class="errors"]', + "'chaine' n'est pas un nombre entier"); + } + + + /** @test */ + public function minGreaterThanMaxShouldDisplayError() { + $this->postDispatch('admin/session-activity/edit/id/32', ['effectif_child_min' => 30, + 'effectif_child_max' => 10]); + $this->assertXPathContentContains('//ul[@class="errors"]', + 'L\'effectif enfants maximum doit être supérieur ou égal à l\'effectif enfants minimum'); + } + + + /** @test */ + public function inscriptionMaxGreaterThanMaxShouldDisplayError() { + $this->postDispatch('admin/session-activity/edit/id/32', ['effectif_inscription_max' => 30, + 'effectif_max' => 10]); + $this->assertXPathContentContains('//ul[@class="errors"]', + 'L\'effectif maximum doit être supérieur ou égal à l\'effectif maximum par inscription'); + } + + + /** @test */ + public function inscriptionChildMaxGreaterThanMaxShouldDisplayError() { + $this->postDispatch('admin/session-activity/edit/id/32', ['effectif_inscription_child_max' => 10, + 'effectif_child_max' => 5]); + $this->assertXPathContentContains('//ul[@class="errors"]', + 'L\'effectif enfants maximum doit être supérieur ou égal à l\'effectif enfants maximum par inscription'); + } + + + /** @test */ + public function inscriptionWithoutAgeChilMaxShouldBerequired() { + $this->postDispatch('admin/session-activity/edit/id/32', ['effectif_inscription_child_max' => 5, + 'effectif_child_max' => 10, + 'age_child_max' => 0]); + $this->assertXPathContentContains('//ul[@class="errors"]', + 'L\'âge maximum pour les enfants doit être renseigné'); + } + + + /** @test */ + public function pageShouldContainsInscriptionMaxAdultesRequired() { + $this->postDispatch('/admin/session-activity/edit/id/32', + ['effectif_inscription_max' => 0]); + $this->assertXPathContentContains('//ul[@class="errors"]//li', + "Adultes maximum par inscription doit être renseigné"); + } + + + /** @test */ + public function pageShouldContainsInscriptionMaxEnfantsRequired() { + $this->postDispatch('/admin/session-activity/edit/id/32', + ['effectif_inscription_child_max' => 0]); + $this->assertXPathContentContains('//ul[@class="errors"]//li', + "Enfants maximum par inscription doit être renseigné"); + } +} + + + + +class Activities_AdminControllerWithQuotasInscriptionExportTest + extends AdminControllerWithQuotasTestCase { + + public function setUp() { + parent::setUp(); + Class_SessionActivity::find(32) + ->resetAttendees() + ->assertSave(); + $this->dispatch('/admin/session-activity/exportinscriptions/id/32'); + } + + + /** @test */ + public function exportShouldContainsEffectif6_30() { + $this->assertContains('Effectif;6-30', $this->_response->getBody()); + } + + + /** @test */ + public function exportShouldContainsAgeMaxChildren() { + $this->assertContains('Enfants (âge max 5)', $this->_response->getBody()); + } + + + /** @test */ + public function exportShouldContainsAdultsAndChildrenNumber() { + $this->assertContains('Barroca;Patrick;Pat;user@server.org;;1;2', $this->_response->getBody()); + } +} \ No newline at end of file diff --git a/tests/scenarios/Activities/BatchTest.php b/tests/scenarios/Activities/BatchTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d89505bab283728512a152f6f48a91d904b65e3a --- /dev/null +++ b/tests/scenarios/Activities/BatchTest.php @@ -0,0 +1,232 @@ +<?php +/** + * Copyright (c) 2012-2020, 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 Activities_BatchActivationTest extends ModelTestCase { + + /** @test */ + public function shouldNotBeEnabled() { + $this->assertFalse((new Class_Batch_ActivitiesNotifications)->isEnabled()); + } + + + /** @test */ + public function shouldBeEnabled() { + Class_AdminVar::set('ACTIVITY', 1); + $this->assertTrue((new Class_Batch_ActivitiesNotifications)->isEnabled()); + } +} + + + + +class Activities_BatchAdminTest extends Admin_AbstractControllerTestCase { + protected $_storm_default_to_volatile = true; + + public function setUp() { + parent::setUp(); + Class_AdminVar::set('ACTIVITY', 1); + $this->dispatch('/admin/batch'); + } + + + /** @test */ + public function pagheShouldContainsNotifierLesProchainesActivites() { + $this->assertXPathContentContains('//td', 'Notifier les prochaines activités'); + } +} + + + + +abstract class Activities_BatchRunTestCase extends ModelTestCase { + protected + $_storm_default_to_volatile = true, + $_mock_transport, + $_sent_mails, + $_log_output = ''; + + + public function setUp() { + parent::setUp(); + + Class_Profil::setCurrentProfil($this->fixture('Class_Profil', + ['id' => 1, + 'mail_site' => 'from@server.com'])); + + Class_AdminVar::set('ACTIVITY', 1); + Class_AdminVar::set('ACTIVITY_NOTIFICATION_DELAY', 3); + Class_AdminVar::set('ACTIVITY_NOTIFICATION_SUBJECT', 'Rappel : {session.libelle_activity}'); + Class_SessionActivity_Notification::setTimeSource(new TimeSourceForTest('2021-02-08 15:38:00')); + + $this->_mock_transport = new MockMailTransport(); + Zend_Mail::setDefaultTransport($this->_mock_transport); + + $this->_prepare(); + Class_SessionActivity::clearCache(); + $this->onLoaderOfModel('Class_SessionActivity'); + + $log_append = function($message) { + $this->_log_output .= $message; + }; + + (new Class_Batch_ActivitiesNotifications) + ->setLogger($this->mock() + ->whenCalled('log') + ->willDo($log_append) + + ->whenCalled('error') + ->willDo($log_append)) + ->run(); + + $this->_sent_mails = $this->_mock_transport->getSentMails(); + } + + + protected function _prepare() { + $stagiaire_group = $this->fixture('Class_UserGroup',['id' => 23]) + ->addRightSuivreActivity(); + + $this->fixture('Class_SessionActivity', + ['id' => 22, + 'date_debut' => '2021-02-11 00:00:00', + 'date_limite_inscription' => '2021-02-11', + 'activity' => $this->fixture('Class_Activity', + ['id' => 12, + 'libelle' => 'Stephanie\'s Birthday Party']), + 'stagiaires' => [$this->fixture('Class_Users', + ['id' => 9938, + 'login' => 'pistache', + 'password' => 'OMG', + 'mail' => 'pist@a.ch', + 'user_groups' => [$stagiaire_group]])], + ]); + } + + + public function tearDown() { + $this->_mock_transport = null; + parent::tearDown(); + } +} + + + + +class Activities_BatchRunTest extends Activities_BatchRunTestCase { + + /** @test */ + public function shouldHaveCalledFindAllByWithDelay3() { + $this->assertContains('DATEDIFF(date_debut, NOW()) <= 3', + Class_SessionActivity::getFirstAttributeForLastCallOn('findAllBy')['where']); + } + + + /** @test */ + public function shouldHaveSentEmail() { + $this->assertEquals(1, $this->_mock_transport->count()); + } + + + /** @test */ + public function mailFromShouldBeFromAtServerDotCom() { + $this->assertEquals('from@server.com', $this->_sent_mails[0]->getFrom()); + } + + + /** @test */ + public function mailSubjectShouldBeRappelStephaniesBirthdayParty() { + $this->assertEquals('Rappel : Stephanie\'s Birthday Party', + $this->_sent_mails[0]->getSubject()); + } + + + /** @test */ + public function shouldLogOneActivityOneNotification() { + $this->assertContains('Stephanie\'s Birthday Party : 1 rappel(s) envoyé(s)', + $this->_log_output); + } + + + /** @test */ + public function mailContenuShouldBePistacheActivityStephanie11_02() { + $this->assertEquals('<p>Bonjour pistache,</p><p>L\'activité Stephanie\'s Birthday Party à laquelle vous êtes inscrit, commencera le 11 février 2021.</p><p>Cordialement</p>', + quoted_printable_decode($this->_sent_mails[0]->getBodyHtml(true))); + } + + + /** @test */ + public function pistacheInscriptionShouldHaveNotifiedAt2021_02_08_153800() { + Class_SessionActivityInscription::clearCache(); + $this->assertEquals('2021-02-08 15:38:00', + Class_SessionActivityInscription::findFirstBy(['stagiaire_id' => '9938', + 'session_activity_id' => 22]) + ->getNotifiedAt()); + } +} + + + + +class Activities_BatchRunAlreadySentTest extends Activities_BatchRunTestCase { + + protected function _prepare() { + parent::_prepare(); + Class_SessionActivityInscription::findFirstBy(['stagiaire_id' => '9938', + 'session_activity_id' => 22]) + ->setNotifiedAt('2021-02-09 00:00:00') + ->assertSave(); + } + + + /** @test */ + public function shouldHaveNotSentEmail() { + $this->assertEquals(0, $this->_mock_transport->count()); + } +} + + + + +class Activities_BatchRunWithMailErrorTest extends Activities_BatchRunTestCase { + protected function _prepare() { + parent::_prepare(); + $this->_mock_transport + ->onSendDo(function() + { + throw new RuntimeException('OUPS !, I did it again'); + }); + } + + + /** @test */ + public function shouldLogNoMailSent() { + $this->assertContains('Stephanie\'s Birthday Party : 0 rappel(s) envoyé(s)', + $this->_log_output); + } + + + /** @test */ + public function shouldLogError() { + $this->assertContains('OUPS !, I did it again', + $this->_log_output); + } +} \ No newline at end of file diff --git a/tests/scenarios/Activities/WidgetWithQuotasTest.php b/tests/scenarios/Activities/WidgetWithQuotasTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2eeff4650e4663bcb0b32fb1ca1fb663c81d9790 --- /dev/null +++ b/tests/scenarios/Activities/WidgetWithQuotasTest.php @@ -0,0 +1,111 @@ +<?php +/** + * Copyright (c) 2012-2020, 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 Activities_WidgetWithQuotasDisplayTest extends ViewHelperTestCase { + + protected $_storm_default_to_volatile = true; + + public function setup() { + parent::setup(); + Class_AdminVar::set('ACTIVITY',1); + Class_AdminVar::set('ACTIVITY_SESSION_QUOTAS', 1); + $time_source = new TimeSourceForTest('2014-05-06 14:00:00'); + Class_Activity::setTimeSource($time_source); + Class_SessionActivity::setTimeSource($time_source); + $this->_createActivity(1, '2016-04', '2016-05'); + $this->_createActivity(3, '2010-04', '2010-05'); + $this->_createActivity(5, '2016-10', '2016-02'); + + $this->_user_group = $this->fixture('Class_UserGroup', + ['id' => 3, + 'libelle'=> 'Stagiaires', + 'group_type' => Class_UserGroup::TYPE_MANUAL, + 'rights' => [Class_UserGroup::RIGHT_SUIVRE_ACTIVITY], + 'users' => [Class_Users::find(1)]]); + $this->fixture('Class_Users', + ['id' => 1, + 'login' => 'stagiaire2', + 'user_groups' => [$this->_user_group], + 'password' => 'pwd', + 'id_abon' => 438]); + + Class_SessionActivity::find(2) + ->setSessionActivityInscriptions([$this->fixture('Class_SessionActivityInscription', + ['id' => 2, + 'stagiaire' => Class_Users::find(1), + 'session_activity' => Class_SessionActivity::find(2), + 'adults' => 1, + 'children' => 1])]) + ->save(); + + $this->_renderWidget(); + } + + + protected function _createActivity($id, $date_session, $date_session2) { + $activity = $this->fixture('Class_Activity', + ['id' => $id, + 'libelle' => 'Activity numero ' . $id, + 'visible' => true]); + + $activity->setSessions([$this->fixture('Class_SessionActivity', + ['id' => $id + 1, + 'activity' => $activity, + 'date_debut' => $date_session . '-01', + 'date_limite_inscription' => $date_session . '-01', + 'date_fin' => $date_session . '-04', + 'effectif_inscription_max' => 2, + 'effectif_inscription_child_max' => 2, + 'effectif_child_min' => 0, + 'effectif_child_max' => 2, + 'age_child_max' => 12]) + ]) + ->assertSave(); + } + + + protected function _renderWidget() { + $preferences = ['division' => 1, + 'type_module' => 'ACTIVITIES_WIDGET', + 'preferences' => ['selected_activities' => '3-1-5', + 'display_order' => 'creation', + 'display_group_mode' => 'ByYear', + 'display_mode' => 'Block']]; + $helper = new ZendAfi_View_Helper_Accueil_ActivitiesWidget('ACTIVITIES_WIDGET', $preferences); + $helper->setView($this->view); + $this->_html = $helper->getBoite(); + } + + + /** @test */ + public function activitieShouldBeDisplayedWithNombreInscrits2() { + $this->assertXPathContentContains($this->_html, + '//dd[@class="training_contributors"][preceding-sibling::dt[text()="Nombre d\'inscrits"]]', + '2'); + } + + + /** @test */ + public function activitieShouldBeDisplayedByYear() { + $this->assertXPathContentContains($this->_html, '//h2[1]', '2010'); + } +} diff --git a/tests/scenarios/NoveltyFacet/NoveltyFacetTest.php b/tests/scenarios/NoveltyFacet/NoveltyFacetTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a53cbb29bb963345fcb5b7c18c3f2c74d73915ad --- /dev/null +++ b/tests/scenarios/NoveltyFacet/NoveltyFacetTest.php @@ -0,0 +1,199 @@ +<?php +/** + * Copyright (c) 2012-2020, 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 NoveltyFacetSearchResultConfigTest extends Admin_AbstractControllerTestCase { + protected $_storm_default_to_volatile = true; + + public function setUp() { + parent::setUp(); + Class_CodifThesaurus::ensureRecordNovelty(); + } + + + /** @test */ + public function noveltyFacetShouldBeAvailableInHistoric() { + $this->dispatch('/admin/modules/recherche/config/site/type_module/recherche/id_profil/1/action1/resultat/action2/simple'); + $this->_assertNoveltyIsAvailable(); + } + + + /** @test */ + public function noveltyFacetShouldBeAvailableInTemplates() { + $id = (new Intonation_Template)->tryOn(Class_Profil::getCurrentProfil()); + $this->dispatch('/admin/widget/edit-action/id/recherche_resultat_simple/id_profil/' . $id); + $this->_assertNoveltyIsAvailable(); + } + + + protected function _assertNoveltyIsAvailable() { + $this->assertXPathContentContains('//div[@data-heading="facettes"]//li[@data-id="HNRNR"]', + 'Nouveauté'); + } +} + + + + +class NoveltyFacetDomainEditTest extends Admin_AbstractControllerTestCase { + protected $_storm_default_to_volatile = true; + + + public function setUp() { + parent::setUp(); + Class_CodifThesaurus::ensureRecordNovelty(); + $this->onLoaderOfModel('Class_CodifThesaurus'); + $this->dispatch('/admin/catalogue/add'); + } + + + /** @test */ + public function pageShouldNotContainRecordNoveltyInput() { + $this->assertContains('id_thesaurus not in ("NRNR", "NNNN", "NANA", "CCCC")', + Class_CodifThesaurus::getFirstAttributeForLastCallOn('findAllBy')['where']); + } +} + + + + +class NoveltyFacetSearchResultSimpleTest extends AbstractControllerTestCase { + protected $_storm_default_to_volatile = true; + + + public function setUp() { + parent::setUp(); + Class_CodifThesaurus::ensureRecordNovelty(); + + $this->fixture('Class_Notice', ['id' => 2]); + + Class_Profil::getCurrentProfil() + ->setModulePreference('recherche', 'resultatsimple', 'facettes_codes', 'HNRNR'); + } + + + public function facets() { + return [['HNRNR0001', 'Oui'], + ['HNRNR0002', 'Non']]; + } + + + /** + * @test + * @dataProvider facets + */ + public function withFacetPageShouldContainLinkToFilterByNovelty($facet, $label) { + Zend_Registry::set('sql', + $this->mock() + ->whenCalled('fetchAll') + ->with('select id_notice, facettes from notices Where type=1', true, false) + ->answers([[2, $facet]])); + + $this->dispatch('/opac/recherche/simple/expressionRecherche/*'); + $this->assertXPathContentContains('//a[contains(@href, "/facette/'. $facet .'")]', $label); + } +} + + + + +abstract class NoveltyFacetRecordUpdateTestCase extends ModelTestCase { + protected $_record; + + public function setUp() { + parent::setUp(); + Class_CodifThesaurus::ensureRecordNovelty(); + $this->_record = $this->fixture('Class_Notice', + ['id' => 2, + 'type_doc' => Class_TypeDoc::LIVRE]); + Class_Exemplaire::setTimeSource(new TimeSourceForTest('2021-01-14 16:55:16')); + } + + + public function tearDown() { + Class_Exemplaire::setTimeSource(null); + parent::tearDown(); + } + + + /** @test */ + public function notNoveltyShouldBecomeNovelty() { + $this->_recordFacetAndNovelty('T1 HNRNR0002', '2021-02-19'); + $this->_updateRecord(); + $this->assertContains('HNRNR0001', $this->_record->getFacettes()); + $this->assertNotContains('HNRNR0002', $this->_record->getFacettes()); + } + + + /** @test */ + public function noveltyShouldBecomeNotNovelty() { + $this->_recordFacetAndNovelty('T1 HNRNR0001', ''); + $this->_updateRecord(); + $this->assertContains('HNRNR0002', $this->_record->getFacettes()); + $this->assertNotContains('HNRNR0001', $this->_record->getFacettes()); + } + + + protected function _recordFacetAndNovelty($facets, $novelty_date) { + $this->_record + ->setFacettes($facets) + ->setExemplaires([$this->fixture('Class_Exemplaire', + ['id' => 3, + 'date_nouveaute' => $novelty_date])]) + ->assertSave(); + } + + + protected function _updateRecord() { + } +} + + + + +class NoveltyFacetUpdateFacetsFromExemplairesTest extends NoveltyFacetRecordUpdateTestCase { + protected function _updateRecord() { + $this->_record->updateFacetsFromExemplaires(); + } +} + + + + +class NoveltyFacetUpdateNoveltyFacetsTest extends NoveltyFacetRecordUpdateTestCase { + protected function _updateRecord() { + $this->_record->updateNoveltyFacets(); + } +} + + + + +class NoveltyFacetIndexTest extends ModelTestCase { + /** @test */ + public function findAllByShouldContainRecordNoveltyFacet() { + Class_CodifThesaurus::ensureRecordNovelty(); + $this->onLoaderOfModel('Class_Notice'); + Class_Notice::indexNoveltyFacets(); + $this->assertContains('+(HNNNN* HNANA* HNRNR0001)', + Class_Notice::getFirstAttributeForLastCallOn('findAllBy')['where']); + } +} \ No newline at end of file diff --git a/tests/scenarios/PnbDilicom/PnbDilicomTest.php b/tests/scenarios/PnbDilicom/PnbDilicomTest.php index 4f46447088ce73cc5dc3f9ea564b1eb4e2aecf02..3d172cc4999cf7103efdfb3a72bd114814449347 100644 --- a/tests/scenarios/PnbDilicom/PnbDilicomTest.php +++ b/tests/scenarios/PnbDilicom/PnbDilicomTest.php @@ -2933,10 +2933,18 @@ abstract class PnbDilicomAdminAlbumControllerTestCase extends Admin_AbstractCont ['id' => 23, 'libelle' => 'Heavy Metal']); + $this->fixture('Class_CodifGenre', + ['id' => 24, + 'libelle' => 'Death Metal']); + $this->fixture('Class_CodifSection', ['id' => 33, 'libelle' => 'Espace métal']); + $this->fixture('Class_CodifSection', + ['id' => 34, + 'libelle' => 'Espace musique']); + $fondu = $this->fixture('Class_AlbumCategorie', ['id' => 1301, 'libelle' => 'Fondu']); @@ -2946,8 +2954,8 @@ abstract class PnbDilicomAdminAlbumControllerTestCase extends Admin_AbstractCont 'id_origine' => 'Dilicom-3663608260879', 'titre' => 'Hell is from here to eternity', 'type_doc_id' => Class_TypeDoc::DILICOM, - 'genre' => '23', - 'sections' => '33', + 'genre' => '23;24', + 'sections' => '33;34', 'categorie' => $fondu]) ->addAuthor('Iron Maiden') ->addEditor('EMI') @@ -3034,6 +3042,7 @@ class PnbDilicomAdminAlbumControllerImportDilicomTest extends PnbDilicomAdminAlb public function setUp() { parent::setUp(); + Class_AdminVar::set('DILICOM_PNB_BOARD_DISPLAY_SECTION', true); $this->dispatch('/admin/album/dilicom', true); } @@ -3087,6 +3096,24 @@ class PnbDilicomAdminAlbumControllerImportDilicomTest extends PnbDilicomAdminAlb } + /** @test */ + public function sectionsShouldBeDisplayed() { + $this->assertXPathContentContains('//table//tr/td', 'Heavy Metal, Death Metal'); + } + + + /** @test */ + public function genreShouldBeDisplayed() { + $this->assertXPathContentContains('//table//tr/td', 'Espace métal, Espace musique'); + } + + + /** @test */ + public function multiselectBasketShouldBeDisplayedWithAlbumId() { + $this->assertXPath('//a[contains(@href,"/admin/album/add-model-to-selection/select_id/23")]',$this->_response->getBody()); + } + + /** @test */ public function nbOfHoldsShouldBeSix() { $this->assertXPath('//table//tr[3]/td[text()="6"]'); diff --git a/tests/scenarios/RendezVous/RendezVousAdminTest.php b/tests/scenarios/RendezVous/RendezVousAdminTest.php index 19decf5f40c49267b1e79ab4178278a4e49b2754..1a739d6cfa25c42f3ab1f089572f71dfcd4ed8c8 100644 --- a/tests/scenarios/RendezVous/RendezVousAdminTest.php +++ b/tests/scenarios/RendezVous/RendezVousAdminTest.php @@ -921,7 +921,7 @@ class RendezVousSendNotificationTest extends RendezVousNotificationTestCase { /** @test */ - public function batchSendRendezVousShouldHaveSentOneEmail() { + public function batchSendRendezVousShouldHaveSentThreeEmail() { $this->assertEquals(3, $this->_mock_transport->count()); } diff --git a/tests/scenarios/Templates/PolygoneTemplateAbonneAgendaTest.php b/tests/scenarios/Templates/PolygoneTemplateAbonneAgendaTest.php index a2739db47c327a174c860c28b8f7a0eec0438293..13d93977be2adee9a0b90339cbbac83e8561b89f 100644 --- a/tests/scenarios/Templates/PolygoneTemplateAbonneAgendaTest.php +++ b/tests/scenarios/Templates/PolygoneTemplateAbonneAgendaTest.php @@ -159,6 +159,7 @@ abstract class PolygoneTemplateAbonneAgendaTestCase extends AbstractControllerTe 'effectif_max' => 5, 'effectif_child_min' => 1, 'effectif_child_max' => 5, + 'age_child_max' => 5, 'effectif_inscription_max' => 2, 'effectif_inscription_child_max' => 3, 'lieu' => $this->_gallice_cafe, @@ -206,6 +207,7 @@ abstract class PolygoneTemplateAbonneAgendaTestCase extends AbstractControllerTe 'effectif_max' => 150, 'effectif_child_min' => 0, 'effectif_child_max' => 100, + 'age_child_max' => 5, 'effectif_inscription_max' => 10, 'effectif_inscription_child_max' => 5, 'duree' => 36, @@ -536,8 +538,8 @@ class PolygoneTemplateAbonneAgendaDetailSessionWithRightRegisterTest /** @test */ public function pageShouldContainsLinkToGererLesInscriptions() { - $this->assertXPathContentContains('//a[contains(@href, "admin/session-activity/inscriptions/id/31")][@target="_blank"]', - 'Gérer les inscriptions'); + $this->assertXPathContentContains('//a[contains(@href, "admin/session-activity/inscriptions/id/31/search_session_activity_subscription_status/all")][@target="_blank"]', + 'Nouvelle inscription'); } } @@ -562,8 +564,8 @@ class PolygoneTemplateAbonneAgendaWithRightRegisterTest /** @test */ public function pageShouldContainsLinkToGererLesInscriptions() { - $this->assertXPathContentContains('//a[contains(@href, "admin/session-activity/inscriptions/id/31")][@target="_blank"]', - 'Gérer les inscriptions'); + $this->assertXPathContentContains('//a[contains(@href, "admin/session-activity/inscriptions/id/31/search_session_activity_subscription_status/all")][@target="_blank"]', + 'Nouvelle inscription'); } } diff --git a/tests/scenarios/Templates/TemplatesAgendaTest.php b/tests/scenarios/Templates/TemplatesAgendaTest.php index 947be47b3194887227fcd3f0da819bb86220b679..509ef31b214ae50a959e51b39e71b80be9e54173 100644 --- a/tests/scenarios/Templates/TemplatesAgendaTest.php +++ b/tests/scenarios/Templates/TemplatesAgendaTest.php @@ -113,4 +113,11 @@ class TemplatesAgendaWidgetWithSessionActivityAndRightRegisterTest $this->assertXPathContentContains('//a[contains(@href, "admin/session-activity/inscriptions/id/12")][@target="_blank"]', 'Gérer les inscriptions'); } + + + /** @test */ + public function pageShouldContainsLinkToNouvelleInscription() { + $this->assertXPathContentContains('//a[contains(@href, "admin/session-activity/inscriptions/id/12/search_session_activity_subscription_status/all")][@target="_blank"]', + 'Nouvelle inscription'); + } } \ No newline at end of file