diff --git a/application/modules/admin/controllers/ThesauriController.php b/application/modules/admin/controllers/ThesauriController.php new file mode 100644 index 0000000000000000000000000000000000000000..c9ae9edb79aa5e909020a63b0fff4482779de934 --- /dev/null +++ b/application/modules/admin/controllers/ThesauriController.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Admin_ThesauriController extends ZendAfi_Controller_Action { + public function getPlugins() { + return ['ZendAfi_Controller_Plugin_ResourceDefinition_Thesauri', + 'ZendAfi_Controller_Plugin_Manager_Thesauri']; + } + + + public function indexAction() { + parent::indexAction(); + + if($this->_request->isPost()) + return $this->_redirectToRefererWithNewParams(['title_search' => $this->_getPost()['title_search'], + 'page' => $this->_getParam('page', 1), + 'order' => $this->_getParam('order', 'libelle')]); + + + $thesauri = $this->_getParam('parent_id') + ? Class_CodifThesaurus::find($this->_getParam('parent_id')) + : Class_CodifThesaurus::root(); + + $this->view->list = $this->_helper + ->thesauriListViewMode(['model' => $thesauri, + 'order' => $this->_getParam('order'), + 'page' => $this->_getParam('page', 0), + 'search_value' => $this->_getParam('title_search', '')]); + + return $this->renderScript('admin/listViewMode.phtml'); + } +} \ No newline at end of file diff --git a/library/Class/CodifThesaurus.php b/library/Class/CodifThesaurus.php index 2b77afde53a2af2298baf405343458f83f1de327..10830d8297c65bfa8c1e8ca5509d59dd686f8299 100644 --- a/library/Class/CodifThesaurus.php +++ b/library/Class/CodifThesaurus.php @@ -131,6 +131,13 @@ class CodifThesaurusLoader extends Storm_Model_Loader { } + public function countChildrenOf($id_thesaurus) { + return Class_CodifThesaurus::countBy(['where' => 'id_thesaurus like "'.$id_thesaurus.'%" and LENGTH(id_thesaurus)>'.strlen($id_thesaurus) + ]); + + } + + public function findRootOfId($id, $code, $label) { if ($codif = Class_CodifThesaurus::findFirstBy(['id_thesaurus' => $id])) return $codif; @@ -425,6 +432,11 @@ class CodifThesaurusLoader extends Storm_Model_Loader { return array_unique($params); } + + + public function root() { + return Class_CodifThesaurus::newInstance(); + } } @@ -444,7 +456,8 @@ class Class_CodifThesaurus extends Storm_Model_Abstract { protected $_loader_class = 'CodifThesaurusLoader'; protected $_table_name = 'codif_thesaurus'; protected $_table_primary = 'id'; - protected $_default_attribute_values = ['libelle_facette' => '', + protected $_default_attribute_values = ['libelle' => '', + 'libelle_facette' => '', 'id_thesaurus' =>null, 'id_origine' => null, 'rules' => null, @@ -502,7 +515,9 @@ class Class_CodifThesaurus extends Storm_Model_Abstract { public function getRulesLabel() { - return json_decode($this->getRules())->label; + return ($json = $this->getRules()) + ? json_decode($json)->label + : ''; } @@ -570,4 +585,34 @@ class Class_CodifThesaurus extends Storm_Model_Abstract { public function getChildren() { return $this->getLoader()->findChildrenOf($this); } + + + public function getParentChildren() { + return array_filter($this->getChildren(), + function ($children) + { + return ($children->hasChildren()); + }); + } + + + public function getChildrenItems() { + return array_filter($this->getChildren(), + function ($children) + { + return (!$children->hasChildren()); + }); + } + + public function getParent() { + return $this->getLoader()->findParent($this->getIdThesaurus()); + } + + public function getTitre() { + return $this->getLibelleFacette(); + } + + public function numberOfChildrens() { + return $this->getLoader()->countChildrenOf($this->getIdThesaurus()); + } } \ No newline at end of file diff --git a/library/ZendAfi/Controller/Action/Helper/AbstractListViewMode.php b/library/ZendAfi/Controller/Action/Helper/AbstractListViewMode.php index 218b36c5205685bfda4f8dbefae7883b6a65720a..42f44d399afe38a4d21a04086dfd5ac76dcd30d8 100644 --- a/library/ZendAfi/Controller/Action/Helper/AbstractListViewMode.php +++ b/library/ZendAfi/Controller/Action/Helper/AbstractListViewMode.php @@ -49,7 +49,17 @@ abstract class ZendAfi_Controller_Action_Helper_AbstractListViewMode extends Zen }], $this->getItemsId(), $this->getItemsGroupBy(), - $this->isSearching() ? [$this->getItemsLabelAttrib() => $callback] : []); + $this->isSearching() ? [$this->getItemsLabelAttrib() => $callback] : [], $this->enabledPager(), $this->enabledSorter()); + } + + + protected function enabledPager() { + return false; + } + + + protected function enabledSorter() { + return true; } @@ -321,6 +331,16 @@ abstract class ZendAfi_Controller_Action_Helper_AbstractListViewMode extends Zen } + public function getCategoriesCols() { + return ['']; + } + + + public function getItemsCols($view) { + return ['']; + } + + protected function _getSearchForm($view) { return (new ZendAfi_Form()) ->setAction($view->url(array_filter($this->getSearchUrl()), null, true)) diff --git a/library/ZendAfi/Controller/Action/Helper/ThesauriListViewMode.php b/library/ZendAfi/Controller/Action/Helper/ThesauriListViewMode.php new file mode 100644 index 0000000000000000000000000000000000000000..7e19b20191b5dd45be84e42d8eb3fb9816d1ac7d --- /dev/null +++ b/library/ZendAfi/Controller/Action/Helper/ThesauriListViewMode.php @@ -0,0 +1,184 @@ +<?php +/** + * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class ZendAfi_Controller_Action_Helper_ThesauriListViewMode extends ZendAfi_Controller_Action_Helper_AbstractListViewMode { + + public function thesauriListViewMode($params) { + $this->_params = $params; + return $this; + } + + + public function direct($params) { + return $this->thesauriListViewMode($params); + } + + protected function enabledSorter() { + return false; + } + + public function getBaseUrl() { + return ['module' => 'admin', + 'controller' => 'thesauri']; + } + + + public function getParamKey() { + return 'parent_id'; + } + + + public function getBreadcrumb() { + $breadcrumb = [['url' => ['module' => 'admin', + 'controller' => 'thesauri', + 'action' => 'index'], + 'label' => $this->_('Racine'), + 'options' => []]]; + + if($this->getModel()->isNew()) + return $breadcrumb; + + return array_merge($breadcrumb, + $this->getBreadcrumbFor($this->getModel())); + } + + + public function getCategories() { + $model = $this->getModel(); + + if($model->isNew()) + return Class_CodifThesaurus::getIndices('root',true); + + return $model->getParentChildren(); + } + + + public function getItems() { + $model = $this->getModel(); + if ($this->isSearching()) + return Class_CodifThesaurus::findAllBy($this->getItemsParams()); + if($model->isNew()) + return []; + + $where = sprintf('id_thesaurus like "%s%%" and LENGTH(id_thesaurus) = %s', + $model->getIdThesaurus(), strlen($model->getIdThesaurus()) + 4); + + return Class_CodifThesaurus::findAllBy(['where' => $where, + 'limitPage' => [$this->getPage(), + $this->_items_by_page], + 'order' => $this->getParam('order','libelle')]); + + } + + + public function countItemsFor($model) { + return count($model->getChildrenItems()); + } + + + public function countItemsInTreeFrom($model) { + if ($model->isNew()) + return 0; + return $model->numberOfChildrens(); + + } + + + public function getItemsCols($view) { + $order = $this->getOrder(); + $anchor_wrapper = function($key, $label) use ($view, $order) { + xdebug_break(); + $order_param = $key; + if((0 === strpos($order, $key)) && (false === strpos($order, 'desc'))) + $order_param .= ' desc'; + + $data_order = (false === strpos($order, $key)) + ? '' + : str_replace(' ', '_', 'order_' . $order_param); + + $url = ['order' => $order_param, + 'page' => null]; + + return $view->tagAnchor($url, $label, ['data-order' => $data_order]); + }; + + $cols = [$anchor_wrapper('libelle', $this->_('Thesaurus')), + $anchor_wrapper('libelle_facette', $this->_('Libellé facette')), + $anchor_wrapper('code', $this->_('Code')), + $anchor_wrapper('id_thesaurus', $this->_('ID Thesaurus')), + $anchor_wrapper('rules_label', $this->_('Règle'))]; + + xdebug_break(); + return $cols; + } + + + public function getCategoriesCols() { + return [$this->_('Thesaurus'), + $this->_('Libellé facette'), + $this->_('Code'), + $this->_('ID Thesaurus'), + $this->_('Règle')]; + } + + + public function getItemsAttribs() { + return $this->getCategoriesAttribs(); + } + + + public function getCategoriesAttribs() { + return ['libelle', + 'libelle_facette', + 'code', + 'id_thesaurus', + 'rules_label']; + } + + public function getSearchParams() { + $columns = ['libelle', + 'libelle_facette', + 'code', + 'id_thesaurus', + 'rules' + ]; + $where = []; + $search_param = Zend_Db_Table::getDefaultAdapter()->quote('%' . $this->getSearch() . '%'); + foreach ($columns as $col) { + $where [] = '('.$col.' like '.$search_param.')'; + } + return ['where' => implode(' or ',$where), + 'order' => $this->getOrder()]; + } + + + public function getCountSearchResult() { + $params = $this->getItemsParams(); + unset($params['limitPage']); + return Class_CodifThesaurus::countBy($params); + } + + + public function getOrder() { + return $this->getParam('order', 'libelle'); + } +} \ No newline at end of file diff --git a/library/ZendAfi/Controller/Plugin/Manager/Thesauri.php b/library/ZendAfi/Controller/Plugin/Manager/Thesauri.php new file mode 100644 index 0000000000000000000000000000000000000000..7468ea6ac06e924c12da1c833ed394bd8c3e02fe --- /dev/null +++ b/library/ZendAfi/Controller/Plugin/Manager/Thesauri.php @@ -0,0 +1,37 @@ +<?php +/** + * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class ZendAfi_Controller_Plugin_Manager_Thesauri extends ZendAfi_Controller_Plugin_Manager_Manager { + + + public function getActions() { + return [ + ['url' => ['module' => 'admin', + 'controller' => 'thesauri', + 'action' => 'edit', + 'id' => '%s'], + 'icon' => 'edit', + 'label' => $this->_('Modifier le thesaurus')], +]; + } + +} diff --git a/library/ZendAfi/Controller/Plugin/ResourceDefinition/Thesauri.php b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Thesauri.php new file mode 100644 index 0000000000000000000000000000000000000000..a64c14863f3c453629bdaf03f8aaf165a7a33969 --- /dev/null +++ b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Thesauri.php @@ -0,0 +1,37 @@ +<?php +/** + * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class ZendAfi_Controller_Plugin_ResourceDefinition_Thesauri extends ZendAfi_Controller_Plugin_ResourceDefinition_Abstract { + public function getDefinitions() { + return + ['model' => ['class' => 'Class_CodifThesaurus', + 'name' => 'thesauri', + 'order' => 'libelle'], + + 'messages' => ['successful_save' => $this->_('Thesaurus "%s" sauvegardé')], + + 'actions' => ['index' => ['title' => $this->_('Parcourir les Thesaurus')], + 'edit' => ['title' => $this->_("Modifier un thesaurus")]], + + 'form_class_name' => 'ZendAfi_Form_Admin_Thesauri']; + } +} \ No newline at end of file diff --git a/library/ZendAfi/View/Helper/Admin/ContentNav.php b/library/ZendAfi/View/Helper/Admin/ContentNav.php index 477decff9a4c159185cddf8d4da85f390d18a3a7..77810a13421a73fe8e5b925f0e53b12c060542ca 100644 --- a/library/ZendAfi/View/Helper/Admin/ContentNav.php +++ b/library/ZendAfi/View/Helper/Admin/ContentNav.php @@ -169,7 +169,11 @@ class ZendAfi_View_Helper_Admin_ContentNav extends ZendAfi_View_Helper_BaseHelpe [], function($user) { return defined('DEVELOPMENT') && $user->isAdmin();}], ["thesaurus_edit",$this->_("Modification Thesaurus"), "/admin/systeme/updatethesaurus", - [], function($user) { return defined('DEVELOPMENT') && $user->isAdmin();}] + [], function($user) { return defined('DEVELOPMENT') && $user->isAdmin();}], + ["thesaurus_edit", + $this->_("Parcourir les Thesaurus"), "/admin/thesauri/index", + [], + function($user) { return $user->isAdmin();}] ]); } diff --git a/library/ZendAfi/View/Helper/TagModelTable.php b/library/ZendAfi/View/Helper/TagModelTable.php index e5ca6f94f15a513216fca2a849c700b756ada397..d63054d27a4f65a05b9d2a4e38418d8d0a31e0fa 100644 --- a/library/ZendAfi/View/Helper/TagModelTable.php +++ b/library/ZendAfi/View/Helper/TagModelTable.php @@ -33,7 +33,7 @@ class ZendAfi_View_Helper_TagModelTable extends ZendAfi_View_Helper_BaseHelper { 'relations'); */ - public function tagModelTable($models, $cols, $attribs, $actions, $id, $group_by = null, $callbacks = [], $pager = false) { + public function tagModelTable($models, $cols, $attribs, $actions, $id, $group_by = null, $callbacks = [], $pager = false, $sorter = true) { $description = new Class_TableDescription($id); foreach($cols as $i => $col) { $attribute = $attribs[$i]; @@ -53,8 +53,8 @@ class ZendAfi_View_Helper_TagModelTable extends ZendAfi_View_Helper_BaseHelper { return $this->view->renderTable($description, (new Class_TableDescription_Models($models))->groupBy($group_by), - ['sorter' => true, + ['sorter' => $sorter, 'pager' => $pager]); } -} +}n ?> diff --git a/tests/scenarios/Thesauri/ThesauriTest.php b/tests/scenarios/Thesauri/ThesauriTest.php new file mode 100644 index 0000000000000000000000000000000000000000..84b38f2a14addb1306d281c9aacda357fdc626fe --- /dev/null +++ b/tests/scenarios/Thesauri/ThesauriTest.php @@ -0,0 +1,157 @@ +<?php +/** + * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +abstract class Thesauri_ThesauriTestCase extends Admin_AbstractControllerTestCase { + protected $_storm_default_to_volatile = true; + + public function setUp() { + parent::setUp(); + + $this->fixture('Class_CodifThesaurus', + ['id' => 3, + 'libelle' => 'Document', + 'libelle_facette' => 'Document', + 'id_thesaurus' => 'DOCU', + 'id_origine' => null, + 'code' => 'DOCU', + 'rules' => '{"label":" 99$t "}']); + + $this->fixture('Class_CodifThesaurus', + ['id' => 4, + 'libelle' => 'SIFI', + 'libelle_facette' => 'Science fiction', + 'id_thesaurus' => 'DOCU0001', + 'id_origine' => null, + 'code' => 'DOCU']); + } +} + + + +class Thesauri_ThesauriIndexTest extends Thesauri_ThesauriTestCase { + + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/thesauri/index', true); + } + + + /** @test */ + public function thesauriShouldBeInAdminNav() { + $this->assertXPath('//a[contains(@href, "/thesauri/index")]'); + } + + + /** @test */ + public function thesauriTitleShouldBePresent() { + $this->assertXPathContentContains('//h1', 'Parcourir les Thesaurus'); + } + + + /** @test */ + public function documentShouldBeDisplay() { + $this->assertXpathContentContains('//table', 'Document'); + } + + + /** @test */ + public function rules99DollarTShouldBeDisplay() { + $this->assertXpathContentContains('//table', '99$t'); + } + + /** @test */ + public function editActionShouldBeDisplayed() { + $this->assertXpath('//table//a[contains(@href, "/admin/thesauri/edit/id/3")]'); + } +} + + + + +class Thesauri_ThesauriIndexChildrenTest extends Thesauri_ThesauriTestCase { + + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/thesauri/index/parent_id/3', true); + } + + + /** @test */ + public function documentShouldBeDisplay() { + $this->assertXpathContentContains('//table', 'Document'); + } + + + /** @test */ + public function changeOrderToLibelleFacetteShouldBePresent() { + $this->assertXpathContentContains('//table//a[contains(@href, "order/libelle_facette")]', 'Libellé facette'); + } + + + /** @test */ + public function sifiShouldBeDisplay() { + $this->assertXpathContentContains('//table', 'Science fiction'); + } + + + /** @test */ + public function rules99DollarTShouldBeDisplay() { + $this->assertXpathContentContains('//table', '99$t'); + } + + +} + + +class Thesauri_ThesauriIndexChildrenSearchTest extends Thesauri_ThesauriTestCase { + + public function setUp() { + parent::setUp(); + $_SERVER['HTTP_REFERER'] = 'http://test.org/admin/thesauri/index'; + $this->postDispatch('/admin/thesauri/index', + ['title_search' => 'Docu']); + } + + + /** @test */ + public function searchShouldRedirect() { + $this->assertRedirectTo('/admin/thesauri/index/title_search/Docu/page/1/order/libelle'); + } +} + + + + + +class Thesauri_ThesauriIndexOrderTest extends Thesauri_ThesauriTestCase { + + public function setUp() { + parent::setUp(); + $this->dispatch('/admin/thesauri/index/parent_id/3/order/libelle_facette', true); + } + + + /** @test */ + public function libelleFacetOrderLinkShouldDesc() { + $this->assertXpathContentContains('//table//a[contains(@href, "order/libelle_facette+desc")]', 'Libellé facette'); + } +} \ No newline at end of file