diff --git a/FEATURES/140057 b/FEATURES/140057 new file mode 100644 index 0000000000000000000000000000000000000000..610f37e367651f175baca14dd4db6ffc894602fb --- /dev/null +++ b/FEATURES/140057 @@ -0,0 +1,10 @@ + '140057' => + ['Label' => $this->_('Administration des domaines par site'), + 'Desc' => $this->_('Permet (sur option) d\'affecter une arboresence de domaines à un site voulu. Les permissions des rédacteurs / administrateurs bibliothèque sont prises en compte'), + 'Image' => '', + 'Video' => 'https://youtu.be/dIfvaOrHkq0', + 'Category' => '', + 'Right' => function($feature_description, $user) {return true;}, + 'Wiki' => 'https://wiki.bokeh-library-portal.org/index.php/Domaines', + 'Test' => '', + 'Date' => '2021-08-24'], \ No newline at end of file diff --git a/VERSIONS_WIP/140057 b/VERSIONS_WIP/140057 new file mode 100644 index 0000000000000000000000000000000000000000..62001786cf96b7d09381add051ec95a1c8610207 --- /dev/null +++ b/VERSIONS_WIP/140057 @@ -0,0 +1 @@ + - ticket #140057 : Administration des domaines par site (à l'instar des articles) \ No newline at end of file diff --git a/application/modules/admin/controllers/CatalogueController.php b/application/modules/admin/controllers/CatalogueController.php index 35904dbac5375bcd1fbfbdc16ce8692a474b4183..d9391e33ca50138c490457ae35a8c70bb208ab00 100644 --- a/application/modules/admin/controllers/CatalogueController.php +++ b/application/modules/admin/controllers/CatalogueController.php @@ -23,6 +23,10 @@ class Admin_CatalogueController extends ZendAfi_Controller_Action { protected $_user; + public function getPlugins() { + return [ZendAfi_Controller_Plugin_Manager_Catalogue::class]; + } + public function preDispatch() { parent::preDispatch(); $this->view->user = $this->_user = Class_Users::getIdentity(); @@ -30,9 +34,56 @@ class Admin_CatalogueController extends ZendAfi_Controller_Action { public function indexAction() { + $this->view->titre = $this->_('Définition des domaines'); + + if (Class_AdminVar::isModuleEnabled('ENABLE_DOMAINS_PER_LIBRARIES')) + return $this->_renderListMode(); + if (!$this->view->catalogues = Class_Catalogue::findTopCatalogues()) $this->view->message = $this->_('Aucun domaine n\'a été trouvé'); - $this->view->titre = $this->_('Définition des domaines'); + } + + + protected function _findAccessibleLibrariesForDomainsListMode() { + $libraries = Class_Bib::findAllAccessibleToCurrentUser(); + if (($this->_user->hasRightToAccess(Class_UserGroup::RIGHT_USER_DOMAINES_TOTAL_ACCESS) + || + $this->_user->hasRightToAccess(Class_UserGroup::RIGHT_USER_DOMAINES_SUPPRESSION_LIMIT) + || + !$this->_user->hasUserGroups()) && $this->_user->isRoleLibraryLimited()) { + $libraries []= Class_Bib::getPortail(); + } + return $libraries; + } + + + protected function _renderListMode() { + if($this->_request->isPost()) + return $this->_redirectToRefererWithNewParams(['title_search' => $this->_getPost()['title_search'], + 'order' => $this->_getParam('order')]); + + $library = ($id_bib = $this->_getParam('id_bib', null)) + ? Class_Bib::find($id_bib) + : Class_Bib::findForCurrentUser(); + + if (!$domain = Class_Catalogue::find($this->_getParam('id', null))) + $domain = Class_Catalogue::newInstanceWithId(null, + ['sous_domaines' => [], + 'library_id' => $library->getId()]); + + $params = ['bib' => $domain->getLibrary(), + 'id_bib' => $id_bib, + 'search_value' => trim($this->_getParam('title_search', null)), + 'bibs' => $this->_findAccessibleLibrariesForDomainsListMode(), + 'model' => $domain]; + + $this->view->list = ($params['search_value'] + || !$domain->isNew() + || (null !== $params['id_bib'])) + ? $this->_helper->ListViewMode_Catalogue($params) + : $this->_helper->ListViewMode_Library($params); + + $this->renderScript('admin/listViewMode.phtml'); } @@ -149,6 +200,13 @@ class Admin_CatalogueController extends ZendAfi_Controller_Action { $this->view->catalogue = $model; $this->view->form = $form; + if (Class_AdminVar::isModuleEnabled('ENABLE_DOMAINS_PER_LIBRARIES')) + $form->setAttrib('data-backurl', + Class_Url::relative(['module' => 'admin', + 'controller' => 'catalogue', + 'id_catalogue' => null, + 'id' => $model->getParentId() ? $model->getParentId() : null, + 'id_bib' => $model->getParentId() ? null : (int)$model->getLibraryId()])); return $form->setAction($this->view->url()); } @@ -164,6 +222,8 @@ class Admin_CatalogueController extends ZendAfi_Controller_Action { $post = $this->_transformPostValuesToThesaurusValues($post); $post = $this->_transformPostValuesToCustomFormValues($post, $catalogue); + if ($library_id = $this->_getParam('id_bib')) + $post['library_id'] = $library_id; return $catalogue ->updateAttributes($post) @@ -238,19 +298,13 @@ class Admin_CatalogueController extends ZendAfi_Controller_Action { public function domainesAction() { - $data = [(new Class_Catalogue())->getDomainesJsonWithoutPaniers()]; + $data = (new Class_Catalogue_TreeSelectJson())->renderWithoutCarts(); $this->_helper->json($data); } public function browsableDomainsAction() { - $this->_helper->viewRenderer->setNoRender(); - $data = []; - $data[] = (new Class_Catalogue())->getBrowsableDomainsJson(); - $JSON = json_encode($data); - - $this->getResponse()->setHeader('Content-Type', 'application/json; charset=utf-8'); - $this->getResponse()->setBody($JSON); + return $this->_helper->json((new Class_Catalogue_TreeSelectJson())->renderBrowsableDomains()); } @@ -303,6 +357,7 @@ class Admin_CatalogueController extends ZendAfi_Controller_Action { $this->_helper->notify($this->_('Panier "%s" retiré', $panier->getLibelle())); } + protected function formAjoutPanier($catalogue) { $options = ['' => $this->_('Veuiller sélectionner un panier')]; $paniers = Class_PanierNotice::findAllBelongsToAdmin(); @@ -320,7 +375,7 @@ class Admin_CatalogueController extends ZendAfi_Controller_Action { public function domainesPaniersJsonAction() { $this->_helper->json([$this->_user->getPaniersJson(), - (new Class_Catalogue())->getDomainesJson(), + (new Class_Catalogue_TreeSelectJson())->render(), (new Class_PanierNotice())->getPaniersAdminsNotInCatalogueJson()]); } -} \ No newline at end of file +} diff --git a/application/modules/admin/controllers/CmsController.php b/application/modules/admin/controllers/CmsController.php index 21274123cc7bdaf5742a97f3c10aabcb9f5e27ab..f5530195aa16a187cb1ace20df704d286ad02683 100644 --- a/application/modules/admin/controllers/CmsController.php +++ b/application/modules/admin/controllers/CmsController.php @@ -34,25 +34,13 @@ class Admin_CmsController extends ZendAfi_Controller_Action { parent::init(); $this->identity = Class_Users::getIdentity(); - - $this->_bib = $this->identity->isRoleLibraryLimited() ? - $this->identity->getBib() : - $this->_bib = Class_Bib::getPortail(); - } - - - protected function _getBibs() { - if (0 != $this->_bib->getId()) - return [$this->_bib]; - - $bibs = Class_Bib::findAllBy(['order' => 'libelle']); - array_unshift($bibs, $this->_bib); - return $bibs; } protected function _renderList() { - $bibs = $this->_getBibs(); + $bibs = Class_Bib::findAllAccessibleToCurrentUser(); + $current_library = Class_Bib::findForCurrentUser(); + $ids = array_map(function($model) { return $model->getId(); @@ -65,7 +53,7 @@ class Admin_CmsController extends ZendAfi_Controller_Action { $id_bib = $this->_getParam('id_bib', $this->identity->isRoleLibraryLimited() - ? $this->_bib->getId() + ? $current_library->getId() : null); $article = ($id_article = $this->_getParam('id', null)) @@ -80,7 +68,7 @@ class Admin_CmsController extends ZendAfi_Controller_Action { 'search_value' => $search, 'order' => $order, ZendAfi_Controller_Action_Helper_ListViewMode_Article::STATUS_SEARCH => $status, - 'bib' => $this->_bib, + 'bib' => $current_library, 'id_bib' => $id_bib, 'id_cat' => $id_cat]; @@ -111,7 +99,7 @@ class Admin_CmsController extends ZendAfi_Controller_Action { if (Class_AdminVar::isArticlesListMode()) return $this->_renderList(); - $bibs = $this->_getBibs(); + $bibs = Class_Bib::findAllAccessibleToCurrentUser(); $add_link_builder = function($bib) { $links = []; diff --git a/application/modules/admin/views/scripts/catalogue/_catalogue_row.phtml b/application/modules/admin/views/scripts/catalogue/_catalogue_row.phtml index 3b16c8d1c2704ce1c84083b6ebc0b71a155476ef..1c7ce59d8433d1bcd48f2682f85d0c638cc30d2a 100644 --- a/application/modules/admin/views/scripts/catalogue/_catalogue_row.phtml +++ b/application/modules/admin/views/scripts/catalogue/_catalogue_row.phtml @@ -1,55 +1,14 @@ -<?php -$catalog = $this->catalogue; -$user = Class_Users::getIdentity(); -$editable = $catalog->canBeDeletedOrModifyByUser($user); -?> <li class="<?php echo $this->item_class; ?>"> - <div><?php echo $this->escape($catalog->getLibelle()); ?></div> - <div class="commentaire"></div> - <div class="actions"> - <?php - $actions = [ - ['action' => 'tester', 'icon' => 'test', 'help' => $this->_('Indexer les notices')], - ['action' => 'edit', 'icon' => 'edit', 'help' => $this->_('Modifier'), 'display' => $editable], - ['action' => 'duplicate', 'icon' => 'copy', 'help' => $this->_('Dupliquer')], - ['action' => 'add', 'icon' => 'add_page', 'help' => $this->_('Ajouter un sous-domaine'), 'display' => $editable], - ['action' => 'paniers', 'icon' => 'basket', 'help' => $this->_('Paniers'), 'display' => $editable] - ]; - - $current_skin = Class_Admin_Skin::current(); - foreach ($actions as $action) { - if (isset($action['display']) && !$action['display']) - continue; - - echo $this->tagAnchor($this->url(['action' => $action['action'], - 'id_catalogue' => $catalog->getId()]), - $current_skin->renderActionIconOn($action['icon'], $this, - ['alt' => $action['help'], - 'title' => $action['help']])); - } - - if ($editable) - echo $this->tag('a', $this->boutonIco('type=del'), - ['href' => BASE_URL . '/admin/catalogue/delete/id_catalogue/'.$catalog->getId()]); - - $catalogue_url = $this->url(['module' => 'opac', - 'controller' => 'recherche', - 'action' => 'simple', - 'id_catalogue' => $catalog->getId()], - null, true); - - echo $this->tagPreview($catalogue_url, - $this->_('Visualiser le domaine "%s" dans un nouvel onglet', $catalog->getLibelle())); - echo $this->permalink($catalogue_url); - - ?> - </div> - <ul> - <?php - echo $this->partialCycle('catalogue/_catalogue_row.phtml', - 'catalogue', - $catalog->getSousDomaines(), - ['first', 'second']); + <div><?php echo $this->escape($this->catalogue->getLibelle()); ?></div> + <div class="commentaire"></div> + <?php echo $this->renderPluginsActions($this->catalogue) ?> + <ul> + <?php + echo $this->partialCycle('catalogue/_catalogue_row.phtml', + 'catalogue', + $this->catalogue->getSousDomaines(), + ['first', 'second'], + ['plugins' => $this->plugins]); ?> </ul> </li> diff --git a/application/modules/admin/views/scripts/catalogue/index.phtml b/application/modules/admin/views/scripts/catalogue/index.phtml index e952257b4e8c04406bd379705b61b6b8e1f75498..c8aff5829d6728dfcffb89279c3e60b98ca07098 100644 --- a/application/modules/admin/views/scripts/catalogue/index.phtml +++ b/application/modules/admin/views/scripts/catalogue/index.phtml @@ -16,7 +16,8 @@ if (Class_Users::getIdentity()->hasRightAccessDomaines()) { ?> echo $this->partialCycle('catalogue/_catalogue_row.phtml', 'catalogue', $this->catalogues, - ['first', 'second']);?> + ['first', 'second'], + ['plugins' => $this->plugins]);?> </ul> <div class="clear"></div> </div> diff --git a/application/modules/opac/controllers/AbonneController.php b/application/modules/opac/controllers/AbonneController.php index a881c63aca85ea87c04e0161da67b9c9fbee1451..dad49362518ae64183ffc5e238eff586dedabf7d 100644 --- a/application/modules/opac/controllers/AbonneController.php +++ b/application/modules/opac/controllers/AbonneController.php @@ -1066,7 +1066,7 @@ class AbonneController extends ZendAfi_Controller_Action { $data[] = $this->_user->getPaniersJson(); if ($this->_user->canAccessBackend()) - $data[] = (new Class_Catalogue())->getDomainesJson(['removeCheckbox' => true]); + $data[] = (new Class_Catalogue_TreeSelectJson())->renderWithoutCheckbox(); $this->_helper->json($data); } diff --git a/application/modules/opac/controllers/BibController.php b/application/modules/opac/controllers/BibController.php index faa212bfa9bfb6f1c165fce7882a7f63dc472655..0757f026ca80c04e3f5808c5928a7fb785681908 100644 --- a/application/modules/opac/controllers/BibController.php +++ b/application/modules/opac/controllers/BibController.php @@ -229,13 +229,6 @@ class BibController extends ZendAfi_Controller_Action { } - public function giveInfoBulle($id_bib) { - $class_bib = new Class_Bib(); - $bib = $class_bib->getBibById($id_bib); - return(addslashes($bib->LIBELLE)); - } - - public function widgetPageAction() { $viewRenderer = $this->getHelper('ViewRenderer'); @@ -391,4 +384,4 @@ class BibController extends ZendAfi_Controller_Action { $this->_helper->notify($this->_('Une erreur s\'est produite.'), ['status' => 'error']); return $this->_redirectClose($this->_getReferer()); } -} \ No newline at end of file +} diff --git a/cosmogramme/sql/patch/patch_416.php b/cosmogramme/sql/patch/patch_416.php new file mode 100644 index 0000000000000000000000000000000000000000..36124ababfd8657086a9c4c977d1fa0924eaae72 --- /dev/null +++ b/cosmogramme/sql/patch/patch_416.php @@ -0,0 +1,8 @@ +<?php +$adapter = Zend_Db_Table_Abstract::getDefaultAdapter(); + +try { + $adapter->query('ALTER TABLE `catalogue`' + . ' ADD COLUMN `library_id` int(11) unsigned null default null,' + . ' ADD KEY `library_id` (`library_id`)'); +} catch(Exception $e) {} diff --git a/library/Class/AdminVar.php b/library/Class/AdminVar.php index 8f4a8f74a37ef115bfb843d8cd1a437317be3e59..2486dffe33d84390dad8fc111967d5ed48fd05de 100644 --- a/library/Class/AdminVar.php +++ b/library/Class/AdminVar.php @@ -494,6 +494,7 @@ Pour vous désabonner de la lettre d\'information, merci de cliquer sur le lien 'OAI_REPOSITORY_NAME' => Class_AdminVar_Meta::newDefault($this->_('Contenu de la balise "repositoryName" dans la réponse au verb Identify, si vide sera [NOM DU SERVEUR] Oai repository')), 'OAI_ADMIN_EMAIL' => Class_AdminVar_Meta::newDefault($this->_('Contenu de la balise "adminEmail" dans la réponse au verb Identify, si vide sera tiré de la variable cosmogramme "mail_admin"')), 'CUSTOM_DOMAIN_FORM' => Class_AdminVar_Meta::newOnOff($this->_('Activation de la personnalisation des formulaires des domaines')), + 'ENABLE_DOMAINS_PER_LIBRARIES' => Class_AdminVar_Meta::newOnOff($this->_('Activation de la répartition des domaines par bibliothèque dans l\'interface d\'administration')), ]; } diff --git a/library/Class/Bib.php b/library/Class/Bib.php index 45be88a991e0bbe9603ab48fbe022208541f7f30..c170d7e7de1212199ca839ed7fa626b485348725 100644 --- a/library/Class/Bib.php +++ b/library/Class/Bib.php @@ -22,12 +22,6 @@ require_once dirname(__FILE__)."/CompositeBuilder.php"; -class BibCSite extends Zend_Db_Table_Abstract { - protected $_name = 'bib_c_site'; -} - - - class BibLoader extends Storm_Model_Loader { use Trait_Translator; @@ -270,10 +264,30 @@ class BibLoader extends Storm_Model_Loader { return $o->getJourSemaine() == $day_of_week; }); } + + + public function findAllAccessibleToCurrentUser() { + $current_library = $this->findForCurrentUser(); + if (!$current_library->isPortail()) + return [$current_library]; + + $libraries = Class_Bib::findAllBy(['order' => 'libelle']); + array_unshift($libraries, $current_library); + return $libraries; + } + + + public function findForCurrentUser() { + $current_user = Class_Users::getIdentity(); + return $current_user->isRoleLibraryLimited() + ? $current_user->getBib() + : $this->getPortail(); + } } + class Class_Bib extends Storm_Model_Abstract { use Trait_PermissionTargetable, @@ -624,21 +638,6 @@ class Class_Bib extends Storm_Model_Abstract { - public function getBibById($id_bib) - { - try - { - $BibCSite = new BibCSite(); - $where = $BibCSite->getAdapter()->quoteInto('ID_SITE=?', $id_bib); - return $fetch = $BibCSite->fetchRow($where); - }catch (Exception $e) - { - logErrorMessage('Class: Class_Zone; Function: getBibById' . NL . $e->getMessage()); - return $this->_dataBaseError; - } - } - - public function getFilePath() { return ($this->getFileName() == $this->getFile()) ? $this->getBasePath().$this->getFile() : $this->getFile(); diff --git a/library/Class/Catalogue.php b/library/Class/Catalogue.php index 24db05655f4377960dd1afbfa5aef043f61ff05d..1f20cbae31e14935932e6300d700f364f9df92f6 100644 --- a/library/Class/Catalogue.php +++ b/library/Class/Catalogue.php @@ -20,685 +20,6 @@ */ -class CatalogueLoader extends Storm_Model_Loader { - use Trait_Translator, Trait_TimeSource; - - const DEFAULT_ITEMS_BY_PAGE = 100; - - protected $_indexable_cache; - - public function loadNoticesFor($catalogue, $itemsByPage = self::DEFAULT_ITEMS_BY_PAGE, $page = 1, $find_all_params = null) { - if (null == $catalogue) - return []; - - if ('' == ($where = $this->clausesFor($catalogue))) - return []; - - if (!is_array($find_all_params)) - $find_all_params = []; - - if (!isset($find_all_params['limitPage'])) - $find_all_params['limitPage'] = [$page, $itemsByPage]; - - $find_all_params['where'] = $where; - - return Class_Notice::findAllBy($find_all_params); - } - - - public function findAllCataloguesAIndexer() { - return array_filter(Class_Catalogue::findAllIndexable(), - function ($catalogue) - { - return '' != Class_Catalogue::clausesFor($catalogue); - }); - } - - - public function findAllIndexableNotEmpty() { - return array_filter(Class_Catalogue::findAllIndexable(), - function($catalog) - { - return !$catalog->isEmpty(); - }); - } - - - public function findAllIndexable() { - return $this->_indexable_cache - ? $this->_indexable_cache - : $this->_indexable_cache = Class_Catalogue::findAllBy(['indexer' => true, - 'order' => 'libelle']); - } - - - public function getDomainsForBreadcrumb($breadcrumb) { - $domains_ids = array_filter(explode(';', $breadcrumb)); - $domains = []; - foreach ($domains_ids as $domain_id) - $domains[] = Class_Catalogue::find($domain_id); - - return $domains; - } - - - public function getMultiOptionsFacets($ids) { - $domain_labels = ['' => $this->_('tous')]; - if (!$domains = Class_Catalogue::findAllBy(['id_catalogue' => $ids, - 'order' => 'libelle'])) - return $domain_labels; - - foreach($domains as $domain) - if ($th = Class_CodifThesaurus::findThesaurusForCatalogue($domain->getId())) - $domain_labels[$th->getFacetteIndex()]= $th->getLibelleFacette(); - - return $domain_labels; - } - - - public function updateAllThesaurusForCatalogueChildren($catalogue_id, $thesaurus_id) { - $catalogues = Class_Catalogue::findAllBy(['parent_id' => $catalogue_id]); - - foreach ($catalogues as $catalogue) { - Class_CodifThesaurus::deleteAllWithIdOrigineAndCode($catalogue->getId(), - Class_CodifThesaurus::fixedCodeOf('Domain')); - $new_thesaurus = $catalogue->getNewThesaurus(); - $new_thesaurus_id = Class_CodifThesaurus::findNextThesaurusChildId('catalogue', - $thesaurus_id); - $new_thesaurus->setIdThesaurus($new_thesaurus_id); - $new_thesaurus->save(); - - Class_Catalogue::getLoader() - ->updateAllThesaurusForCatalogueChildren($catalogue->getId(), $new_thesaurus_id); - } - } - - - public function countNoticesFor($catalogue) { - if (!$catalogue) - return 0; - - if ('' == ($where = $this->clausesFor($catalogue))) - return 0; - - return Class_Notice::countBy(['where' => $where]); - } - - - public function clausesFor($catalogue) { - if (!$catalogue) - return ''; - - $fromUntil = $this->fromUntilClauseFor($catalogue); - - if ($catalogue->isMatchingAllNotices()) - return $fromUntil ? $fromUntil : '1=1'; - - $conditions = array_filter(array_merge($this->_catalogueConditions($catalogue), - [$fromUntil])); - - return 0 < count($conditions) - ? implode(' and ', $conditions) - : ''; - } - - - protected function _localClausesFor($catalogue, $against='') { - $conditions = []; - - if ($facets = $this->facetsClauseFor($catalogue, $against)) - $conditions[] = $facets; - - if ($docType = $this->docTypeClauseFor($catalogue)) - $conditions[] = $docType; - - if ($year = $this->yearClauseFor($catalogue)) - $conditions[] = $year; - - if ($cote = $this->coteClauseFor($catalogue)) - $conditions[] = $cote; - - if ($new = $this->nouveauteClauseFor($catalogue)) - $conditions[] = $new; - - return $conditions; - } - - - protected function _noticesLinked($catalogue) { - if (!$catalogue || $catalogue->isCustomDomainForm()) - return ''; - - if (!Class_NoticeDomain::getClesNoticesForDomain($catalogue->getId())) - return ''; - - return (new Class_MoteurRecherche())->prepareFacetteDomainForOrConditions($catalogue->getId()); - } - - - /** - * @param $catalogue Class_Catalogue - * @return string - */ - public function facetsClauseFor($catalogue, $against = '') { - $against_ou = ''; - $facets = ['B' => $catalogue->getBibliotheque(), - 'S' => $catalogue->getSection(), - 'G' => $catalogue->getGenre(), - 'L' => $catalogue->getLangue(), - 'Y' => $catalogue->getAnnexe(), - 'E' => $catalogue->getEmplacement(), - 'H' => $catalogue->getThesaurusNovelty()]; - - foreach ($facets as $k => $v) - $against .= Class_Catalogue::getSelectionFacette($k, $v); - - $facets = ['A' => $catalogue->getAuteur(), - 'M' => $catalogue->getMatiere(), - 'D' => $catalogue->getDewey(), - 'P' => $catalogue->getPcdm4(), - 'H' => $catalogue->getThesaurus(), - 'Z' => $catalogue->getTags(), - 'F' => $catalogue->getInteret()]; - - foreach ($facets as $k => $v) - $against_ou .= Class_Catalogue::getSelectionFacette($k, - $v, - in_array($k, - ['M', 'D', 'P','H']), - false); - - if ('' != $against_ou) - $against .= ' +(' . $against_ou . ")"; - - if ('' == $against) - return ''; - - return "MATCH(facettes) AGAINST('".$against."' IN BOOLEAN MODE)"; - } - - - public function docTypeClauseFor($catalogue) { - if (!$docType = $catalogue->getTypeDoc()) - return ''; - - $parts = array_filter(explode(';', $docType)); - return (1 == count($parts)) ? - ('notices.type_doc=\'' . $parts[0]) . '\'' : - ('notices.type_doc IN (\'' . implode('\', \'', $parts) . '\')'); - } - - - public function yearClauseFor($catalogue) { - $clauses = []; - if ($start = $catalogue->getAnneeDebut()) - $clauses[] = "annee >= '" . $start . "'"; - - if($end = $catalogue->getAnneeFin()) - $clauses[] = "annee <= '" . $end . "'"; - - if (0 == count($clauses)) - return ''; - - return implode(' and ', $clauses); - } - - - public function coteClauseFor($catalogue) { - $clauses = []; - if ($start = $catalogue->getCoteDebut()) - $clauses[] = "cote >= '" . strtoupper($start) . "'"; - - if ($end = $catalogue->getCoteFin()) - $clauses[] = "cote <= '". strtoupper($end) . "'"; - - if (0 == count($clauses)) - return ''; - - return implode(' and ', $clauses); - } - - - public function nouveauteClauseFor($catalogue) { - /* Attention : la date de creation corresponds à la date de fin de nouveauté */ - if (1 != $catalogue->getNouveaute()) - return ''; - - return 'date_creation >= \'' . $this->getCurrentDate() . '\''; - } - - - public function fromUntilClauseFor($catalogue) { - $clauses = []; - if ($start = $catalogue->getFrom()) - $clauses[] = "created_at >= '" . $start . "'"; - - if($end = $catalogue->getUntil()) - $clauses[] = "created_at <= '" . $end . "'"; - - if (0 == count($clauses)) - return ''; - - $clauses[] = 'created_at is not null'; - - return implode(' and ', $clauses); - } - - - /** - * @return array [id => label] - */ - public function allByIdLabel() { - return $this->byIdLabel(Class_Catalogue::findAllBy(['order' => 'libelle'])); - } - - - /** - * @return array [id => label] - */ - public function byIdLabel($domains) { - $datas = []; - foreach($domains as $domain) - $datas[$domain->getId()] = $domain->getLibelle(); - return $datas; - } - - - /** - * @return array - */ - public function findTopCatalogues() { - return Class_Catalogue::findAllBy(['where' => 'parent_id is null', - 'order' => 'libelle']); - } - - - /** - * @return Class_Catalogue - */ - public function getRoot() { - return Class_Catalogue::newInstanceWithId(null, - ['sous_domaines' => Class_Catalogue::findTopCatalogues()]); - } - - - /** - * @param $treeNode Trait_TreeNode - * @return Class_Catalogue - */ - public function findWithSamePathAs($treeNode) { - return Class_Catalogue::getRoot()->findByPath($treeNode->getPath()); - } - - - public function fetchAllNoticesByPreferences($preferences) { - $requetes = $this->getRequetes($preferences); - if (!array_key_exists("req_liste", $requetes)) - return []; - - $nb_par_page = (array_key_exists('aleatoire', $preferences) - && array_key_exists('nb_analyse', $preferences) - && $preferences['aleatoire'] - && $preferences['nb_analyse']) - ? $preferences['nb_analyse'] - : $preferences['nb_notices']; - - return Class_Notice::findAllByRequeteRecherche($requetes['req_ids'], - $nb_par_page, - 1); - } - - - public function getRequetes($preferences, $fields = null) { - if (isset($preferences['id_panier']) - && (0 !== (int)$preferences['id_panier'])) - return $this->getRequetesPanier($preferences); - - $catalogue = isset($preferences['id_catalogue']) - ? Class_Catalogue::find($preferences['id_catalogue']) - : null; - - if ($catalogue && $catalogue->isEmpty()) - return []; - - $against = $this->selectionFacettesForCatalogueRequestByPreferences($preferences); - - $conditions = $this->_catalogueConditions($catalogue, $against); - - if (isset($preferences['only_img']) && ($preferences['only_img'] == Class_Catalogue::ONLY_IMG) - && (($catalogue && Class_Catalogue::hasFilters($preferences['id_catalogue'])) - || !$catalogue)) - $conditions[] = "url_vignette > '' and url_vignette != '" . Class_WebService_Vignette::NO_DATA . "' "; - - if (isset($preferences['only_img']) && ($preferences['only_img'] == Class_Catalogue::WITHOUT_IMG)) - $conditions[] = "url_vignette=''"; - - $join = (isset($preferences['avec_avis']) && ($preferences['avec_avis'] == 1)) - ? ' INNER JOIN notices_avis ON notices.clef_oeuvre=notices_avis.clef_oeuvre ' - : ''; - - $order_by = $this->orderByForCatalogueRequestByPreferences($preferences); - $limite = $this->limitForCatalogueRequestByPreferences($preferences); - - $sql = 'select %s from notices' . - $join . - (new Class_MoteurRecherche)->getConditionsForRequest(array_filter($conditions), - $this->_noticesLinked($catalogue)); - - return ['req_liste' => sprintf($sql, $fields ? implode(',', $fields) : '*') - . $order_by . $limite, - 'req_comptage' => sprintf($sql, 'count(*)'), - 'req_facettes' => sprintf($sql, 'notices.id_notice, notices.type_doc, facettes') - . $limite, - 'req_ids' => sprintf($sql, 'notices.id_notice') . $order_by . $limite]; - } - - - protected function _catalogueConditions($catalogue, $against='') { - if (!$catalogue) - return $against - ? ["MATCH(facettes) AGAINST('" . $against . "' IN BOOLEAN MODE)"] - : []; - - if (!$catalogue->isCustomDomainForm()) - return $this->_localClausesFor($catalogue, $against); - - $search_engine = (new Class_MoteurRecherche) - ->visitSearchSettings((new Class_CriteresRecherche) - ->clearProfil() - ->setParam('id_catalogue', $catalogue->getId())); - - return !is_array($search_engine->buildWherePartQuery()) - ? $search_engine->getConditions() - : []; - } - - - public function selectionFacettesForCatalogueRequestByPreferences($preferences) { - if (!isset($preferences['facettes'])) - return ''; - - $against = ''; - $facettes = explode(';', $preferences['facettes']); - foreach($facettes as $facette) { - $facette = trim($facette); - $against .= $this->getSelectionFacette(substr($facette, 0, 1), substr($facette, 1)); - } - - return $against; - } - - - public function orderByForCatalogueRequestByPreferences($preferences) { - if( ! array_key_exists('tri', $preferences)) - return ' order by alpha_titre '; - - $tri = $preferences['tri']; - - if ($tri == '0' || $tri == 'alpha_titre') - return ' order by alpha_titre '; - - if ( $tri == '1' || $tri == 'date_creation desc') - return ' order by date_creation DESC '; - - if ($tri == '2' || $tri == 'nb_visu desc') - return ' order by nb_visu DESC '; - - if ($tri == '3' || $tri == 'annee desc') - return ' order by annee DESC '; - - return $tri instanceof Class_MoteurRecherche_OrderCriteria - ? sprintf(' order by %s ', $tri->getOrder()) - : ''; - } - - - public function limitForCatalogueRequestByPreferences($preferences, $max_limited = false) { - if ( $max_limited ) - return ' LIMIT 5000'; - - if ( isset($preferences["aleatoire"]) - && 1 == (int) $preferences["aleatoire"]) - return sprintf(' LIMIT 0,%d', (int) $preferences["nb_analyse"]); - - if (isset($preferences['nb_notices']) && $preferences["nb_notices"]) - return sprintf(' LIMIT 0,%d', (int) $preferences["nb_notices"]); - - return ' LIMIT 5000'; //LL: j'ai rajouté une limite max car explosion mémoire sur des catalogues mal définis - } - - - public function getRequetesPanier($preferences) { - $panier = null; - if (array_key_exists('id_user', $preferences)) - $panier = Class_PanierNotice::findFirstBy(['id_user' => $preferences['id_user'], - 'id' => $preferences['id_panier']]); - if (!$panier) - $panier = Class_PanierNotice::find($preferences['id_panier']); - - if (!$panier) - return ['nombre' => 0]; - - $cles_notices = $panier->getClesNotices(); - if (empty($cles_notices)) - return ['nombre' => 0]; - - $keys = []; - foreach($cles_notices as $notice) { - if (!trim($notice)) - continue; - $keys[] = "'" . $notice . "'"; - } - $in_sql = implode(',', $keys); - - $limite = ($preferences['aleatoire'] == 1) - ? $preferences['nb_analyse'] : $preferences['nb_notices']; - $limite = ($limite) ? 'LIMIT 0,' . $limite : ''; - - $order_by = ''; - - if (!isset($preferences["tri"])) - $preferences["tri"] = 0; - - if ($preferences["tri"]==0) - $order_by=" order by alpha_titre "; - if ($preferences["tri"]==1) - $order_by=" order by date_creation DESC "; - if ($preferences["tri"]==2) - $order_by=" order by nb_visu DESC "; - if($preferences['tri'] > 2) - $order_by = ' order by FIELD(notices.clef_alpha, ' . $in_sql . ') '; - - $condition = (array_isset("only_img", $preferences) - && $preferences["only_img"] == 1) - ? " and url_vignette > '' and url_vignette != '" . Class_WebService_Vignette::NO_DATA . "'" - : ''; - $condition .= ' and type=1 '; - - $join = (array_isset("avec_avis", $preferences) && $preferences["avec_avis"] == 1) - ? ' INNER JOIN notices_avis ON notices.clef_oeuvre=notices_avis.clef_oeuvre ' - : ''; - - $sql = 'select %s from notices ' - . $join - . 'where notices.clef_alpha in(' . $in_sql . ')' - . $condition; - - return ['req_liste' => sprintf($sql, '*') . $order_by . $limite, - 'req_comptage' => sprintf($sql, 'count(*)'), - 'req_facettes' => sprintf($sql, 'id_notice, notices.type_doc, facettes') . $limite, - 'req_ids' => sprintf($sql, 'notices.id_notice') . $order_by . $limite]; - } - - - public function getNoticesFromCacheByPreferences($preferences) { - $callback = function() use ($preferences) { - return Class_Catalogue::getLoader()->fetchAllNoticesByPreferences($preferences); - }; - - return (array_key_exists('aleatoire', $preferences) - && $preferences['aleatoire']) - ? $callback() - : (new Storm_Cache())->memoize([$preferences, __CLASS__, __FUNCTION__], $callback); - } - - - public function getNoticesByPreferences($preferences) { - if (isset($preferences['id_catalogue']) - && ($catalogue = Class_Catalogue::getLoader()->find($preferences['id_catalogue']))) { - $preferences['catalogue_cache_key'] = serialize($catalogue->toArray()); - } - - $notices = $this->getNoticesFromCacheByPreferences($preferences); - - if ((int)$preferences["aleatoire"] !== 1) - return $notices; - - shuffle($notices); - return array_slice ($notices, 0, $preferences["nb_notices"]); - } - - - public function hasFilters($id) { - if(!$catalogue = Class_Catalogue::find($id)) - return false; - - return !$catalogue->hasNoSettings(); - } - - - public function hasFiltersOrLinkedRecords($id) { - return ($catalog = Class_Catalogue::find((int)$id)) - ? !$catalog->isEmpty() - : false; - } - - - public function saveThesaurus($catalogue) { - if ($thesaurus = Class_CodifThesaurus::findThesaurusForCatalogue($catalogue->getId())) { - $catalogue->deleteThesaurusInFacette($thesaurus->getIdThesaurus()); - $catalogue->updateThesaurusLabel($thesaurus); - } else if (!$thesaurus = $catalogue->saveThesauriParents()) - return; - - if($catalogue->hasDomaineParent()){ - $parent=$catalogue->getParent(); - $thesaurus_parent = $parent->saveThesauriParents(); - if (!$thesaurus_parent) - return null; - $new_thesaurus_id=Class_CodifThesaurus::findNextThesaurusChildId( - 'catalogue', - $thesaurus_parent->getIdThesaurus()); - } - else if (strlen($thesaurus->getIdThesaurus())>8) { - $new_thesaurus_id=Class_CodifThesaurus::findNextRacineCatalogue();} - else - return $thesaurus; - - if ($thesaurus->getId() && ($new_thesaurus_id != $thesaurus->getIdThesaurus())) { - $thesaurus->setIdThesaurus($new_thesaurus_id); - $thesaurus->setLibelle($catalogue->getLibelle()); - $thesaurus->save(); - - Class_Catalogue::updateAllThesaurusForCatalogueChildren($catalogue->getId(),$new_thesaurus_id); - return $thesaurus; - } - - $thesaurus->setIdThesaurus($new_thesaurus_id); - $thesaurus->setLibelle($catalogue->getLibelle()); - $thesaurus->save(); - - return $thesaurus; - } - - - public function getIds($domains) { - return (new Storm_Model_Collection($domains)) - ->collect('id') - ->getArrayCopy(); - } - - - public function hasViewableDomain() { - return 0 < count(Class_Catalogue::findAllIndexableNotEmpty()); - } - - - public function getSelectionFacette($type, $valeurs, $descendants = false, $signe = true) { - if ( !$valeurs = array_filter(explode(';', $valeurs))) - return false; - - $cond = ''; - foreach ($valeurs as $valeur) { - if (!$valeur) - continue; - - if (!$descendants) { - $cond .= $type . $valeur . ' '; - continue; - } - - if ('M' != $type) { - $cond .= $type . $valeur . '* '; - continue; - } - - if (!$matiere = Class_Matiere::find($valeur)) - continue; - - if ('' != ($sous_vedettes = trim($matiere->getSousVedettes()))) - $valeur .= str_replace(' ', ' M', ' ' . $sous_vedettes); - $cond .= $type . $valeur . ' '; - } - - $cond = trim($cond); - - return ($signe) ? ' +(' . $cond . ')' : ' ' . $cond; - } - - - public function newCatalogueForAll() { - return new AllNoticesCatalogue(); - } - - - public function getCataloguesForCombo() { - if (!$catalogues = Class_Catalogue::findTopCatalogues()) - return []; - - $liste = ['']; - foreach($catalogues as $catalogue) { - $this->addCataloguePathAndChildrenTo($catalogue, $liste); - } - return $liste; - } - - - public function addCataloguePathAndChildrenTo($catalogue, &$liste) { - $liste[$catalogue->getId()] = implode(' > ', $catalogue->getPathParts()); - $sous_domaines = $catalogue->getSousDomaines(); - foreach($sous_domaines as $sous_domaine) - $this->addCataloguePathAndChildrenTo($sous_domaine, $liste); - } - - - public function findParentChildrenOf($model) { - if ($model->isNew()) - return array_filter(Class_Catalogue::findTopCatalogues(), - [$this, '_isParent']); - - $children = $model->getSousDomaines(); - return array_filter($children, [$this, '_isParent']); - } - - - protected function _isParent($model) { - return $model->hasSousDomaines(); - } -} - - - class Class_Catalogue extends Storm_Model_Abstract { use Trait_TreeNode, Trait_Translator, Trait_CustomFields, Trait_Facetable; @@ -710,7 +31,7 @@ class Class_Catalogue extends Storm_Model_Abstract { protected $_table_name = 'catalogue', $_table_primary = 'ID_CATALOGUE', - $_loader_class = 'CatalogueLoader', + $_loader_class = Class_Catalogue_Loader::class, $_default_attribute_values = ['parent_id' => null, 'libelle' => '', 'oai_spec' => '', @@ -737,21 +58,22 @@ class Class_Catalogue extends Storm_Model_Abstract { 'indexer' => 0, 'url_img' => '', 'custom_form_id' => null, - 'custom_form_values' => ''], + 'custom_form_values' => '', + 'library_id' => null], - $_belongs_to = ['domaine_parent' => ['model' => 'Class_Catalogue', - 'referenced_in' => 'parent_id'], - 'user' => ['model' => 'Class_Users', + $_belongs_to = ['domaine_parent' => ['model' => Class_Catalogue::class, + 'referenced_in' => 'parent_id'], + 'user' => ['model' => Class_Users::class, 'referenced_in' => 'id_user'], - 'custom_form' => ['model' => 'Class_SearchForm'] + 'custom_form' => ['model' => Class_SearchForm::class] ], - $_has_many = ['sous_domaines' => ['model' => 'Class_Catalogue', + $_has_many = ['sous_domaines' => ['model' => Class_Catalogue::class, 'role' => 'domaine_parent', 'dependents' => 'delete', 'order' => 'libelle'], - 'panier_notice_catalogues' => ['model' => 'Class_PanierNoticeCatalogue', + 'panier_notice_catalogues' => ['model' => Class_PanierNoticeCatalogue::class, 'dependents' => 'delete', 'role' => 'catalogue'], @@ -761,7 +83,6 @@ class Class_Catalogue extends Storm_Model_Abstract { $_until; - /** [[file:~/public_html/afi-opac3/library/Trait/TreeNode.php::trait%20Trait_TreeNode%20{][voir Trait_TreeNode]] */ public function getParent() { return $this->getDomaineParent(); } @@ -1266,6 +587,12 @@ class Class_Catalogue extends Storm_Model_Abstract { return true; } + if (Class_AdminVar::isModuleEnabled('ENABLE_DOMAINS_PER_LIBRARIES') + && $user->isRoleLibraryLimited() + && (!in_array($this->getOwnOrParentLibraryId(), [0, $user->getIdSite()]))) { + return false; + } + if ($user->hasRightToAccess(Class_UserGroup::RIGHT_USER_DOMAINES_TOTAL_ACCESS)) return true; @@ -1274,7 +601,6 @@ class Class_Catalogue extends Storm_Model_Abstract { return ($this->hasUser() && ($this->getUser()->getId() == $user->getId())); - } @@ -1284,9 +610,16 @@ class Class_Catalogue extends Storm_Model_Abstract { } + public function getCreatorLoginOrFullName() { + return $this->hasUser() + ? $this->getUser()->getLoginOrFullName() + : ''; + } + + public function copy() { $attributes = $this->getRawAttributes(); - $attributes['libelle'] = '** Nouveau Domaine **'; + $attributes['libelle'] = '** ' . $this->_('Nouveau Domaine') . ' **'; unset($attributes['id']); unset($attributes['id_catalogue']); unset($attributes['ID_CATALOGUE']); @@ -1295,68 +628,6 @@ class Class_Catalogue extends Storm_Model_Abstract { } - public function getDomainesJson($options = []) { - return $this->_jsonWith( - 'domaines_paniers', - function($domain) use ($options) { - return $domain->toDataForJson($options); - }); - } - - - protected function _jsonWith($id, $closure) { - $domaines = Class_Catalogue::getLoader()->findTopCatalogues(); - $data_domaines=[]; - foreach($domaines as $domaine) - $data_domaines [] = $closure($domaine); - - return $data = ['id' => $id, - 'label' => $this->_('Domaines'), - 'categories' => $data_domaines, - 'items' => [], - 'options' => ['ico' => URL_ADMIN_IMG.'picto/domaines_16.png', - 'multipleSelection' => false]]; - } - - - public function getDomainesJsonWithoutPaniers($options = []) { - return $this->_jsonWith( - 'domaines', - function($domain) use ($options) { - return $domain->toDataForJsonWithoutPaniers($options); - }); - - } - - - public function getBrowsableDomainsJson($domains = [], $options = []) { - $domains = $domains ? $domains : Class_Catalogue::getLoader()->findTopCatalogues(); - $browsable_domains = array_filter($domains, function($domain) {return $domain->hasSousDomaines();}); - - $data_domaines=[]; - foreach($browsable_domains as $domaine) { - $data_domaines [] = $domaine->getBrowsableDomainsJson($domaine->getSousDomaines(), $options); - } - - $leaf_domains = array_diff($domains, $browsable_domains); - $data_leaf_domains = []; - foreach($leaf_domains as $domain) { - $data_leaf_domains [] = ['id' => $domain->getId(), - 'label' => $domain->getLibelle(), - 'options' => ['ico' => URL_ADMIN_IMG.'picto/domaines_16.png', - 'multipleSelection' => false]]; - } - - - return ['id' => $this->getId() ? $this->getId() : 'domaines', - 'label' => $this->getLibelle() ? $this->getLibelle() : $this->_('Domaines'), - 'categories' => $data_domaines, - 'items' => $data_leaf_domains, - 'options' => ['ico' => URL_ADMIN_IMG.'picto/domaines_16.png', - 'multipleSelection' => false]]; - - } - public function hasNoSettings() { if ($this->isCustomDomainForm()) @@ -1513,6 +784,30 @@ class Class_Catalogue extends Storm_Model_Abstract { return $count; } + + + public function getLibrary() { + if ($parent = $this->getParent()) + return $parent->getLibrary(); + + return ($library = Class_Bib::find($this->getLibraryId())) + ? $library + : Class_Bib::getPortail(); + } + + + public function getLibraryLabel() { + return ($library = $this->getLibrary()) + ? $library->getLibelle() + : ''; + } + + + public function getOwnOrParentLibraryId() { + return ($library = $this->getLibrary()) + ? $library->getId() + : null; + } } @@ -1522,4 +817,4 @@ class AllNoticesCatalogue extends Class_Catalogue { public function isMatchingAllNotices() { return true; } -} \ No newline at end of file +} diff --git a/library/Class/Catalogue/Loader.php b/library/Class/Catalogue/Loader.php new file mode 100644 index 0000000000000000000000000000000000000000..9279c91613b8b4543e4b1cb16033dfde2e885de5 --- /dev/null +++ b/library/Class/Catalogue/Loader.php @@ -0,0 +1,711 @@ +<?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 Class_Catalogue_Loader extends Storm_Model_Loader { + use Trait_Translator, Trait_TimeSource; + + const DEFAULT_ITEMS_BY_PAGE = 100; + + protected $_indexable_cache; + + public function loadNoticesFor($catalogue, $itemsByPage = self::DEFAULT_ITEMS_BY_PAGE, $page = 1, $find_all_params = null) { + if (null == $catalogue) + return []; + + if ('' == ($where = $this->clausesFor($catalogue))) + return []; + + if (!is_array($find_all_params)) + $find_all_params = []; + + if (!isset($find_all_params['limitPage'])) + $find_all_params['limitPage'] = [$page, $itemsByPage]; + + $find_all_params['where'] = $where; + + return Class_Notice::findAllBy($find_all_params); + } + + + public function findAllCataloguesAIndexer() { + return array_filter(Class_Catalogue::findAllIndexable(), + function ($catalogue) + { + return '' != Class_Catalogue::clausesFor($catalogue); + }); + } + + + public function findAllIndexableNotEmpty() { + return array_filter(Class_Catalogue::findAllIndexable(), + function($catalog) + { + return !$catalog->isEmpty(); + }); + } + + + public function findAllIndexable() { + return $this->_indexable_cache + ? $this->_indexable_cache + : $this->_indexable_cache = Class_Catalogue::findAllBy(['indexer' => true, + 'order' => 'libelle']); + } + + + public function getDomainsForBreadcrumb($breadcrumb) { + $domains_ids = array_filter(explode(';', $breadcrumb)); + $domains = []; + foreach ($domains_ids as $domain_id) + $domains[] = Class_Catalogue::find($domain_id); + + return $domains; + } + + + public function getMultiOptionsFacets($ids) { + $domain_labels = ['' => $this->_('tous')]; + if (!$domains = Class_Catalogue::findAllBy(['id_catalogue' => $ids, + 'order' => 'libelle'])) + return $domain_labels; + + foreach($domains as $domain) + if ($th = Class_CodifThesaurus::findThesaurusForCatalogue($domain->getId())) + $domain_labels[$th->getFacetteIndex()]= $th->getLibelleFacette(); + + return $domain_labels; + } + + + public function updateAllThesaurusForCatalogueChildren($catalogue_id, $thesaurus_id) { + $catalogues = Class_Catalogue::findAllBy(['parent_id' => $catalogue_id]); + + foreach ($catalogues as $catalogue) { + Class_CodifThesaurus::deleteAllWithIdOrigineAndCode($catalogue->getId(), + Class_CodifThesaurus::fixedCodeOf('Domain')); + $new_thesaurus = $catalogue->getNewThesaurus(); + $new_thesaurus_id = Class_CodifThesaurus::findNextThesaurusChildId('catalogue', + $thesaurus_id); + $new_thesaurus->setIdThesaurus($new_thesaurus_id); + $new_thesaurus->save(); + + Class_Catalogue::getLoader() + ->updateAllThesaurusForCatalogueChildren($catalogue->getId(), $new_thesaurus_id); + } + } + + + public function countNoticesFor($catalogue) { + if (!$catalogue) + return 0; + + if ('' == ($where = $this->clausesFor($catalogue))) + return 0; + + return Class_Notice::countBy(['where' => $where]); + } + + + public function clausesFor($catalogue) { + if (!$catalogue) + return ''; + + $fromUntil = $this->fromUntilClauseFor($catalogue); + + if ($catalogue->isMatchingAllNotices()) + return $fromUntil ? $fromUntil : '1=1'; + + $conditions = array_filter(array_merge($this->_catalogueConditions($catalogue), + [$fromUntil])); + + return 0 < count($conditions) + ? implode(' and ', $conditions) + : ''; + } + + + protected function _localClausesFor($catalogue, $against='') { + $conditions = []; + + if ($facets = $this->facetsClauseFor($catalogue, $against)) + $conditions[] = $facets; + + if ($docType = $this->docTypeClauseFor($catalogue)) + $conditions[] = $docType; + + if ($year = $this->yearClauseFor($catalogue)) + $conditions[] = $year; + + if ($cote = $this->coteClauseFor($catalogue)) + $conditions[] = $cote; + + if ($new = $this->nouveauteClauseFor($catalogue)) + $conditions[] = $new; + + return $conditions; + } + + + protected function _noticesLinked($catalogue) { + if (!$catalogue || $catalogue->isCustomDomainForm()) + return ''; + + if (!Class_NoticeDomain::getClesNoticesForDomain($catalogue->getId())) + return ''; + + return (new Class_MoteurRecherche())->prepareFacetteDomainForOrConditions($catalogue->getId()); + } + + + /** + * @param $catalogue Class_Catalogue + * @return string + */ + public function facetsClauseFor($catalogue, $against = '') { + $against_ou = ''; + $facets = ['B' => $catalogue->getBibliotheque(), + 'S' => $catalogue->getSection(), + 'G' => $catalogue->getGenre(), + 'L' => $catalogue->getLangue(), + 'Y' => $catalogue->getAnnexe(), + 'E' => $catalogue->getEmplacement(), + 'H' => $catalogue->getThesaurusNovelty()]; + + foreach ($facets as $k => $v) + $against .= Class_Catalogue::getSelectionFacette($k, $v); + + $facets = ['A' => $catalogue->getAuteur(), + 'M' => $catalogue->getMatiere(), + 'D' => $catalogue->getDewey(), + 'P' => $catalogue->getPcdm4(), + 'H' => $catalogue->getThesaurus(), + 'Z' => $catalogue->getTags(), + 'F' => $catalogue->getInteret()]; + + foreach ($facets as $k => $v) + $against_ou .= Class_Catalogue::getSelectionFacette($k, + $v, + in_array($k, + ['M', 'D', 'P','H']), + false); + + if ('' != $against_ou) + $against .= ' +(' . $against_ou . ")"; + + if ('' == $against) + return ''; + + return "MATCH(facettes) AGAINST('".$against."' IN BOOLEAN MODE)"; + } + + + public function docTypeClauseFor($catalogue) { + if (!$docType = $catalogue->getTypeDoc()) + return ''; + + $parts = array_filter(explode(';', $docType)); + return (1 == count($parts)) ? + ('notices.type_doc=\'' . $parts[0]) . '\'' : + ('notices.type_doc IN (\'' . implode('\', \'', $parts) . '\')'); + } + + + public function yearClauseFor($catalogue) { + $clauses = []; + if ($start = $catalogue->getAnneeDebut()) + $clauses[] = "annee >= '" . $start . "'"; + + if($end = $catalogue->getAnneeFin()) + $clauses[] = "annee <= '" . $end . "'"; + + if (0 == count($clauses)) + return ''; + + return implode(' and ', $clauses); + } + + + public function coteClauseFor($catalogue) { + $clauses = []; + if ($start = $catalogue->getCoteDebut()) + $clauses[] = "cote >= '" . strtoupper($start) . "'"; + + if ($end = $catalogue->getCoteFin()) + $clauses[] = "cote <= '". strtoupper($end) . "'"; + + if (0 == count($clauses)) + return ''; + + return implode(' and ', $clauses); + } + + + public function nouveauteClauseFor($catalogue) { + /* Attention : la date de creation corresponds à la date de fin de nouveauté */ + if (1 != $catalogue->getNouveaute()) + return ''; + + return 'date_creation >= \'' . $this->getCurrentDate() . '\''; + } + + + public function fromUntilClauseFor($catalogue) { + $clauses = []; + if ($start = $catalogue->getFrom()) + $clauses[] = "created_at >= '" . $start . "'"; + + if($end = $catalogue->getUntil()) + $clauses[] = "created_at <= '" . $end . "'"; + + if (0 == count($clauses)) + return ''; + + $clauses[] = 'created_at is not null'; + + return implode(' and ', $clauses); + } + + + /** + * @return array [id => label] + */ + public function allByIdLabel() { + return $this->byIdLabel(Class_Catalogue::findAllBy(['order' => 'libelle'])); + } + + + /** + * @return array [id => label] + */ + public function byIdLabel($domains) { + $datas = []; + foreach($domains as $domain) + $datas[$domain->getId()] = $domain->getLibelle(); + return $datas; + } + + + /** + * @return array + */ + public function findTopCatalogues() { + return Class_Catalogue::findAllBy(['where' => 'parent_id is null', + 'order' => 'libelle']); + } + + + public function findTopCataloguesPerLibraryLabel() { + $domains = $this->findTopCatalogues(); + $libraries = []; + foreach($domains as $domain) { + if (!isset($libraries[$domain->getLibraryLabel()])) + $libraries[$domain->getLibraryLabel()] = []; + $libraries[$domain->getLibraryLabel()] []= $domain; + } + + ksort($libraries, SORT_STRING); + return $libraries; + } + + + /** + * @return Class_Catalogue + */ + public function getRoot() { + return Class_Catalogue::newInstanceWithId(null, + ['sous_domaines' => Class_Catalogue::findTopCatalogues()]); + } + + + /** + * @param $treeNode Trait_TreeNode + * @return Class_Catalogue + */ + public function findWithSamePathAs($treeNode) { + return Class_Catalogue::getRoot()->findByPath($treeNode->getPath()); + } + + + public function fetchAllNoticesByPreferences($preferences) { + $requetes = $this->getRequetes($preferences); + if (!array_key_exists("req_liste", $requetes)) + return []; + + $nb_par_page = (array_key_exists('aleatoire', $preferences) + && array_key_exists('nb_analyse', $preferences) + && $preferences['aleatoire'] + && $preferences['nb_analyse']) + ? $preferences['nb_analyse'] + : $preferences['nb_notices']; + + return Class_Notice::findAllByRequeteRecherche($requetes['req_ids'], + $nb_par_page, + 1); + } + + + public function getRequetes($preferences, $fields = null) { + if (isset($preferences['id_panier']) + && (0 !== (int)$preferences['id_panier'])) + return $this->getRequetesPanier($preferences); + + $catalogue = isset($preferences['id_catalogue']) + ? Class_Catalogue::find($preferences['id_catalogue']) + : null; + + if ($catalogue && $catalogue->isEmpty()) + return []; + + $against = $this->selectionFacettesForCatalogueRequestByPreferences($preferences); + + $conditions = $this->_catalogueConditions($catalogue, $against); + + if (isset($preferences['only_img']) && ($preferences['only_img'] == Class_Catalogue::ONLY_IMG) + && (($catalogue && Class_Catalogue::hasFilters($preferences['id_catalogue'])) + || !$catalogue)) + $conditions[] = "url_vignette > '' and url_vignette != '" . Class_WebService_Vignette::NO_DATA . "' "; + + if (isset($preferences['only_img']) && ($preferences['only_img'] == Class_Catalogue::WITHOUT_IMG)) + $conditions[] = "url_vignette=''"; + + $join = (isset($preferences['avec_avis']) && ($preferences['avec_avis'] == 1)) + ? ' INNER JOIN notices_avis ON notices.clef_oeuvre=notices_avis.clef_oeuvre ' + : ''; + + $order_by = $this->orderByForCatalogueRequestByPreferences($preferences); + $limite = $this->limitForCatalogueRequestByPreferences($preferences); + + $sql = 'select %s from notices' . + $join . + (new Class_MoteurRecherche)->getConditionsForRequest(array_filter($conditions), + $this->_noticesLinked($catalogue)); + + return ['req_liste' => sprintf($sql, $fields ? implode(',', $fields) : '*') + . $order_by . $limite, + 'req_comptage' => sprintf($sql, 'count(*)'), + 'req_facettes' => sprintf($sql, 'notices.id_notice, notices.type_doc, facettes') + . $limite, + 'req_ids' => sprintf($sql, 'notices.id_notice') . $order_by . $limite]; + } + + + protected function _catalogueConditions($catalogue, $against='') { + if (!$catalogue) + return $against + ? ["MATCH(facettes) AGAINST('" . $against . "' IN BOOLEAN MODE)"] + : []; + + if (!$catalogue->isCustomDomainForm()) + return $this->_localClausesFor($catalogue, $against); + + $search_engine = (new Class_MoteurRecherche) + ->visitSearchSettings((new Class_CriteresRecherche) + ->clearProfil() + ->setParam('id_catalogue', $catalogue->getId())); + + return !is_array($search_engine->buildWherePartQuery()) + ? $search_engine->getConditions() + : []; + } + + + public function selectionFacettesForCatalogueRequestByPreferences($preferences) { + if (!isset($preferences['facettes'])) + return ''; + + $against = ''; + $facettes = explode(';', $preferences['facettes']); + foreach($facettes as $facette) { + $facette = trim($facette); + $against .= $this->getSelectionFacette(substr($facette, 0, 1), substr($facette, 1)); + } + + return $against; + } + + + public function orderByForCatalogueRequestByPreferences($preferences) { + if( ! array_key_exists('tri', $preferences)) + return ' order by alpha_titre '; + + $tri = $preferences['tri']; + + if ($tri == '0' || $tri == 'alpha_titre') + return ' order by alpha_titre '; + + if ( $tri == '1' || $tri == 'date_creation desc') + return ' order by date_creation DESC '; + + if ($tri == '2' || $tri == 'nb_visu desc') + return ' order by nb_visu DESC '; + + if ($tri == '3' || $tri == 'annee desc') + return ' order by annee DESC '; + + return $tri instanceof Class_MoteurRecherche_OrderCriteria + ? sprintf(' order by %s ', $tri->getOrder()) + : ''; + } + + + public function limitForCatalogueRequestByPreferences($preferences, $max_limited = false) { + if ( $max_limited ) + return ' LIMIT 5000'; + + if ( isset($preferences["aleatoire"]) + && 1 == (int) $preferences["aleatoire"]) + return sprintf(' LIMIT 0,%d', (int) $preferences["nb_analyse"]); + + if (isset($preferences['nb_notices']) && $preferences["nb_notices"]) + return sprintf(' LIMIT 0,%d', (int) $preferences["nb_notices"]); + + return ' LIMIT 5000'; //LL: j'ai rajouté une limite max car explosion mémoire sur des catalogues mal définis + } + + + public function getRequetesPanier($preferences) { + $panier = null; + if (array_key_exists('id_user', $preferences)) + $panier = Class_PanierNotice::findFirstBy(['id_user' => $preferences['id_user'], + 'id' => $preferences['id_panier']]); + if (!$panier) + $panier = Class_PanierNotice::find($preferences['id_panier']); + + if (!$panier) + return ['nombre' => 0]; + + $cles_notices = $panier->getClesNotices(); + if (empty($cles_notices)) + return ['nombre' => 0]; + + $keys = []; + foreach($cles_notices as $notice) { + if (!trim($notice)) + continue; + $keys[] = "'" . $notice . "'"; + } + $in_sql = implode(',', $keys); + + $limite = ($preferences['aleatoire'] == 1) + ? $preferences['nb_analyse'] : $preferences['nb_notices']; + $limite = ($limite) ? 'LIMIT 0,' . $limite : ''; + + $order_by = ''; + + if (!isset($preferences["tri"])) + $preferences["tri"] = 0; + + if ($preferences["tri"]==0) + $order_by=" order by alpha_titre "; + if ($preferences["tri"]==1) + $order_by=" order by date_creation DESC "; + if ($preferences["tri"]==2) + $order_by=" order by nb_visu DESC "; + if($preferences['tri'] > 2) + $order_by = ' order by FIELD(notices.clef_alpha, ' . $in_sql . ') '; + + $condition = (array_isset("only_img", $preferences) + && $preferences["only_img"] == 1) + ? " and url_vignette > '' and url_vignette != '" . Class_WebService_Vignette::NO_DATA . "'" + : ''; + $condition .= ' and type=1 '; + + $join = (array_isset("avec_avis", $preferences) && $preferences["avec_avis"] == 1) + ? ' INNER JOIN notices_avis ON notices.clef_oeuvre=notices_avis.clef_oeuvre ' + : ''; + + $sql = 'select %s from notices ' + . $join + . 'where notices.clef_alpha in(' . $in_sql . ')' + . $condition; + + return ['req_liste' => sprintf($sql, '*') . $order_by . $limite, + 'req_comptage' => sprintf($sql, 'count(*)'), + 'req_facettes' => sprintf($sql, 'id_notice, notices.type_doc, facettes') . $limite, + 'req_ids' => sprintf($sql, 'notices.id_notice') . $order_by . $limite]; + } + + + public function getNoticesFromCacheByPreferences($preferences) { + $callback = function() use ($preferences) { + return Class_Catalogue::getLoader()->fetchAllNoticesByPreferences($preferences); + }; + + return (array_key_exists('aleatoire', $preferences) + && $preferences['aleatoire']) + ? $callback() + : (new Storm_Cache())->memoize([$preferences, __CLASS__, __FUNCTION__], $callback); + } + + + public function getNoticesByPreferences($preferences) { + if (isset($preferences['id_catalogue']) + && ($catalogue = Class_Catalogue::getLoader()->find($preferences['id_catalogue']))) { + $preferences['catalogue_cache_key'] = serialize($catalogue->toArray()); + } + + $notices = $this->getNoticesFromCacheByPreferences($preferences); + + if ((int)$preferences["aleatoire"] !== 1) + return $notices; + + shuffle($notices); + return array_slice ($notices, 0, $preferences["nb_notices"]); + } + + + public function hasFilters($id) { + if(!$catalogue = Class_Catalogue::find($id)) + return false; + + return !$catalogue->hasNoSettings(); + } + + + public function hasFiltersOrLinkedRecords($id) { + return ($catalog = Class_Catalogue::find((int)$id)) + ? !$catalog->isEmpty() + : false; + } + + + public function saveThesaurus($catalogue) { + if ($thesaurus = Class_CodifThesaurus::findThesaurusForCatalogue($catalogue->getId())) { + $catalogue->deleteThesaurusInFacette($thesaurus->getIdThesaurus()); + $catalogue->updateThesaurusLabel($thesaurus); + } else if (!$thesaurus = $catalogue->saveThesauriParents()) + return; + + if($catalogue->hasDomaineParent()){ + $parent=$catalogue->getParent(); + $thesaurus_parent = $parent->saveThesauriParents(); + if (!$thesaurus_parent) + return null; + $new_thesaurus_id=Class_CodifThesaurus::findNextThesaurusChildId( + 'catalogue', + $thesaurus_parent->getIdThesaurus()); + } + else if (strlen($thesaurus->getIdThesaurus())>8) { + $new_thesaurus_id=Class_CodifThesaurus::findNextRacineCatalogue();} + else + return $thesaurus; + + if ($thesaurus->getId() && ($new_thesaurus_id != $thesaurus->getIdThesaurus())) { + $thesaurus->setIdThesaurus($new_thesaurus_id); + $thesaurus->setLibelle($catalogue->getLibelle()); + $thesaurus->save(); + + Class_Catalogue::updateAllThesaurusForCatalogueChildren($catalogue->getId(),$new_thesaurus_id); + return $thesaurus; + } + + $thesaurus->setIdThesaurus($new_thesaurus_id); + $thesaurus->setLibelle($catalogue->getLibelle()); + $thesaurus->save(); + + return $thesaurus; + } + + + public function getIds($domains) { + return (new Storm_Model_Collection($domains)) + ->collect('id') + ->getArrayCopy(); + } + + + public function hasViewableDomain() { + return 0 < count(Class_Catalogue::findAllIndexableNotEmpty()); + } + + + public function getSelectionFacette($type, $valeurs, $descendants = false, $signe = true) { + if ( !$valeurs = array_filter(explode(';', $valeurs))) + return false; + + $cond = ''; + foreach ($valeurs as $valeur) { + if (!$valeur) + continue; + + if (!$descendants) { + $cond .= $type . $valeur . ' '; + continue; + } + + if ('M' != $type) { + $cond .= $type . $valeur . '* '; + continue; + } + + if (!$matiere = Class_Matiere::find($valeur)) + continue; + + if ('' != ($sous_vedettes = trim($matiere->getSousVedettes()))) + $valeur .= str_replace(' ', ' M', ' ' . $sous_vedettes); + $cond .= $type . $valeur . ' '; + } + + $cond = trim($cond); + + return ($signe) ? ' +(' . $cond . ')' : ' ' . $cond; + } + + + public function newCatalogueForAll() { + return new AllNoticesCatalogue(); + } + + + public function getCataloguesForCombo() { + if (!$catalogues = Class_Catalogue::findTopCatalogues()) + return []; + + $liste = ['']; + foreach($catalogues as $catalogue) { + $this->addCataloguePathAndChildrenTo($catalogue, $liste); + } + return $liste; + } + + + public function addCataloguePathAndChildrenTo($catalogue, &$liste) { + $liste[$catalogue->getId()] = implode(' > ', $catalogue->getPathParts()); + $sous_domaines = $catalogue->getSousDomaines(); + foreach($sous_domaines as $sous_domaine) + $this->addCataloguePathAndChildrenTo($sous_domaine, $liste); + } + + + public function findParentChildrenOf($model) { + if ($model->isNew()) + return array_filter(Class_Catalogue::findTopCatalogues(), + [$this, '_isParent']); + + $children = $model->getSousDomaines(); + return array_filter($children, [$this, '_isParent']); + } + + + protected function _isParent($model) { + return $model->hasSousDomaines(); + } +} diff --git a/library/Class/Catalogue/TreeSelectJson.php b/library/Class/Catalogue/TreeSelectJson.php new file mode 100644 index 0000000000000000000000000000000000000000..70f0453af582886c98a611c6cb0246d6b6441be5 --- /dev/null +++ b/library/Class/Catalogue/TreeSelectJson.php @@ -0,0 +1,130 @@ +<?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 Class_Catalogue_TreeSelectJson { + use Trait_Translator; + + public function render($options = []) { + return $this->_jsonWith( + 'domaines_paniers', + function($domain) use ($options) { + return $domain->toDataForJson($options); + }); + } + + + public function renderWithoutCheckbox() { + return $this->render(['removeCheckbox' => true]); + } + + + public function renderWithoutCarts() { + return [$this->_jsonWith( + 'domaines', + function($domain) { + return $domain->toDataForJsonWithoutPaniers(); + })]; + } + + + protected function _jsonWith($id, $closure) { + $root = ['id' => $id, + 'label' => $this->_('Domaines'), + 'categories' => [], + 'items' => [], + 'options' => ['ico' => URL_ADMIN_IMG.'picto/domaines_16.png', + 'multipleSelection' => false]]; + + if (!Class_AdminVar::isModuleEnabled('ENABLE_DOMAINS_PER_LIBRARIES')) { + $root['categories'] = array_map($closure, Class_Catalogue::findTopCatalogues()); + return $root; + } + + + foreach(Class_Catalogue::findTopCataloguesPerLibraryLabel() as $library_label => $domains) { + $root['categories'][]= ['id' => $library_label, + 'label' => $library_label, + 'categories' => array_map($closure, $domains), + 'items' => [], + 'options' => ['ico' => URL_ADMIN_IMG.'picto/bibliotheques_16.png', + 'removeCheckbox' => true]]; + } + + return $root; + } + + + public function renderBrowsableDomains() { + $top_domains = Class_AdminVar::isModuleEnabled('ENABLE_DOMAINS_PER_LIBRARIES') + ? Class_Catalogue::findTopCataloguesPerLibraryLabel() + : [$this->_('Domaines') => Class_Catalogue::findTopCatalogues()]; + + $datas = []; + + foreach($top_domains as $library_label => $domains) { + $datas[] = ['id' => $library_label, + 'label' => $library_label, + 'categories' => array_map( + function($domain) { + return $this->getBrowsableDomainsJson($domain); + }, + $domains), + 'items' => [], + 'options' => []]; + } + + return $datas; + } + + + public function getBrowsableDomainsJson($parent, $options = []) { + $domains = $parent->getSousDomaines(); + $browsable_domains = array_filter($domains, + function($domain) { + return $domain->hasSousDomaines(); + }); + + $data_domaines=[]; + foreach($browsable_domains as $parent_domain) { + $data_domaines [] = $this->getBrowsableDomainsJson($parent_domain, + $options); + } + + $leaf_domains = array_diff($domains, $browsable_domains); + $data_leaf_domains = []; + foreach($leaf_domains as $domain) { + $data_leaf_domains [] = ['id' => $domain->getId(), + 'label' => $domain->getLibelle(), + 'options' => ['ico' => URL_ADMIN_IMG.'picto/domaines_16.png', + 'multipleSelection' => false]]; + } + + + return ['id' => $parent->getId(), + 'label' => $parent->getLibelle(), + 'categories' => $data_domaines, + 'items' => $data_leaf_domains, + 'options' => ['ico' => URL_ADMIN_IMG.'picto/domaines_16.png', + 'multipleSelection' => false]]; + + } +} diff --git a/library/ZendAfi/Controller/Action/Helper/ListViewMode/Abstract.php b/library/ZendAfi/Controller/Action/Helper/ListViewMode/Abstract.php index 6516269fb36e5ca26e4b18c887b332286f2599df..096b9d298a62710f04354c55436f077bb35ba347 100644 --- a/library/ZendAfi/Controller/Action/Helper/ListViewMode/Abstract.php +++ b/library/ZendAfi/Controller/Action/Helper/ListViewMode/Abstract.php @@ -55,7 +55,7 @@ abstract class ZendAfi_Controller_Action_Helper_ListViewMode_Abstract public function getCategoriesDescription() { - if ($this->isSearching()) + if ($this->isSearching() && !$this->isSearchDisplayCategories()) return; $model_class = $this->getModel() ? get_class($this->getModel()) : ''; @@ -82,7 +82,9 @@ abstract class ZendAfi_Controller_Action_Helper_ListViewMode_Abstract if ($this->isCountEnabled()) $label .= ' (' . ($count = $this->countItemsInTreeFrom($model)) . ')'; - return $this->_view->tagAnchor($url, $label, ['data-count' => $count]); + $html = $this->_view->tagAnchor($url, $label, ['data-count' => $count]); + return $this->_decorateModelWithSearchBreadcrumb($html, + $model); } @@ -108,13 +110,20 @@ abstract class ZendAfi_Controller_Action_Helper_ListViewMode_Abstract protected function _renderItem($model, $attrib) { $value = $model->callGetterByAttributeName($attrib); + return $this->_decorateModelWithSearchBreadcrumb($value, $model); + } + + + protected function _decorateModelWithSearchBreadcrumb($value, $model) { if (!$this->isSearching()) return $value; - return $this->_view->tag('span', $value) - . $this->_view->tag('p', - $this->_getBreadcrumbHtmlFor($this->getBreadcrumbFor($this->getCategoryFor($model))), - ['style' => 'font-size:0.9em;']); + return + $this->_view->tag('span', $value) + . + $this->_view->tag('p', + $this->_getBreadcrumbHtmlFor($this->getBreadcrumbFor($this->getCategoryFor($model))), + ['style' => 'font-size:0.9em;']); } @@ -141,6 +150,11 @@ abstract class ZendAfi_Controller_Action_Helper_ListViewMode_Abstract } + public function isSearchDisplayCategories() { + return false; + } + + protected function enabledPager() { return false; } @@ -284,7 +298,7 @@ abstract class ZendAfi_Controller_Action_Helper_ListViewMode_Abstract * @return array */ protected function getBreadcrumbFor($model, $breadcrumb=[], $start_key='') { - if (!$model) + if (!$model || $model->isNew()) return $breadcrumb; if (!$this->_shouldCheckParent($start_key, $model) @@ -471,4 +485,4 @@ abstract class ZendAfi_Controller_Action_Helper_ListViewMode_Abstract protected function _sqlQuote($value) { return Zend_Registry::get('sql')->quote($value); } -} \ No newline at end of file +} diff --git a/library/ZendAfi/Controller/Action/Helper/ListViewMode/Catalogue.php b/library/ZendAfi/Controller/Action/Helper/ListViewMode/Catalogue.php new file mode 100644 index 0000000000000000000000000000000000000000..4cdf761a21bb586c7f09e6d5f6a41d184801ffca --- /dev/null +++ b/library/ZendAfi/Controller/Action/Helper/ListViewMode/Catalogue.php @@ -0,0 +1,199 @@ +<?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 ZendAfi_Controller_Action_Helper_ListViewMode_Catalogue + extends ZendAfi_Controller_Action_Helper_ListViewMode_Abstract { + + + public function init() { + parent::init(); + $this->_form_settings->setPlaceHolder($this->_('libellé du domaine')); + } + + + public function ListViewMode_Catalogue($params) { + $this->_params = $params; + return $this; + } + + + public function direct($params) { + return $this->ListViewMode_Catalogue($params); + } + + + public function isSearchDisplayCategories() { + return true; + } + + + protected function _describeDomainList($description, $title, $render_callback) { + $description + ->setSorterServer() + ->addColumn($title, + ['attribute' => 'libelle', + 'sortable' => false, + 'callback' => $render_callback]) + ->addColumn($this->_('Créateur'), ['attribute' => 'creator_login_or_full_name', + 'sortable' => false]) + ->addColumn($this->_('Description'), ['attribute' => 'description', + 'sortable' => false]); + + return $description; + } + + + protected function _describeCategoriesIn($description) { + return $this->_describeDomainList($description, + $this->_('Liste des domaines avec sous-domaines'), + function ($model, $attrib) + { + return $this->_renderCategory($model, $attrib); + }); + } + + + protected function countItemsFor($domain) { + return $domain ? $domain->numberOfSousDomaines() : 0; + } + + + + protected function _describeItemsIn($description) { + return $this->_describeDomainList($description, + $this->_('Liste des domaines'), + function ($model, $attrib) + { + return $this->_renderItem($model, $attrib); + }); + } + + + protected function _allDomains() { + return $this->isSearching() + ? $this->_searchDomains() + : $this->_browseDomains(); + + return $domains; + } + + + protected function _searchDomains() { + $params = ['order' => 'libelle', + 'libelle like' => '%' . $this->getSearchValue() . '%']; + + $domains = new Storm_Model_Collection(Class_Catalogue::findAllBy($params)); + $library_id = $this->getParam('id_bib', null); + + return $domains->select( + function($domain) use ($library_id) + { + return $domain->getOwnOrParentLibraryId() == $library_id; + }); + } + + + protected function _browseDomains() { + $parent_id = $this->getModel()->getId(); + $params = ['order' => 'libelle', + 'parent_id' => $parent_id]; + + if ((null === $parent_id) && array_key_exists('id_bib', $this->_params)) + $params['library_id'] = $this->_params['id_bib'] + ? $this->_params['id_bib'] + : null; + return new Storm_Model_Collection(Class_Catalogue::findAllBy($params)); + } + + + public function getItems() { + return $this->_allDomains() + ->reject('hasSousDomaines') + ->getArrayCopy(); + } + + + public function getCategories() { + return $this->_allDomains() + ->select('hasSousDomaines') + ->getArrayCopy(); + } + + + public function getDefaultModel() { + return ($this->getModel() && !$this->getModel()->isNew()) + ? $this->getModel() + : $this->_getLibrary(); + } + + + + public function getBaseUrl() { + return ['module' => 'admin', + 'controller' => 'catalogue', + 'action' => 'index', + 'id_bib' => (array_key_exists('id_bib', $this->_params) + ? $this->_params['id_bib'] + : null)]; + } + + + public function getBreadcrumb() { + $breadcrumb = [ + ['url' => ['module' => 'admin', + 'controller' => 'catalogue', + 'action' => 'index'], + 'label' => $this->_('Racine'), + 'options' => [] + ], + + ['url' => array_merge($this->getBaseUrl(), + ['id_bib' => $this->_getLibraryId()]), + 'label' => $this->_getLibraryLabel(), + 'options' => []] + ]; + + return array_merge($breadcrumb, + $this->getBreadcrumbFor($this->getModel())); + } + + + protected function _getLibrary() { + return $this->getParam('bib', Class_Bib::getPortail()); + } + + + protected function _getLibraryLabel() { + return $this->_getLibrary()->getLibelle(); + } + + + protected function _getLibraryId() { + return $this->_getLibrary()->getId(); + } + + + public function isSearchEnabled() { + return true; + } + +} diff --git a/library/ZendAfi/Controller/Action/Helper/ListViewMode/Library.php b/library/ZendAfi/Controller/Action/Helper/ListViewMode/Library.php index 373cd3f43f6de3d1a8372decb941ecf9bd0964b8..8a04d0e83ef5a99c347e602b908f84358ae6985c 100644 --- a/library/ZendAfi/Controller/Action/Helper/ListViewMode/Library.php +++ b/library/ZendAfi/Controller/Action/Helper/ListViewMode/Library.php @@ -21,7 +21,6 @@ class ZendAfi_Controller_Action_Helper_ListViewMode_Library extends ZendAfi_Controller_Action_Helper_ListViewMode_Abstract { - public function ListViewMode_Library($params) { return parent::_initParams($params); } @@ -32,6 +31,11 @@ class ZendAfi_Controller_Action_Helper_ListViewMode_Library extends ZendAfi_Cont } + public function getItemsDescription() { + return null; + } + + protected function _describeCategoriesIn($description) { return $description ->addColumn($this->_('Localisation'), ['attribute' => 'libelle', @@ -49,7 +53,7 @@ class ZendAfi_Controller_Action_Helper_ListViewMode_Library extends ZendAfi_Cont public function getBaseUrl() { return ['module' => 'admin', - 'controller' => 'cms']; + 'controller' => $this->getRequest()->getControllerName()]; } @@ -76,4 +80,4 @@ class ZendAfi_Controller_Action_Helper_ListViewMode_Library extends ZendAfi_Cont public function getStrategyLabel() { return 'bib'; } -} \ No newline at end of file +} diff --git a/library/ZendAfi/Controller/Plugin/Manager/Catalogue.php b/library/ZendAfi/Controller/Plugin/Manager/Catalogue.php new file mode 100644 index 0000000000000000000000000000000000000000..bb5fd8aa23fc924697b26f4bfd6c2396e871aeb5 --- /dev/null +++ b/library/ZendAfi/Controller/Plugin/Manager/Catalogue.php @@ -0,0 +1,103 @@ +<?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 ZendAfi_Controller_Plugin_Manager_Catalogue extends ZendAfi_Controller_Plugin_Manager_Manager { + public function getActions($model) { + if (!$model) + return []; + + if (Class_Catalogue::class == get_class($model)) + return $this->_getDomainActions($model); + + if (Class_Bib::class == get_class($model)) + return $this->_getLibraryActions($model); + + return []; + } + + + protected function _getLibraryActions($library) { + $actions = [ + ['url' => '/admin/catalogue/add/id_bib/' . $library->getId(), + 'icon' => 'add_page', + 'label' => $this->_('Ajouter un domaine à la bibliothèque %s', + $library->getLibelle())] + ]; + + return $actions; + } + + + protected function _getDomainActions($domain) { + $editable = $domain->canBeDeletedOrModifyByUser(Class_Users::getIdentity()); + $actions = [['url' => '/admin/catalogue/tester/id_catalogue/%s', + 'icon' => 'test', + 'label' => $this->_('Indexer les notices du domaine %s', + $domain->getLibelle())]]; + + if ($editable) + $actions []= ['url' => '/admin/catalogue/edit/id_catalogue/%s', + 'icon' => 'edit', + 'label' => $this->_('Modifier le domaine %s', + $domain->getLibelle())]; + + $actions []= ['url' => '/admin/catalogue/duplicate/id_catalogue/%s', + 'icon' => 'copy', + 'label' => $this->_('Dupliquer le domaine %s', + $domain->getLibelle())]; + + if ($editable) { + $actions []= ['url' => '/admin/catalogue/add/id_catalogue/%s', + 'icon' => 'add_page', + 'label' => $this->_('Ajouter un sous-domaine au domaine %s', + $domain->getLibelle())]; + $actions []= ['url' => '/admin/catalogue/paniers/id_catalogue/%s', + 'icon' => 'basket', + 'label' => $this->_('Paniers du domaine %s', + $domain->getLibelle())]; + + $actions []= ['url' => '/admin/catalogue/delete/id_catalogue/%s', + 'icon' => 'delete', + 'label' => $this->_('Supprimer le domaine %s', + $domain->getLibelle())]; + } + + $actions []= ['url' => ['module' => 'opac', + 'controller' => 'recherche', + 'action' => 'simple', + 'id_catalogue' => $domain->getId()], + 'icon' => 'view', + 'label' => $this->_('Visualiser le domaine "%s" dans un nouvel onglet', + $domain->getLibelle()), + 'anchorOptions' => ['target' => '_blank']]; + + $actions []= ['url' => null, + 'icon' => 'permalink', + 'label' => $this->_('Voir le lien permanent du domaine "%s"', + $domain->getLibelle()), + 'anchorOptions' => ['data-url' => '/recherche/simple/id_catalogue/' . $domain->getId(), + 'data-helptext' => $this->_('Copiez le lien suivant'), + 'title' => $this->_('Lien permanent'), + 'onclick' => 'popupPermalink(this);return false']]; + return $actions; + } +} diff --git a/library/ZendAfi/View/Helper/Admin/ComboCatalogue.php b/library/ZendAfi/View/Helper/Admin/ComboCatalogue.php index 65005e9844db6b77a9a68549a9e54af183a6b215..1dc9330a96842848a9ba4395b60bab6c81305a00 100644 --- a/library/ZendAfi/View/Helper/Admin/ComboCatalogue.php +++ b/library/ZendAfi/View/Helper/Admin/ComboCatalogue.php @@ -34,7 +34,23 @@ class ZendAfi_View_Helper_Admin_ComboCatalogue extends ZendAfi_View_Helper_BaseH public function _getAllCatalogues() { - return $this->_getCatalogs(Class_Catalogue::findTopCatalogues()); + return Class_AdminVar::isModuleEnabled('ENABLE_DOMAINS_PER_LIBRARIES') + ? $this->_getCatalogsPerLibrary(Class_Catalogue::findTopCataloguesPerLibraryLabel()) + : $this->_getCatalogs(Class_Catalogue::findTopCatalogues()); + } + + + protected function _getCatalogsPerLibrary($libraries) { + $html = ''; + foreach($libraries as $label => $domains) { + $html .= ($visible_domains = $this->_getCatalogs($domains)) + ? $this->_tag('optgroup', + $visible_domains, + ['label' => $label]) + : ''; + } + + return $html; } @@ -67,4 +83,4 @@ class ZendAfi_View_Helper_Admin_ComboCatalogue extends ZendAfi_View_Helper_BaseH } } -?> \ No newline at end of file +?> diff --git a/library/ZendAfi/View/Helper/PartialCycle.php b/library/ZendAfi/View/Helper/PartialCycle.php index c9bb48c3a55ec2e6d14a244e21c329fa5dab1fa8..de1bacea483c4c4bf3a3be98513cb5c970b854e9 100644 --- a/library/ZendAfi/View/Helper/PartialCycle.php +++ b/library/ZendAfi/View/Helper/PartialCycle.php @@ -21,7 +21,7 @@ class ZendAfi_View_Helper_PartialCycle extends Zend_View_Helper_Partial { - public function partialCycle($name, $key, $models, $class_cycle) { + public function partialCycle($name, $key, $models, $class_cycle, $extra_variables=[]) { $content = ''; end($class_cycle); @@ -29,11 +29,13 @@ class ZendAfi_View_Helper_PartialCycle extends Zend_View_Helper_Partial if (false == $item_class = next($class_cycle)) $item_class = reset($class_cycle); - $content .= $this->partial($name, [$key => $item, - 'item_class' => $item_class]); + $content .= $this->partial($name, + array_merge([$key => $item, + 'item_class' => $item_class], + $extra_variables)); } return $content; } } -?> \ No newline at end of file +?> diff --git a/library/storm b/library/storm index 3e243b7852935d6613857b2b07a083ce234077bf..27ef84c18e7820736efebc43c0817fe7d32b9a52 160000 --- a/library/storm +++ b/library/storm @@ -1 +1 @@ -Subproject commit 3e243b7852935d6613857b2b07a083ce234077bf +Subproject commit 27ef84c18e7820736efebc43c0817fe7d32b9a52 diff --git a/tests/application/modules/admin/controllers/CatalogueControllerTest.php b/tests/application/modules/admin/controllers/CatalogueControllerTest.php index 33e01eccd1707a540476cc045d07ec1e714b4b3a..5d186dd62844b833a7469f242a4cd015c7673f25 100644 --- a/tests/application/modules/admin/controllers/CatalogueControllerTest.php +++ b/tests/application/modules/admin/controllers/CatalogueControllerTest.php @@ -366,7 +366,7 @@ class CatalogueControllerWithModoPortailTotalAccessIndexTest extends AdminCatalo /** @test */ public function pageShouldContainsPermalinkForCataloguePolitique() { - $this->assertXPath('//img[contains(@class, "permalink")][contains(@data-url, "recherche/simple/id_catalogue/200")]'); + $this->assertXPath('//a[@title="Lien permanent"][contains(@data-url, "recherche/simple/id_catalogue/200")]'); } diff --git a/tests/db/UpgradeDBTest.php b/tests/db/UpgradeDBTest.php index 47a8a956cd2eddcdf0896a6236eba5c1b2ff252a..ca6651fcbe644f4773e79f28a32c5ecd68c7b6be 100644 --- a/tests/db/UpgradeDBTest.php +++ b/tests/db/UpgradeDBTest.php @@ -3919,7 +3919,7 @@ class UpgradeDB_412_Test extends UpgradeDBTestCase { class UpgradeDB_413_Test extends UpgradeDBTestCase { public function prepare() { - $this->silentQuery("alter table alter drop column interet"); + $this->silentQuery("alter table album drop column interet"); } @@ -3982,4 +3982,26 @@ class UpgradeDB_415_Test extends UpgradeDBTestCase { public function tableCmsArticleTimingShouldHaveField($field, $type) { $this->assertFieldType('cms_article_timings', $field, $type); } -} \ No newline at end of file +} + + + + +class UpgradeDB_416_Test extends UpgradeDBTestCase { + public function prepare() { + $this->silentQuery("alter table catalogue drop column library_id"); + } + + + /** @test */ + public function catalogueShouldHaveColumnLibraryIdInt() { + $this->assertFieldType('catalogue', 'library_id', 'int(11) unsigned'); + } + + + /** @test */ + public function catalogueShouldHaveIndexOnLibraryId() { + $this->assertIndex('catalogue', 'library_id'); + } + +} diff --git a/tests/library/Class/CatalogueTest.php b/tests/library/Class/CatalogueTest.php index 7f927b4b09fac53fb04a19a76adae3b60467315c..fb320bcefbf014eb6d649efb7fc8b7d10a901c38 100644 --- a/tests/library/Class/CatalogueTest.php +++ b/tests/library/Class/CatalogueTest.php @@ -454,7 +454,7 @@ class CatalogueTestGetPagedNotices extends ModelTestCase { protected function _expectNoticeFindAllBy($where, $limit = []) { if (0 == count($limit)) - $limit = [1, CatalogueLoader::DEFAULT_ITEMS_BY_PAGE]; + $limit = [1, Class_Catalogue_Loader::DEFAULT_ITEMS_BY_PAGE]; $this->_noticeWrapper ->whenCalled('findAllBy') @@ -544,7 +544,7 @@ class CatalogueTestOAISpec extends ModelTestCase { class CatalogueGetNoticesByPreferencesNotRandomTest extends ModelTestCase { - protected $_cache_key = '5be5b882d00792a8bcf7299b575bb175'; + protected $_cache_key = '25d43b0fa219225c79624883f5f7fd99'; public function setUp() { parent::setUp(); diff --git a/tests/scenarios/DomainsPerLibraries/DomainsPerLibrariesTest.php b/tests/scenarios/DomainsPerLibraries/DomainsPerLibrariesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ee7867af5157c08b624ed07e64f9c1a8a0f5a657 --- /dev/null +++ b/tests/scenarios/DomainsPerLibraries/DomainsPerLibrariesTest.php @@ -0,0 +1,870 @@ +<?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 + */ + +abstract class DomainsPerLibrariesTestCase extends Admin_AbstractControllerTestCase { + protected + $_storm_default_to_volatile = true; + + + public function setUp() { + parent::setUp(); + Class_AdminVar::set('ENABLE_DOMAINS_PER_LIBRARIES', 1); + + $this->fixture(Class_Catalogue::class, + ['id' => 1, + 'libelle' => 'All places', + 'library_id' => null, + 'parent_id' => null]); + + $this->fixture(Class_Catalogue::class, + ['id' => 2, + 'libelle' => 'All characters', + 'library_id' => null, + 'parent_id' => null]); + + $this->fixture(Class_Catalogue::class, + ['id' => 3, + 'libelle' => 'Wookiees', + 'library_id' => null, + 'parent_id' => 2]); + + $this->fixture(Class_Bib::class, + ['id' => 1, + 'libelle' => 'Alderaan']); + + $this->fixture(Class_Users::class, + ['id' => 8, + 'login' => 'alderaan_admin', + 'password' => 'secret', + 'bib' => Class_Bib::find(1)]) + ->beAdminBib(); + + $this->fixture(Class_Catalogue::class, + ['id' => 4, + 'libelle' => 'Alderaan places', + 'library_id' => 1, + 'id_user' => 8, + 'description' => 'Cool places on Alderaan', + 'parent_id' => null]); + + $this->fixture(Class_Catalogue::class, + ['id' => 5, + 'libelle' => 'Alderaan towns', + 'library_id' => null, + 'parent_id' => 4]); + + $this->fixture(Class_Catalogue::class, + ['id' => 6, + 'libelle' => 'Alderaan characters', + 'library_id' => null, + 'parent_id' => 4]); + + $this->fixture(Class_Bib::class, + ['id' => 2, + 'libelle' => 'Tatooine']); + + $this->fixture(Class_Catalogue::class, + ['id' => 7, + 'libelle' => 'Tatooine characters', + 'library_id' => 2, + 'parent_id' => null]); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerIndexTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/catalogue/index'); + } + + + /** @test */ + public function pageShouldContainsTableWithFolderLinkToPortal() { + $this->assertXPathContentContains('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/0")]', + 'Portail'); + } + + + /** @test */ + public function pageShouldContainsTableWithFolderLinkToAlderaan() { + $this->assertXPathContentContains('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/1")]', + 'Alderaan'); + } + + + /** @test */ + public function breadShouldContainsPortalActionToAddNewDomain() { + $this->assertXPathContentContains('//table//td//a/@href', + '/admin/catalogue/add/id_bib/0'); + + } + + + /** @test */ + public function pageShouldNotContainsItemsTable() { + $this->assertNotXPath('//table[contains(@id, "items_")]'); + } +} + + + +class DomainsPerLibrariesCatalogueControllerAsAdminBibWithoutGroupIndexTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + ZendAfi_Auth::getInstance() + ->logUser(Class_Users::findFirstBy(['login' => 'alderaan_admin'])); + + $this->dispatch('/admin/catalogue/index'); + + } + + + /** @test */ + public function pageShouldContainsTableWithFolderLinkToPortal() { + $this->assertXPathContentContains('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/0")]', + 'Portail'); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerAsAdminAlderaanWithAccessIndexTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + $domain_admins = $this->fixture(Class_UserGroup::class, + ['id' => 4, + 'libelle' => 'Domains admins', + 'rights' => [Class_UserGroup::RIGHT_USER_DOMAINES_TOTAL_ACCESS]]); + + ZendAfi_Auth::getInstance() + ->logUser(Class_Users::findFirstBy(['login' => 'alderaan_admin']) + ->addUserGroup($domain_admins)); + + $this->dispatch('/admin/catalogue/index'); + } + + + /** @test */ + public function leftAdminMenuShouldHaveEntryToAdminCatalogue() { + $this->assertXPathContentContains('//ul[@class="menuAdmin"]//a/@href', + 'admin/catalogue'); + } + + + /** @test */ + public function pageShouldContainsTableWithFolderLinkToPortal() { + $this->assertXPathContentContains('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/0")]', + 'Portail'); + } + + + /** @test */ + public function pageShouldContainsTableWithFolderLinkToAlderaan() { + $this->assertXPathContentContains('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/1")]', + 'Alderaan'); + } + + + /** @test */ + public function pageShouldNotContainsTableWithFolderLinkToTatooine() { + $this->assertNotXPath('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/2")]'); + } +} + + + + +abstract class DomainsPerLibrariesCatalogueControllerAsAdminTatooineWithAccessSuppressionLimitTestCase extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + $this->fixture(Class_UserGroup::class, + ['id' => 4, + 'libelle' => 'Domains admins', + 'rights' => [Class_UserGroup::RIGHT_USER_DOMAINES_SUPPRESSION_LIMIT]]); + + $admin = $this->fixture(Class_Users::class, + ['id' => 9, + 'login' => 'tatooine', + 'password' => 'secret', + 'bib' => Class_Bib::find(2), + 'user_groups' => [Class_UserGroup::find(4)]]) + ->beAdminBib(); + ZendAfi_Auth::getInstance()->logUser($admin); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerAsAdminTatooineWithAccessCreatorIndexTest extends DomainsPerLibrariesCatalogueControllerAsAdminTatooineWithAccessSuppressionLimitTestCase { + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/catalogue/index'); + } + + + /** @test */ + public function pageShouldContainsTableWithFolderLinkToPortal() { + $this->assertXPathContentContains('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/0")]', + 'Portail'); + } + + + /** @test */ + public function pageShouldContainsTableWithFolderLinkToTatooine() { + $this->assertXPathContentContains('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/2")]', + 'Tatooine'); + } + + + /** @test */ + public function pageShouldNotContainsTableWithFolderLinkToAlderaan() { + $this->assertNotXPath('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/1")]'); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerAsAdminTatooineWithAccessCreatorAddTest extends DomainsPerLibrariesCatalogueControllerAsAdminTatooineWithAccessSuppressionLimitTestCase { + public function setUp() { + parent::setUp(); + + Class_Catalogue::findFirstBy(['libelle' => 'Tatooine characters']) + ->setUser(Class_Users::getIdentity()) + ->save(); + + Class_Catalogue::findFirstBy(['libelle' => 'All characters']) + ->setUser(Class_Users::getIdentity()) + ->save(); + + $this->dispatch('/admin/catalogue/add/id_bib/2'); + } + + + /** @test */ + public function selectParentIdShouldHaveOptGroupTatooine() { + $this->assertXPath('//select[@id="parent_id"]/optgroup[@label="Tatooine"]'); + } + + + /** @test */ + public function selectParentIdShouldHaveOptGroupPortail() { + $this->assertXPath('//select[@id="parent_id"]/optgroup[@label="Portail"]'); + } + + + /** @test */ + public function selectParentIdShouldNotHaveOptGroupAlderaan() { + $this->assertNotXPath('//select[@id="parent_id"]/optgroup[@label="Alderaan"]'); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerViewLibraryPortalTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/catalogue/index/id_bib/0'); + } + + + /** @test */ + public function tableForCategoriesTitleShouldBeListeDesDomainesAvecSousDomaines() { + $this->assertXPath('//table[@id="categories_Class_Catalogue"]/thead//th[text()="Liste des domaines avec sous-domaines"]'); + } + + + /** @test */ + public function tableForItemsTitleShouldBeListeDesDomaines() { + $this->assertXPath('//table[@id="items_Class_Catalogue"]/thead//th[text()="Liste des domaines"]'); + } + + + /** @test */ + public function pageShouldContainsLinkToSubDomainForAllCharacters() { + $this->assertXPathContentContains('//table[@id="categories_Class_Catalogue"]//tr//td//a[text()="All characters (1)"]/@href', + '/admin/catalogue/index/id_bib/0/id/2'); + } + + + /** @test */ + public function pageShouldContainsDomainAllPlaces() { + $this->assertXPathContentContains('//table[@id="items_Class_Catalogue"]//tr//td', 'All places'); + } + + + /** @test */ + public function pageShouldNotContainsDomainAlderaan() { + $this->assertNotXPathContentContains('//table//tr//td', 'Alderaan'); + } + + + /** @test */ + public function allPlacesDomainShouldHaveEditAction() { + $this->assertXPathContentContains('//table[@id="items_Class_Catalogue"]//div[@class="actions"]/a/@href', + '/admin/catalogue/edit/id_catalogue/1'); + } + + + /** @test */ + public function breadCrumbShouldHaveTwoEntries() { + $this->assertXPathCount('//div[@class="breadcrumb"]/a', 2); + } + + + /** @test */ + public function breadCrumbShouldContainsPortalActionToAddNewDomain() { + $this->assertXPathContentContains('//div[@class="breadcrumb"]/div[@class="actions"]/a/@href', + '/admin/catalogue/add/id_bib/0'); + + } + + + /** @test */ + public function pageShouldContainsSearchInput() { + $this->assertXPath('//input[@id="list_title_search"][@placeholder="libellé du domaine"]'); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerViewAllCharactersDomainTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/catalogue/index/id/2/id_bib/0'); + } + + + /** @test */ + public function pageShouldContainsDomainWookies() { + $this->assertXPathContentContains('//table[@id="items_Class_Catalogue"]//tr//td', 'Wookiees'); + } + + + /** @test */ + public function pageShouldIndicatesEmptyCategories() { + $this->assertXPathContentContains('//table[@id="categories_Class_Catalogue"]//tr//td', 'Aucune donnée'); + } + + + /** @test */ + public function breadCrumbShouldContainsLinkToRoot() { + $this->assertXPathContentContains('//div[@class="breadcrumb"]/a[text()="Racine"]/@href', + '/admin/catalogue'); + + } + + + /** @test */ + public function breadCrumbShouldContainsLinkToLibraryPortal() { + $this->assertXPathContentContains('//div[@class="breadcrumb"]/a[text()="Portail"]/@href', + '/admin/catalogue/index/id_bib/0'); + + } + + + /** @test */ + public function breadCrumbShouldContainsLinkToDomainAllCharacters() { + $this->assertXPathContentContains('//div[@class="breadcrumb"]/a[text()="All characters"]/@href', + '/admin/catalogue/index/id_bib/0/id/2'); + + } + + + /** @test */ + public function breadCrumbShouldContainsAllCharactersDomainActions() { + $this->assertXPathContentContains('//div[@class="breadcrumb"]/div[@class="actions"]/a/@href', + '/admin/catalogue/tester/id_catalogue/2'); + + } +} + + + + +class DomainsPerLibrariesCatalogueControllerViewAlderaanTownsDomainTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + + $this->fixture(Class_Catalogue::class, + ['id' => 10, + 'libelle' => 'Crevasse City', + 'library_id' => null, + 'parent_id' => 5]); + + $this->dispatch('/admin/catalogue/index/id/5/id_bib/1'); + } + + + /** @test */ + public function breadCrumbShouldContainsLinkToLibraryAlderaan() { + $this->assertXPathContentContains('//div[@class="breadcrumb"]/a[text()="Alderaan"]/@href', + '/admin/catalogue/index/id_bib/1'); + + } + + + /** @test */ + public function paseShouldDisplayDomainCrevasseCity() { + $this->assertXPath('//table[@id="items_Class_Catalogue"]//td[text()="Crevasse City"]', + $this->_response->getBody()); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerPostDispatchInLibraryTatooineTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + $this->postDispatch('/admin/catalogue/add/id_bib/2', + ['libelle' => 'Tatooine Places', + 'parent_id' => '']); + } + + + /** @test */ + public function domainWithLabelTatooinePlacesSevenShouldHaveBeenSaved() { + Class_Catalogue::clearCache(); + $domain = Class_Catalogue::findFirstBy(['libelle' => 'Tatooine Places']); + $this->assertNotNull($domain); + return $domain; + } + + + /** + * @depends domainWithLabelTatooinePlacesSevenShouldHaveBeenSaved + * @test + */ + public function tatooinePlacesShouldHaveLibraryIdTwo($domain) { + $this->assertEquals(2, $domain->getLibraryId()); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerPostDispatchInLibraryPortalTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + $this->postDispatch('/admin/catalogue/add/id_bib/0', + ['libelle' => 'Galaxies', + 'parent_id' => '']); + } + + + /** @test */ + public function domainWithIdSixShouldHaveBeenSaved() { + Class_Catalogue::clearCache(); + $this->assertNotNull(Class_Catalogue::find(6)); + } + + + /** @test */ + public function galaxiesShouldHaveLibraryIdNull() { + $this->assertNull(Class_Catalogue::find(6)->getLibraryId()); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerViewLibraryAlderaanTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/catalogue/index/id_bib/1'); + } + + + /** @test */ + public function breadCrumbShouldContainsAlderaanActionToAddNewDomain() { + $this->assertXPathContentContains('//div[@class="breadcrumb"]/div[@class="actions"]/a/@href', + '/admin/catalogue/add/id_bib/1'); + + } + + + /** @test */ + public function pageShouldContainsDomainAlderaanPlaces() { + $this->assertXPathContentContains('//table[@id="categories_Class_Catalogue"]//tr[1]//td', 'Alderaan places'); + } + + + /** @test */ + public function alderanPlacesShouldDisplayDescriptionCoolPlaces() { + $this->assertXPathContentContains('//table[@id="categories_Class_Catalogue"]//tr[1]//td', 'Cool places on Alderaan'); + } + + + /** @test */ + public function alderanPlacesShouldDisplayCreatorAlderaanAdmin() { + $this->assertXPathContentContains('//table[@id="categories_Class_Catalogue"]//tr[1]//td', 'alderaan_admin'); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerEditDomainTest extends DomainsPerLibrariesTestCase { + /** @test */ + public function formDataBackurlForWookiesShouldBeIndexIdTwo() { + $this->dispatch('/admin/catalogue/edit/id_catalogue/3'); + $this->assertXPathContentContains('//form[contains(@action, "/admin/catalogue/edit/id_catalogue/3")]/@data-backurl', + '/admin/catalogue/index/id/2'); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerEditDomainAllPlacesTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/catalogue/edit/id_catalogue/1'); + } + + + /** @test */ + public function formDataBackurlShouldBeIndexIdBibZero() { + $this->assertXPathContentContains('//form[contains(@action, "/admin/catalogue/edit/id_catalogue/1")]/@data-backurl', + '/admin/catalogue/index/id_bib/0'); + } + + + /** @test */ + public function selectParentIdShouldHaveOptGroupAlderaanWithAlderaanPlaces() { + $this->assertXPath('//select[@id="parent_id"]/optgroup[@label="Alderaan"]/option[@value="4"][text()="Alderaan places"]'); + } + + + /** @test */ + public function selectParentIdShouldHaveOptGroupPortailWithAllCharacters() { + $this->assertXPath('//select[@id="parent_id"]/optgroup[@label="Portail"]/option[@value="2"][text()="All characters"]'); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerPostEditDomainAlderaanPlacesTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + $this->postDispatch('/admin/catalogue/edit/id_catalogue/4', + ['libelle' => 'Alderaan Places', + 'parent_id' => '']); + } + + + /** @test */ + public function domainLibraryIdShouldStillBeOneForAlderaan() { + $this->assertEquals(1, Class_Catalogue::find(4)->getLibraryId()); + } + + + /** @test */ + public function responsShouldBeARedirect() { + $this->assertRedirectTo('/admin/catalogue/edit/id_catalogue/4'); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerPostSearchTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + $_SERVER['HTTP_REFERER'] = 'http://monbokeh.org/admin/catalogue/index'; + $this->postDispatch('/admin/catalogue/index/order/libelle/title_search/old_search', + ['title_search' => 'places']); + } + + + /** @test */ + public function responseShouldRedirectToTitleSearchPlaces() { + $this->assertRedirectTo('/admin/catalogue/index/title_search/places/order/libelle'); + } + + + public function tearDown() { + unset($_SERVER['HTTP_REFERER']); + parent::tearDown(); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerSearchAllTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/catalogue/index/title_search/all'); + } + + + /** @test */ + public function pageShouldContainsAllPlaces() { + $this->assertXPathContentContains('//table//tr//td', 'All places'); + } + + + /** @test */ + public function pageShouldContainsAllCharactersAsCategory() { + $this->assertXPathContentContains('//table[@id="categories_Class_Catalogue"]//tr//td', + 'All characters'); + } + + + /** @test */ + public function pageShouldNotContainsWookies() { + $this->assertNotXPathContentContains('//table//tr//td', 'Wookies'); + } +} + + + + +class DomainsPerLibrariesCatalogueControllerSearchCharactersInLibraryAlderaanTest extends DomainsPerLibrariesTestCase { + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/catalogue/index/title_search/charac/id_bib/1'); + } + + + /** @test */ + public function pageShouldContainsAlderaanCharactersAsItem() { + $this->assertXPathContentContains('//table[@id="items_Class_Catalogue"]//tr//td', 'Alderaan characters'); + } + + + /** @test */ + public function pageShouldContainsAlderaanCharactersShouldHaveLinkToAlderaanPlaces() { + $this->assertXPathContentContains('//table//tr//td/span[text()="Alderaan characters"]/following-sibling::p/a[text()="Alderaan places"]/@href', '/admin/catalogue/index/id_bib/1/id/4'); + } + + + /** @test */ + public function pageShouldNotContainsAllCharacters() { + $this->assertNotXPathContentContains('//table//tr//td', 'All characters'); + } + + + /** @test */ + public function breadCrumbShouldContainsLinkToLibraryAlderaan() { + $this->assertXPathContentContains('//div[@class="breadcrumb"]/a[text()="Alderaan"]/@href', + '/admin/catalogue/index/id_bib/1'); + + } +} + + + + +class DomainsPerLibrariesCatalogueControllerJsonRendersTest extends DomainsPerLibrariesTestCase { + /** @test */ + public function domainesPaniersShouldContainsDomainsPerLibraries() { + $this->onLoaderOfModel(Class_PanierNotice::class) + ->whenCalled('findAllBelongsToAdmin') + ->answers([]); + + $this->dispatch('admin/catalogue/domaines-paniers-json', true); + $datas = json_decode($this->_response->getBody(), true); + + $item_options = ['ico' => Class_Url::baseUrl() . '/public/admin/images/picto/domaines_16.png']; + + $library_options = ['ico' => Class_Url::baseUrl() . '/public/admin/images/picto/bibliotheques_16.png', + 'removeCheckbox' => true]; + $this->assertEquals([['id' => 'panier_for_user', + 'label' => 'Mes paniers', + 'categories' => [], + 'items' => [], + 'options' => ['multipleSelection' => false]], + + ['id' => 'domaines_paniers', + 'label' => 'Domaines', + 'categories' => [['id' => 'Alderaan', + 'label' => 'Alderaan', + 'categories' => [[ + 'id' => 6, + 'label' => 'Alderaan characters', + 'categories' => [], + 'items' => [], + 'options' => $item_options], + + ['id' => 4, + 'label' => 'Alderaan places', + 'categories' => [[ + 'id' => 6, + 'label' => 'Alderaan characters', + 'categories' => [], + 'items' => [], + 'options' => $item_options], + + ['id' => 5, + 'label' => 'Alderaan towns', + 'categories' => [], + 'items' => [], + 'options' => $item_options]], + 'items' => [], + 'options' => $item_options], + + ['id' => 5, + 'label' => 'Alderaan towns', + 'categories' => [], + 'items' => [], + 'options' => $item_options]], + 'items' => [], + 'options' => $library_options], + + ['id' => 'Portail', + 'label' => 'Portail', + 'categories' => [['id' => 2, + 'label' => 'All characters', + 'categories' => [[ + 'id' => 3, + 'label' => 'Wookiees', + 'categories' => [], + 'items' => [], + 'options' => $item_options]], + 'items' => [], + 'options' => $item_options], + + ['id' => 1, + 'label' => 'All places', + 'categories' => [], + 'items' => [], + 'options' => $item_options], + + ['id' => 3, + 'label' => 'Wookiees', + 'categories' => [], + 'items' => [], + 'options' => $item_options]], + 'items' => [], + 'options' => $library_options], + + ['id' => 'Tatooine', + 'label' => 'Tatooine', + 'categories' => [[ + 'id' => 7, + 'label' => 'Tatooine characters', + 'categories' => [], + 'items' => [], + 'options' => $item_options]], + 'items' => [], + 'options' => $library_options]], + 'items' => [], + 'options' => ['ico' => Class_Url::baseUrl() . '/public/admin/images/picto/domaines_16.png', + 'multipleSelection' => false]], + + ['id' => 'paniers_by_users', + 'label' => 'Autres paniers', + 'categories' => [], + 'items' => [], + 'options' => ['multipleSelection' => false]] + ], + $datas); + } + + + /** @test */ + public function browsableDomainsShouldContainsDomainsPerLibraries() { + $this->dispatch('admin/catalogue/browsable-domains', true); + + $datas = json_decode($this->_response->getBody(), true); + $item_options = ['ico' => (Class_Url::baseUrl() . '/public/admin/images/picto/domaines_16.png'), + 'multipleSelection' => false]; + + $this->assertEquals([['id' => 'Alderaan', + 'label' => 'Alderaan', + 'categories' => [['id' => 6, + 'label' => 'Alderaan characters', + 'categories' => [], + 'items' => [], + 'options' => $item_options], + + ['id' => 4, + 'label' => 'Alderaan places', + 'categories' => [], + 'items' => [['id' => 6, + 'label' => 'Alderaan characters', + 'options' => $item_options], + + ['id' => 5, + 'label' => 'Alderaan towns', + 'options' => $item_options]], + 'options' => $item_options], + + ['id' => 5, + 'label' => 'Alderaan towns', + 'categories' => [], + 'items' => [], + 'options' => $item_options]], + 'items' => [], + 'options' => []], + + + ['id' => 'Portail', + 'label' => 'Portail', + 'categories' => [['id' => 2, + 'label' => 'All characters', + 'categories' => [], + 'items' => [['id' => 3, + 'label' => 'Wookiees', + 'options' => $item_options]], + 'options' => $item_options], + + ['id' => 1, + 'label' => 'All places', + 'categories' => [], + 'items' => [], + 'options' => $item_options], + + ['id' => 3, + 'label' => 'Wookiees', + 'categories' => [], + 'items' => [], + 'options' => $item_options]], + 'items' => [], + 'options' => []], + + + + ['id' => 'Tatooine', + 'label' => 'Tatooine', + 'categories' => [[ + 'id' => 7, + 'label' => 'Tatooine characters', + 'categories' => [], + 'items' => [], + 'options' => $item_options]], + 'items' => [], + 'options' => []] + ], + $datas); + } +} diff --git a/tests/scenarios/Journal/JournalTest.php b/tests/scenarios/Journal/JournalTest.php index c357b3cd42c35233bf7db3bc3da2c844c5b97d06..c85b08b8cae53ef993e6fd8ef92c0af9494ad963 100644 --- a/tests/scenarios/Journal/JournalTest.php +++ b/tests/scenarios/Journal/JournalTest.php @@ -428,7 +428,7 @@ class JournalCatalogueEditTest extends JournalTestCase { /** @test */ public function journalDetailsShouldContainsNewValue() { - $this->assertEquals('{"parent_id":null,"libelle":"Coups de coeur","oai_spec":"","description":"les coups de coeur de l\'equipe","bibliotheque":"","section":"","genre":"","langue":"","annexe":"","emplacement":"","auteur":"","matiere":"","dewey":"","pcdm4":"","thesaurus":"","tags":"","interet":"","type_doc":1,"annee_debut":"","annee_fin":"","cote_debut":"","cote_fin":"","nouveaute":"","indexer":0,"url_img":"","custom_form_id":null,"custom_form_values":"","id":1,"id_catalogue":1}', + $this->assertEquals('{"parent_id":null,"libelle":"Coups de coeur","oai_spec":"","description":"les coups de coeur de l\'equipe","bibliotheque":"","section":"","genre":"","langue":"","annexe":"","emplacement":"","auteur":"","matiere":"","dewey":"","pcdm4":"","thesaurus":"","tags":"","interet":"","type_doc":1,"annee_debut":"","annee_fin":"","cote_debut":"","cote_fin":"","nouveaute":"","indexer":0,"url_img":"","custom_form_id":null,"custom_form_values":"","library_id":null,"id":1,"id_catalogue":1}', Class_JournalDetail::findFirstBy(['type' => 'new_value'])->getValue()); }