diff --git a/FEATURES/131794 b/FEATURES/131794 new file mode 100644 index 0000000000000000000000000000000000000000..5767eda6e16c31c5f78b6a5a230b3a898fb1c5d7 --- /dev/null +++ b/FEATURES/131794 @@ -0,0 +1,10 @@ + '131794' => + ['Label' => $this->_('Amélioration du contrôle des URL'), + 'Desc' => $this->('L\'outil de contrôle des URL prend maintenant en charge les sitothèques et les collections manuelles.'), + 'Image' => '', + 'Video' => '', + 'Category' => '$this->_(\'Administration\')', + 'Right' => function($feature_description, $user) {return true;}, + 'Wiki' => 'https://wiki.bokeh-library-portal.org/index.php?title=Gestion_des_URL', + 'Test' => '', + 'Date' => '2022-10-03'], \ No newline at end of file diff --git a/VERSIONS_WIP/131794 b/VERSIONS_WIP/131794 new file mode 100644 index 0000000000000000000000000000000000000000..bcd41f1e534001ca9bd43c47ce4de11be1e7e16c --- /dev/null +++ b/VERSIONS_WIP/131794 @@ -0,0 +1 @@ + - fonctionnalité #131794 : Administration : L'outil de contrôle des URL prend maintenant en charge les sitothèques et les collections manuelles. \ No newline at end of file diff --git a/application/modules/admin/controllers/UrlManagerController.php b/application/modules/admin/controllers/UrlManagerController.php index 287ff79e7b0bedde50fffd2da145c6591f8704d3..7deebfab55f2ca14a932512d03b9130a1c0c7a5e 100644 --- a/application/modules/admin/controllers/UrlManagerController.php +++ b/application/modules/admin/controllers/UrlManagerController.php @@ -38,12 +38,12 @@ class Admin_UrlManagerController extends ZendAfi_Controller_Action { public function updateUrlInModelsAction() { - if (!$url = urldecode($this->_getParam('url'))) { + if (!$url = $this->_getParam('url')) { $this->helper->notify($this->_('Mise à jour impossible. Veuillez fournir une url source.')); return $this->_redirectClose($this->view->url(['action' => 'index'])); } - if (!$by = urldecode($this->_getParam('by'))) { + if (!$by = $this->_getParam('by')) { $this->helper->notify($this->_('Mise à jour impossible. Veuillez fournir une url de remplacement.')); return $this->_redirectClose($this->view->url(['action' => 'index'])); } @@ -69,10 +69,10 @@ class Admin_UrlManagerController extends ZendAfi_Controller_Action { session_write_close(); $this->getHelper('ViewRenderer')->setNoRender(); - if (!$url = urldecode($this->_getParam('url'))) + if (!$url = $this->_getParam('url')) return; - if (!$by = urldecode($this->_getParam('by'))) + if (!$by = $this->_getParam('by')) return; if ($url == $by) @@ -83,7 +83,7 @@ class Admin_UrlManagerController extends ZendAfi_Controller_Action { public function editUrlAction() { - if (! $this->view->url = urldecode($this->_getParam('url'))) { + if (! $this->view->url = $this->_getParam('url')) { $this->_helper->notify($this->_('Url inexistante')); return $this->_redirectClose($this->view->url(['action' => 'index'])); } @@ -100,7 +100,7 @@ class Admin_UrlManagerController extends ZendAfi_Controller_Action { public function urlDetailsAction() { - if (!$url=urldecode($this->_getParam('url'))) { + if (!$url=$this->_getParam('url')) { $this->_helper->notify($this->_('Url inexistante')); return $this->_redirectClose($this->view->url(['action' => 'index'])); } @@ -117,7 +117,7 @@ class Admin_UrlManagerController extends ZendAfi_Controller_Action { public function testUrlAction() { session_write_close(); - if (!$url = urldecode($this->_getParam('url'))) + if (!$url = $this->_getParam('url')) return $this->_redirectClose($this->view->url(['action' => 'index'])); $view_renderer = $this->getHelper('ViewRenderer'); diff --git a/application/modules/admin/views/scripts/url-manager/index.phtml b/application/modules/admin/views/scripts/url-manager/index.phtml index ffc572ee4ed197c3719b87f82813f36704546cd6..725ccfe4d6d9d32cb605254ae679fd7e0a340eb7 100644 --- a/application/modules/admin/views/scripts/url-manager/index.phtml +++ b/application/modules/admin/views/scripts/url-manager/index.phtml @@ -6,7 +6,7 @@ Class_ScriptLoader::getInstance() $html = [ - $this->tag('p', $this->_('Cet outil collecte les URL dans les articles, les lettres d\'information et les domaines.')), + $this->tag('p', $this->_('Cet outil collecte les URL dans les articles, les lettres d\'information, les domaines, la sitothèque et les collections manuelles de la bibliothèque numérique.')), $this->tag('p', $this->_('Pour chaque URL collectée, vous pouvez convertir son protocole en HTTPS ainsi qu\'explorer les contenus qui l\'utilise.')), diff --git a/application/modules/admin/views/scripts/url-manager/url-details.phtml b/application/modules/admin/views/scripts/url-manager/url-details.phtml index 0f5d8bff06ef0d1a93614cce7ce9d81eb5fb15c1..a7f9d5542e0c52aace9b6066c3b9471811f10257 100644 --- a/application/modules/admin/views/scripts/url-manager/url-details.phtml +++ b/application/modules/admin/views/scripts/url-manager/url-details.phtml @@ -1,3 +1,3 @@ <?php -echo $this->renderTable((new Class_UrlManager_InstancesDescription())->getDescription($this), +echo $this->renderTable((new Class_UrlManager_InstancesDescription)->getDescription($this)->setPager(false), $this->models); diff --git a/library/Class/AlbumCategorie.php b/library/Class/AlbumCategorie.php index 2b30d3cfac99b1e3e2f3a127ac21458797b1b377..8ec8014340f35210a59bc2cd9bdbae3e0cfb9d7f 100644 --- a/library/Class/AlbumCategorie.php +++ b/library/Class/AlbumCategorie.php @@ -127,14 +127,25 @@ class AlbumCategorieLoader extends Storm_Model_Loader { $albums = new Storm_Model_Collection(Class_AlbumCategorie::getAlbumsFromCategories($ids)); return $albums->collect('id')->getArrayCopy(); } + + + public function getWebsiteCategoryId() : string { + return ($category = $this->findFirstBy(['libelle' => Class_AlbumCategorie::WEBSITE_CATEGORIE_LABEL])) + ? $category->getId() + : ''; + } } class Class_AlbumCategorie extends Storm_Model_Abstract { + use Trait_TreeNode; + const WEBSITE_CATEGORIE_LABEL = 'Sites web'; + + protected $_loader_class = 'AlbumCategorieLoader'; protected $_table_name = 'album_categorie'; protected $_table_primary = 'id'; @@ -315,4 +326,9 @@ class Class_AlbumCategorie extends Storm_Model_Abstract { return $count; } + + + public function isForWebsites() : bool { + return static::WEBSITE_CATEGORIE_LABEL === $this->getLibelle(); + } } \ No newline at end of file diff --git a/library/Class/AlbumRessource.php b/library/Class/AlbumRessource.php index 0ed044e78e205b01d5629b4bccea60a9ae00f2a8..e1447c337f5c423b56517bbf4cfe9f33317820ab 100644 --- a/library/Class/AlbumRessource.php +++ b/library/Class/AlbumRessource.php @@ -1167,4 +1167,9 @@ class Class_AlbumRessource extends Storm_Model_Abstract { return Class_Url::absolute('/bib-numerique/play-ressource/id/' . $this->getId(), null, true) . '.' . $extension; } + + + public function getLibelle() : string { + return (string) $this->getTitre(); + } } diff --git a/library/Class/TypeDoc.php b/library/Class/TypeDoc.php index 3ed58b40fe1270ad8465b5ca1f63e4b65c6210ca..43b4a35f6c46e99271311751c63bcfe0b3be9140 100644 --- a/library/Class/TypeDoc.php +++ b/library/Class/TypeDoc.php @@ -383,6 +383,17 @@ class Class_TypeDoc extends Storm_Model_Abstract { } + public static function getHarvestedIds() : array { + $harvested = static::getDigitalDocTypes(); + unset($harvested[self::LIVRE_NUM]); + unset($harvested[self::DIAPORAMA]); + unset($harvested[self::OAI]); + unset($harvested[self::AUDIO_RECORD]); + unset($harvested[self::WEBSITE]); + return array_keys($harvested); + } + + /** * @param String label * @return Class_Type_Doc diff --git a/library/Class/UrlManager.php b/library/Class/UrlManager.php index 7ef36e6c2229765e742e44d5226e7ee0e7779208..e9a49de399b9641144f87c03da77f6f15b278aa9 100644 --- a/library/Class/UrlManager.php +++ b/library/Class/UrlManager.php @@ -20,12 +20,17 @@ */ -class Class_UrlManager extends Class_Entity { +class Class_UrlManager { protected static $_http_client; - public function findAll($params) { + protected string $_sql_like = ''; + protected string $_preg = ''; + protected string $_protocol = ''; + + + public function findAll(array $params) : array { $protocol = ('no' == $params['protocol']) ? 'http[s]*' : $params['protocol']; @@ -45,7 +50,7 @@ class Class_UrlManager extends Class_Entity { '://'], '', $term); - $preg = '@(' . $protocol . '://'. $search_pattern . '*' . preg_quote($preg_term) . $search_pattern . '*)[\b\s]?@i'; + $preg = '@(' . $protocol . '://'. $search_pattern . '*' . preg_quote($preg_term, '@') . $search_pattern . '*)[\b\s]?@i'; } $this @@ -56,18 +61,17 @@ class Class_UrlManager extends Class_Entity { $urls = $this->_collectUrlInArticles([]); $urls = $this->_collectUrlInNewsletters($urls); $urls = $this->_collectUrlInDomains($urls); + $urls = $this->_collectUrlInLegacyWebsites($urls); + $urls = $this->_collectUrlInCollections($urls); - uasort($urls, function($instances_a, $instances_b) - { - return count($instances_a) < count($instances_b); - }); + uasort($urls, fn($instances_a, $instances_b) => count($instances_a) < count($instances_b)); return $urls; } - public function replace($url, $by) { - $result = new Class_Entity(['Succes' => false]); + public function replace(string $url, string $by) : Class_UrlManager_ReplaceResult { + $result = new Class_UrlManager_ReplaceResult; if (!$url || !$by) return $result; @@ -96,7 +100,9 @@ class Class_UrlManager extends Class_Entity { } - protected function _replaceInInstances($instances, $url, $by) { + protected function _replaceInInstances(array $instances, + string $url, + string $by) : bool { $success = true; foreach ($instances as $model) $success += $model->replace($url, $by); @@ -105,34 +111,79 @@ class Class_UrlManager extends Class_Entity { } - protected function _collectUrlInArticles($urls) { - foreach (Class_Article::findAllBy(['where' => 'concat(description,contenu) like "%'. $this->getSqlLike() .'%"']) as $article) - $urls = $this->_collectUrlInModel((new Class_UrlManager_Article)->setModel($article), $urls); + protected function _collectUrlInArticles(array $urls) : array { + foreach (Storm_Query::from(Class_Article::class) + ->beOr() + ->like('contenu', $this->_getSqlLike()) + ->like('description', $this->_getSqlLike()) + ->fetchAll() as $article) + $urls = $this->_collectUrlInModel(new Class_UrlManager_Article($article), $urls); + + return $urls; + } + + + protected function _collectUrlInNewsletters(array $urls) : array { + foreach (Storm_Query::from(Class_Newsletter::class) + ->like('contenu', $this->_getSqlLike()) + ->fetchAll() as $newsletter) + $urls = $this->_collectUrlInModel(new Class_UrlManager_Newsletter($newsletter), $urls); + + return $urls; + } + + + protected function _collectUrlInDomains(array $urls) : array { + foreach (Storm_Query::from(Class_Catalogue::class) + ->like('url_img', $this->_getSqlLike()) + ->fetchAll() as $domain) + $urls = $this->_collectUrlInModel(new Class_UrlManager_Domain($domain), $urls); return $urls; } - protected function _collectUrlInNewsletters($urls) { - foreach (Class_Newsletter::findAllBy(['where' => 'contenu like "%' . $this->getSqlLike() . '%"']) as $newsletter) - $urls = $this->_collectUrlInModel((new Class_UrlManager_Newsletter)->setModel($newsletter), $urls); + protected function _collectUrlInLegacyWebsites(array $urls) : array { + foreach (Storm_Query::from(Class_Sitotheque::class) + ->like('url', $this->_getSqlLike()) + ->fetchAll() + as $website) + $urls = $this->_collectUrlInModel(new Class_UrlManager_LegacyWebsite($website), $urls); return $urls; } - protected function _collectUrlInDomains($urls) { - foreach (Class_Catalogue::findAllBy(['where' => 'url_img like "%' . $this->getSqlLike() . '%"']) as $domain) - $urls = $this->_collectUrlInModel((new Class_UrlManager_Domain)->setModel($domain), $urls); + protected function _collectUrlInCollections(array $urls) : array { + foreach ( Storm_Query::from(Class_Album::class) + ->like('description', $this->_getSqlLike()) + ->not_in('type_doc_id', Class_TypeDoc::getHarvestedIds()) + ->fetchAll() as $album) + $urls = $this->_collectUrlInModel(new Class_UrlManager_Album($album), $urls); + + if ( ! $albums = Storm_Query::from(Class_Album::class) + ->not_in('type_doc_id', Class_TypeDoc::getHarvestedIds()) + ->fetchAll()) + return $urls; + + $albums_ids = (new Storm_Model_Collection($albums)) + ->collect('id') + ->getArrayCopy(); + + foreach ( Storm_Query::from(Class_AlbumRessource::class) + ->in('id_album', $albums_ids) + ->like('url', $this->_getSqlLike()) + ->fetchAll() as $resource) + $urls = $this->_collectUrlInModel(new Class_UrlManager_Resource($resource), $urls); return $urls; } - protected function _collectUrlInModel($instance, $urls) { + protected function _collectUrlInModel(Class_UrlManager_Abstract $instance, + array $urls) : array { $text = $instance->getData(); preg_match_all($this->getPreg(), $text, $matches, PREG_PATTERN_ORDER); - if (!isset($matches[0]) || !is_array($matches[0])) return $urls; @@ -159,4 +210,32 @@ class Class_UrlManager extends Class_Entity { return $urls; } + + + public function setProtocol(string $protocol) : self { + $this->_protocol = $protocol; + return $this; + } + + + public function setSqlLike(string $sql_like) : self { + $this->_sql_like = $sql_like; + return $this; + } + + + public function setPreg(string $preg) : self { + $this->_preg = $preg; + return $this; + } + + + protected function _getSqlLike() : string { + return '%' . $this->_sql_like . '%'; + } + + + public function getPreg() : string { + return $this->_preg; + } } \ No newline at end of file diff --git a/library/Class/UrlManager/Abstract.php b/library/Class/UrlManager/Abstract.php index 60ca2c70e75e0cf9e6d1dad00e81383ff3158a2a..203d4a94e31e9f2ffcb4cbfc24d71b16207202e1 100644 --- a/library/Class/UrlManager/Abstract.php +++ b/library/Class/UrlManager/Abstract.php @@ -20,20 +20,51 @@ */ -abstract class Class_UrlManager_Abstract extends Class_Entity { - abstract public function getData(); - abstract public function replace($url, $by); +abstract class Class_UrlManager_Abstract { - public function getType() { + + protected Storm_Model_Abstract $_model; + protected string $_id = ''; + protected string $_url = ''; + + + public function setId(string $id) : self { + $this->_id = $id; + return $this; + } + + + public function setUrl(string $url) : self { + $this->_url = $url; + return $this; + } + + + public function getUrl() : string { + return $this->_url; + } + + + public function getId() : string { + return $this->_id; + } + + + public function getModel() : Storm_Model_Abstract { + return $this->_model; + } + + + public function getType() : string { return get_class($this->getModel()); } - public function getTitle() { - if (!$model = $this->getModel()) - return ''; - return $model->getLibelle(); + public function getTitle() : string { + return $this->_model->getLibelle(); } - abstract public function getAdminUrl(); + abstract public function getData() : string; + abstract public function replace(string $url, string $by) : bool; + abstract public function getAdminUrl() : string; } diff --git a/library/Class/UrlManager/Album.php b/library/Class/UrlManager/Album.php new file mode 100644 index 0000000000000000000000000000000000000000..e81dae2f497df4be32f3f705f4e8ccf2727d6a0c --- /dev/null +++ b/library/Class/UrlManager/Album.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright (c) 2012-2022, 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_UrlManager_Album extends Class_UrlManager_Abstract { + + + public function __construct(Class_Album $album) { + $this->_model = $album; + } + + + public function getData() : string { + return (string) $this->_model->getDescription(); + } + + + public function replace(string $url, string $by) : bool { + return $this->_model + ->setDescription(str_ireplace($url, $by, $this->_model->getDescription())) + ->save(); + } + + + public function getAdminUrl() : string { + return Class_Url::relative(['module' => 'admin', + 'controller' => 'album', + 'action' => 'edit_album', + 'id' => $this->_model->getId()]); + } +} diff --git a/library/Class/UrlManager/Article.php b/library/Class/UrlManager/Article.php index 8d1fb4923419e20b51da28f549dd534f9cc6a106..96fcc2998d73bad2397d01bd0fd19ff4017ce49c 100644 --- a/library/Class/UrlManager/Article.php +++ b/library/Class/UrlManager/Article.php @@ -23,34 +23,30 @@ class Class_UrlManager_Article extends Class_UrlManager_Abstract { - public function getData() { - if (!$model = $this->getModel()) - return ''; + public function __construct(Class_Article $article) { + $this->_model = $article; + } + - return $model->getDescription() + public function getData() : string { + return $this->_model->getDescription() . ' ' - . $model->getContenu(); + . $this->_model->getContenu(); } - public function replace($url, $by) { - if (!$model = $this->getModel()) - return false; - - return $model - ->setContenu(str_ireplace($url, $by, $model->getContenu())) - ->setDescription(str_ireplace($url, $by, $model->getDescription())) + public function replace(string $url, string $by) : bool { + return $this->_model + ->setContenu(str_ireplace($url, $by, $this->_model->getContenu())) + ->setDescription(str_ireplace($url, $by, $this->_model->getDescription())) ->save(); } - public function getAdminUrl() { - if (!$model = $this->getModel()) - return '#'; - - return Class_Url::absolute(['module' => 'admin', + public function getAdminUrl() : string { + return Class_Url::relative(['module' => 'admin', 'controller' => 'cms', 'action' => 'edit', - 'id' => $model->getId()]); + 'id' => $this->_model->getId()]); } } diff --git a/library/Class/UrlManager/Description.php b/library/Class/UrlManager/Description.php index afe6e297906eb9bc536cceb3384a1f7467b8e287..c958750944c5731545e3a7f09e2fa0b8c30817cb 100644 --- a/library/Class/UrlManager/Description.php +++ b/library/Class/UrlManager/Description.php @@ -44,10 +44,10 @@ class Class_UrlManager_Description { function($instances) use ($view) { $instance = current($instances); - $url = Class_Url::absolute(['module' => 'admin', + $url = Class_Url::relative(['module' => 'admin', 'controller' => 'url-manager', 'action' => 'test-url', - 'url' => urlencode($instance->getUrl())]); + 'url' => $instance->getUrl()]); return $view->tag('div', '' , ['data-test-url' => $url, @@ -59,11 +59,11 @@ class Class_UrlManager_Description { function($instances) use ($view) { $instance = current($instances); - $url = Class_Url::absolute(['module' => 'admin', + $url = Class_Url::relative(['module' => 'admin', 'controller' => 'url-manager', 'action' => 'test-url', - 'url' => urlencode(str_replace('http://', - 'https://', $instance->getUrl()))]); + 'url' => str_replace('http://', + 'https://', $instance->getUrl())]); return $view->tag('div', '' , ['data-test-url' => $url, 'data-selectable' => '0', @@ -84,20 +84,17 @@ class Class_UrlManager_Description { $url = $instance->getUrl(); $https_url = str_replace('http://', 'https://', $url); - $url_request = urlencode($url); - $update_url = Class_Url::absolute(['module' => 'admin', + $update_url = Class_Url::relative(['module' => 'admin', 'controller' => 'url-manager', 'action' =>'update-url-in-models', - 'url' => $url_request, - 'by' => urlencode($https_url)] - , null, true); + 'url' => $url, + 'by' => $https_url]); - $async_update_url = Class_Url::absolute(['module' => 'admin', + $async_update_url = Class_Url::relative(['module' => 'admin', 'controller' => 'url-manager', 'action' =>'async-update-url-in-models', - 'url' => $url_request, - 'by' => urlencode($https_url)] - , null, true); + 'url' => $url, + 'by' => $https_url]); $actions = [$view->tagAnchor('#', Class_Admin_Skin::current() @@ -110,7 +107,7 @@ class Class_UrlManager_Description { 'data-convert' => $async_update_url, 'data-image-selected' => Class_Admin_Skin::current()->getIconUrl('actions', 'show'), 'data-image-not-selected' => Class_Admin_Skin::current()->getIconUrl('actions', 'hide'), - 'data-selected-status' => $instance->getSelectedStatus()]), + 'data-selected-status' => '0']), $view->tagAnchor('#', Class_Admin_Skin::current() @@ -130,7 +127,7 @@ class Class_UrlManager_Description { $view->tagAnchor($view->url(['controller' => 'url-manager', 'action' =>'url-details', - 'url' => $url_request]), + 'url' => $url]), Class_Admin_Skin::current() ->renderActionIconOn('loupe', $view, @@ -140,7 +137,7 @@ class Class_UrlManager_Description { $view->tagAnchor($view->url(['controller' => 'url-manager', 'action' =>'edit-url', - 'url' => $url_request]), + 'url' => $url]), Class_Admin_Skin::current() ->renderActionIconOn('edit', $view, diff --git a/library/Class/UrlManager/Domain.php b/library/Class/UrlManager/Domain.php index 207728e654bfa58ea0530fe8fe311ada47907b68..eb782353e1ab5453eb7be49cb3fdbf8ee48ee3ae 100644 --- a/library/Class/UrlManager/Domain.php +++ b/library/Class/UrlManager/Domain.php @@ -23,30 +23,27 @@ class Class_UrlManager_Domain extends Class_UrlManager_Abstract { - public function getData() { - return ($model = $this->getModel()) - ? $model->getUrlImg() - : ''; + public function __construct(Class_Catalogue $domain) { + $this->_model = $domain; } - public function replace($url, $by) { - if (!$model = $this->getModel()) - return false; + public function getData() : string { + return $this->_model->getUrlImg(); + } + - return $model - ->setUrlImg(str_ireplace($url, $by, $model->getUrlImg())) + public function replace(string $url, string $by) : bool { + return $this->_model + ->setUrlImg(str_ireplace($url, $by, $this->_model->getUrlImg())) ->save(); } - public function getAdminUrl() { - if (!$model = $this->getModel()) - return '#'; - - return Class_Url::absolute(['module' => 'admin', + public function getAdminUrl() : string { + return Class_Url::relative(['module' => 'admin', 'controller' => 'catalogue', 'action' => 'edit', - 'id_catalogue' => $model->getId()]); + 'id_catalogue' => $this->_model->getId()]); } } diff --git a/library/Class/UrlManager/LegacyWebsite.php b/library/Class/UrlManager/LegacyWebsite.php new file mode 100644 index 0000000000000000000000000000000000000000..4869ee05b7702ef7945ed0a8e174d706e39c722b --- /dev/null +++ b/library/Class/UrlManager/LegacyWebsite.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright (c) 2012-2022, 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_UrlManager_LegacyWebsite extends Class_UrlManager_Abstract { + + + public function __construct(Class_Sitotheque $website) { + $this->_model = $website; + } + + + public function getData() : string { + return (string) $this->_model->getUrl(); + } + + + public function replace(string $url, string $by) : bool { + return $this->_model + ->setUrl(str_ireplace($url, $by, $this->_model->getUrl())) + ->save(); + } + + + public function getAdminUrl() : string { + return Class_Url::relative(['module' => 'admin', + 'controller' => 'sito', + 'action' => 'edit', + 'id' => $this->_model->getId()]); + } +} diff --git a/library/Class/UrlManager/Newsletter.php b/library/Class/UrlManager/Newsletter.php index 1eacf75f2a5ab34e8016c47bb55ea00ef199d563..62171d0080e6d0ecbe57be09c6247c7a0e22c2e0 100644 --- a/library/Class/UrlManager/Newsletter.php +++ b/library/Class/UrlManager/Newsletter.php @@ -23,30 +23,27 @@ class Class_UrlManager_Newsletter extends Class_UrlManager_Abstract { - public function getData() { - return ($model = $this->getModel()) - ? $model->getContenu() - : ''; + public function __construct(Class_Newsletter $newsletter) { + $this->_model = $newsletter; } - public function replace($url, $by) { - if (!$model = $this->getModel()) - return false; + public function getData() : string { + return $this->_model->getContenu(); + } + - return $model - ->setContenu(str_ireplace($url, $by, $model->getContenu())) + public function replace(string $url, string $by) : bool { + return $this->_model + ->setContenu(str_ireplace($url, $by, $this->_model->getContenu())) ->save(); } - public function getAdminUrl() { - if (!$model = $this->getModel()) - return '#'; - - return Class_Url::absolute(['module' => 'admin', + public function getAdminUrl() : string { + return Class_Url::relative(['module' => 'admin', 'controller' => 'newsletter', 'action' => 'edit', - 'id' => $model->getId()]); + 'id' => $this->_model->getId()]); } } \ No newline at end of file diff --git a/library/Class/UrlManager/ReplaceResult.php b/library/Class/UrlManager/ReplaceResult.php new file mode 100644 index 0000000000000000000000000000000000000000..899fc2d2ffd13223b6f8140df1f9d73d03b9fdcc --- /dev/null +++ b/library/Class/UrlManager/ReplaceResult.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright (c) 2012-2022, 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_UrlManager_ReplaceResult { + protected bool $_success = false; + + + public function setSuccess(bool $success) : self { + $this->_success = $success; + return $this; + } + + + public function getSuccess() : bool { + return $this->_success; + } +} diff --git a/library/Class/UrlManager/Resource.php b/library/Class/UrlManager/Resource.php new file mode 100644 index 0000000000000000000000000000000000000000..bc47b435426d0b3c1fcc612cc3aeab4f54361393 --- /dev/null +++ b/library/Class/UrlManager/Resource.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright (c) 2012-2022, 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_UrlManager_Resource extends Class_UrlManager_Abstract { + + + public function __construct(Class_AlbumRessource $resource) { + $this->_model = $resource; + } + + + public function getData() : string { + return (string) $this->_model->getUrl(); + } + + + public function replace(string $url, string $by) : bool { + return $this->_model + ->setUrl(str_ireplace($url, $by, $this->_model->getUrl())) + ->save(); + } + + + public function getAdminUrl() : string { + return Class_Url::relative(['module' => 'admin', + 'controller' => 'album', + 'action' => 'edit_ressource', + 'id' => $this->_model->getId()]); + } +} diff --git a/library/ZendAfi/Controller/Plugin/Manager/Album.php b/library/ZendAfi/Controller/Plugin/Manager/Album.php index c538564949d923ae476c974fcddad9908e6aace7..a9d28813e738acbcf6b80dfe000c466d306533d6 100644 --- a/library/ZendAfi/Controller/Plugin/Manager/Album.php +++ b/library/ZendAfi/Controller/Plugin/Manager/Album.php @@ -52,6 +52,11 @@ class ZendAfi_Controller_Plugin_Manager_Album extends ZendAfi_Controller_Plugin_ return; } + if ( $categorie->isForWebsites()) { + $this->_helper->notify($this->_('La catégorie %s ne peut pas être modifiée', Class_AlbumCategorie::WEBSITE_CATEGORIE_LABEL)); + return $this->_redirect('admin/album'); + } + $this->_renderCategoryForm( $categorie, 'Modification de la '. ((!$categorie->hasParentCategorie()) ? 'collection' : 'catégorie') . ' "' . $categorie->getLibelle() . '"'); @@ -609,6 +614,8 @@ class ZendAfi_Controller_Plugin_Manager_Album extends ZendAfi_Controller_Plugin_ public function addWebsiteAction() { + $this->_view->titre = $this->_('Importer un site'); + $import_form = $this->_view ->newForm(['id' => 'import', 'class' => 'form']) ->setMethod('post') @@ -622,7 +629,6 @@ class ZendAfi_Controller_Plugin_Manager_Album extends ZendAfi_Controller_Plugin_ ['label' => $this->_('Importer')]); $this->_view->import_form = $import_form; - $this->_view->titre = $this->_('Importer un site'); if (!$this->_request->isPost() || @@ -695,7 +701,7 @@ class ZendAfi_Controller_Plugin_Manager_Album extends ZendAfi_Controller_Plugin_ $dom = new Zend_Dom_Query($html); $title_node = $dom->queryXpath('//head/title')->current(); - $category = Class_AlbumCategorie::getOrCreateRootCategory('Sites web'); + $category = Class_AlbumCategorie::getOrCreateRootCategory(Class_AlbumCategorie::WEBSITE_CATEGORIE_LABEL); $album = Class_Album::newInstance(['type_doc_id' => Class_TypeDoc::WEBSITE, 'categorie' => $category]); diff --git a/library/storm b/library/storm index bcc5c97963992a729a2d598c6945bccdf6c6d18c..d1dbd909b0d89e20ca534ca1f8cdd1c876dafaaf 160000 --- a/library/storm +++ b/library/storm @@ -1 +1 @@ -Subproject commit bcc5c97963992a729a2d598c6945bccdf6c6d18c +Subproject commit d1dbd909b0d89e20ca534ca1f8cdd1c876dafaaf diff --git a/tests/application/modules/admin/controllers/AlbumControllerAddWebsiteTest.php b/tests/application/modules/admin/controllers/AlbumControllerAddWebsiteTest.php index fad362f853f490f174fe5f86aa2413b2ec3b7e3e..5abf5ebc958ee6a02c248c10589d9e2eb27bba3a 100644 --- a/tests/application/modules/admin/controllers/AlbumControllerAddWebsiteTest.php +++ b/tests/application/modules/admin/controllers/AlbumControllerAddWebsiteTest.php @@ -384,3 +384,18 @@ class AlbumControllerAddWebsiteEditDuplicatedResourceCnedTest $this->assertXPathCount('//p[@class="error"][contains(text(), "Sites déjà référencés")]//a', 1); } } + + + + +class AlbumControllerAddWebsiteEditWebsitesCategoryTest extends Admin_AbstractControllerTestCase { + /** @test */ + public function websitesCategoryShouldNotBeEditable() { + $this->fixture(Class_AlbumCategorie::class, + ['id' => 213, + 'libelle' => 'Sites web']); + $this->dispatch('admin/album/edit_categorie/id/213'); + $this->assertRedirectTo('/admin/album'); + $this->assertFlashMessengerContentContains('La catégorie Sites web ne peut pas être modifiée'); + } +} diff --git a/tests/application/modules/admin/controllers/UrlManagerControllerTest.php b/tests/application/modules/admin/controllers/UrlManagerControllerTest.php index ea40b5dfd12fd9749b943455995994d22cae98af..fd6ca54fc1c5e7df89b134ced69c9038f1c9b3b2 100644 --- a/tests/application/modules/admin/controllers/UrlManagerControllerTest.php +++ b/tests/application/modules/admin/controllers/UrlManagerControllerTest.php @@ -72,41 +72,41 @@ class UrlManagerControllerIndexPostDispatchTest extends Admin_AbstractController -abstract class UrlManagerTestCase extends Admin_AbstractControllerTestCase { - protected $_storm_default_to_volatile = true; +abstract class UrlManagerTestCase extends Admin_AbstractControllerTestCase { public function setUp() { parent::setUp(); - $this->fixture('Class_Article', + $this->fixture(Class_Article::class, ['id' => 78, 'titre' => 'Chien et chat', 'description' => 'test de description : http://mon-domain.org', 'contenu' => 'test: http://monurl.fr. http://mon-domain.org']); - $this->fixture('Class_Newsletter', + $this->fixture(Class_Newsletter::class, ['id' => 45, 'titre' => 'Les nouveautés', 'mail_subject' => 'nouveautés', 'contenu' => 'test de newsletter: http://monurl.newsletter.fr. http://mon-domain.org']); - $this->fixture('Class_Catalogue', - ['id' => 63, - 'libelle' => 'Musique', - 'url_img' => 'http://mon-domain.org/mon-image.jpeg']); + $this->fixture(Class_Catalogue::class, + ['id' => 63, + 'libelle' => 'Musique', + 'url_img' => 'http://mon-domain.org/mon-image.jpeg']); } } + class UrlManagerControllerIndexDispatchWithURLFilteredTest extends UrlManagerTestCase { public function setUp() { parent::setUp(); - $this->dispatch('/admin/url-manager/index', true); + $this->dispatch('/admin/url-manager/index'); } @@ -214,30 +214,42 @@ class UrlManagerControllerEditUrlActionTest extends UrlManagerTestCase { + class UrlManagerUrlDetailsActionTest extends UrlManagerTestCase { + public function setUp() { parent::setUp(); - $this->dispatch('/admin/url-manager/url-details/url/'.urlencode('http://mon-domain.org'),true); + $this->dispatch('/admin/url-manager/url-details/url/'.urlencode('http://mon-domain.org')); } + /** @test */ public function shouldContainsChienEtChat() { $this->assertXPathContentContains('//td', 'Chien et chat'); } + /** @test */ public function shouldContainsLesnouveautes() { $this->assertXPathContentContains('//td', 'Les nouveautés'); } + /** @test */ public function shouldContainsMusique() { $this->assertXPathContentContains('//td', 'Musique'); } + + + /** @test */ + public function pagerShouldNotBePresent() { + $this->assertNotXpath('//div[@class="pager model_table_pager pager_urls"]'); + } } + class UrlManagerControllerTestUrlActionTest extends UrlManagerTestCase { public function setUp() { @@ -301,19 +313,235 @@ class UrlManagerControllerIndexDispatchUrlWithPlusTest extends UrlManagerTestCas public function setUp() { parent::setUp(); - $this->fixture('Class_Article', + $this->fixture(Class_Article::class, ['id' => 78, 'titre' => 'Chien et chat', - 'description' => 'test de description : http://mon-domain.org', - 'contenu' => 'test: http://monurl.fr. http://mon-domain.org/recherche/pommo+d\'api']); - - $this->dispatch(sprintf('/admin/url-manager/index/term/%s', - urlencode('http://mon-domain.org/recherche/pommo+d\'api'))); + 'description' => 'test de description : http://mon-domain.org http://with-arobase@.org', + 'contenu' => 'test: http://monurl.fr. http://mon-domain.org/recherche/pomme+d\'api']); } /** @test **/ public function tableUrlShouldContainsMonDomainePregEscaped() { - $this->assertXPathContentContains('//table[@id="urls"]//td', 'http://mon-domain.org/recherche/pommo+d\'api'); + $this->dispatch(sprintf('/admin/url-manager/index/term/%s', + urlencode('http://mon-domain.org/recherche/pomme+d\'api'))); + $this->assertXPathContentContains('//table[@id="urls"]//td', 'http://mon-domain.org/recherche/pomme+d\'api'); + } + + + /** @test */ + public function postEditUrlShouldUpdateWebsiteUrl() { + $this->postDispatch('/admin/url-manager/edit-url/url/' + . urlencode('http://mon-domain.org/recherche/pomme+d\'api'), + ['new_url' => 'https://mon-domain.org/recherche/pomme+d\'api']); + $this->assertEquals('test: http://monurl.fr. https://mon-domain.org/recherche/pomme+d\'api', + Class_Article::find(78)->getContenu()); + } + + + /** @test */ + public function postEditUrlWithArobaseInHttpsShouldUpdateArobaseUrl() { + $this->postDispatch('/admin/url-manager/edit-url/url/' + . urlencode('http://with-arobase@.org'), + ['new_url' => 'https://with-arobase@.org']); + $this->assertEquals('test de description : http://mon-domain.org https://with-arobase@.org', + Class_Article::find(78)->getDescription()); + } +} + + + + +class UrlManagerControllerWithLegacyWebsiteTest extends UrlManagerTestCase { + public function setUp() { + parent::setUp(); + + $this->fixture(Class_Sitotheque::class, + ['id' => 1, + 'titre' => 'Le Pic', + 'url' => 'http://www.le-pic.org/']); + } + + + /** @test */ + public function dispatchIndexTableShouldContainsLePicDorOrg() { + $this->dispatch('/admin/url-manager'); + $this->assertXPathContentContains('//table//td', 'http://www.le-pic.org/'); + } + + + /** @test */ + public function dispatchDetailTableShouldContainsEditSiteOne() { + $this->dispatch('/admin/url-manager/url-details?url=http://www.le-pic.org'); + $this->assertXPath('//table//td/a[contains(@href, "/admin/sito/edit/id/1")]'); + } + + + /** @test */ + public function postEditUrlShouldUpdateWebsiteUrl() { + $this->postDispatch('/admin/url-manager/edit-url?url=http://www.le-pic', + ['new_url' => 'https://www.le-pic']); + $this->assertEquals('https://www.le-pic.org/', Class_Sitotheque::find(1)->getUrl()); + } +} + + + + +class UrlManagerControllerWithCollectionWebsiteTest extends UrlManagerTestCase { + public function setUp() { + parent::setUp(); + + Class_AlbumCategorie::getOrCreateRootCategory(Class_AlbumCategorie::WEBSITE_CATEGORIE_LABEL); + + $this->fixture(Class_Album::class, + ['id' => 1, + 'titre' => 'Le Pic', + 'cat_id' => 1, + 'description' => 'test de description : http://www.le-pic.org']); + + $this->fixture(Class_AlbumRessource::class, + ['id' => 1, + 'id_album' => 1, + 'url' => 'http://www.le-pic.org']); + } + + + /** @test */ + public function dispatchIndexTableShouldContainsLePicDorOrg() { + $this->dispatch('/admin/url-manager'); + $this->assertXPathContentContains('//table//td', 'http://www.le-pic.org'); + } + + + /** @test */ + public function dispatchDetailTableShouldContainsEditAlbumOne() { + $this->dispatch('/admin/url-manager/url-details?url=http://www.le-pic.org'); + $this->assertXPath('//table//td/a[contains(@href, "/admin/album/edit_album/id/1")]'); + } + + + /** @test */ + public function dispatchDetailTableShouldContainsEditAlbumResourceOne() { + $this->dispatch('/admin/url-manager/url-details?url=http://www.le-pic.org'); + $this->assertXPath('//table//td/a[contains(@href, "/admin/album/edit_ressource/id/1")]'); + } + + + /** @test */ + public function postEditUrlShouldUpdateAlbumResourceOneUrl() { + $this->postDispatch('/admin/url-manager/edit-url?url=http://www.le-pic', + ['new_url' => 'https://www.le-pic']); + $this->assertEquals('https://www.le-pic.org', Class_AlbumRessource::find(1)->getUrl()); + } + + + /** @test */ + public function postEditUrlShouldUpdateAlbumOneDescription() { + $this->postDispatch('/admin/url-manager/edit-url?url=http://www.le-pic', + ['new_url' => 'https://www.le-pic']); + $this->assertEquals('test de description : https://www.le-pic.org', Class_Album::find(1)->getDescription()); + } +} + + + + +class UrlManagerControllerWithCollectionTest extends UrlManagerTestCase { + public function setUp() { + parent::setUp(); + + Class_AlbumCategorie::getOrCreateRootCategory('À la mano'); + + $this->fixture(Class_Album::class, + ['id' => 1, + 'titre' => 'Le Pic', + 'cat_id' => 1, + 'description' => 'test de description : http://www.le-pic.org']); + + $this->fixture(Class_AlbumRessource::class, + ['id' => 1, + 'id_album' => 1, + 'url' => 'http://www.le-pic.org']); + + $this->fixture(Class_Album::class, + ['id' => 2, + 'titre' => 'Le Pic sans description', + 'cat_id' => 1]); + + $this->fixture(Class_AlbumRessource::class, + ['id' => 2, + 'id_album' => 2, + 'url' => 'http://www.le-pic.org/resource2']); + + $this->fixture(Class_Album::class, + ['id' => 3, + 'type_doc_id' => 119, + 'titre' => 'Le Pic Cite de la Musique', + 'cat_id' => 1]); + + $this->fixture(Class_AlbumRessource::class, + ['id' => 3, + 'id_album' => 3, + 'url' => 'http://www.le-pic.org/cite_de_la_musique']); + } + + + /** @test */ + public function dispatchIndexTableShouldContainsLePicDorOrg() { + $this->dispatch('/admin/url-manager'); + $this->assertXPathContentContains('//table//td', 'http://www.le-pic.org'); + } + + + /** @test */ + public function dispatchIndexTableShouldContainsLePicDorOrgSlashResourceTwo() { + $this->dispatch('/admin/url-manager'); + $this->assertXPathContentContains('//table//td', 'http://www.le-pic.org/resource2'); + } + + + /** @test */ + public function dispatchIndexTableShouldNotContainsLePicDorOrgSlashCiteDeLaMusique() { + $this->dispatch('/admin/url-manager'); + $this->assertNotXPathContentContains('//table//td', 'http://www.le-pic.org/cite_de_la_musique',); + } + + + /** @test */ + public function dispatchDetailTableShouldContainsEditAlbumOne() { + $this->dispatch('/admin/url-manager/url-details?url=http://www.le-pic.org'); + $this->assertXPath('//table//td/a[contains(@href, "/admin/album/edit_album/id/1")]'); + } + + + /** @test */ + public function dispatchDetailTableShouldContainsEditAlbumResourceOne() { + $this->dispatch('/admin/url-manager/url-details?url=http://www.le-pic.org'); + $this->assertXPath('//table//td/a[contains(@href, "/admin/album/edit_ressource/id/1")]'); + } + + + /** @test */ + public function postEditUrlShouldUpdateAlbumResourceOneUrl() { + $this->postDispatch('/admin/url-manager/edit-url?url=http://www.le-pic', + ['new_url' => 'https://www.le-pic']); + $this->assertEquals('https://www.le-pic.org', Class_AlbumRessource::find(1)->getUrl()); + } + + + /** @test */ + public function postEditUrlShouldUpdateAlbumResourceTwoUrl() { + $this->postDispatch('/admin/url-manager/edit-url?url=http://www.le-pic', + ['new_url' => 'https://www.le-pic']); + $this->assertEquals('https://www.le-pic.org/resource2', Class_AlbumRessource::find(2)->getUrl()); + } + + + /** @test */ + public function postEditUrlShouldUpdateAlbumOneDescription() { + $this->postDispatch('/admin/url-manager/edit-url?url=http://www.le-pic', + ['new_url' => 'https://www.le-pic']); + $this->assertEquals('test de description : https://www.le-pic.org', Class_Album::find(1)->getDescription()); } } \ No newline at end of file