From 51631e1eab9337a2781d579a1e293eb8d64a7359 Mon Sep 17 00:00:00 2001 From: Patrick Barroca <pbarroca@afi-sa.fr> Date: Tue, 7 Jun 2022 15:38:16 +0200 Subject: [PATCH] fix RT --- library/Class/CodifThesaurus.php | 569 +--------------- library/Class/CodifThesaurus/Loader.php | 608 ++++++++++++++++++ .../Cosmogramme/Integration/PhaseDomains.php | 50 +- library/Class/Notice/Loader.php | 7 +- library/Class/NoticeDomain.php | 2 +- .../Integration/PhaseDomainsTest.php | 16 +- 6 files changed, 638 insertions(+), 614 deletions(-) create mode 100644 library/Class/CodifThesaurus/Loader.php diff --git a/library/Class/CodifThesaurus.php b/library/Class/CodifThesaurus.php index 612e5d4983e..e7b6b857ed3 100644 --- a/library/Class/CodifThesaurus.php +++ b/library/Class/CodifThesaurus.php @@ -19,573 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -class CodifThesaurusLoader extends Storm_Model_Loader { - use Trait_Translator; - - protected - $_fixed = [], - $_customfields_facet_prefix, - $_all_by_dynamic_facets; - - public function __construct($class) { - parent::__construct($class); - $this->_fixed = Class_CodifThesaurusFixed::getAll(); - } - - - public function findFixed($key) { - return isset($this->_fixed[$key]) - ? $this->_fixed[$key] - : null; - } - - - public function findThesaurusForCatalogue($catalogue_id) { - return Class_CodifThesaurus::getLoader() - ->findFirstBy(['id_origine'=> $catalogue_id, - 'code' => Class_CodifThesaurus::fixedCodeOf('Domain')]); - } - - - public function collectForModelsUnderFixed($fixed_name, $models, $closure) { - if (!isset($this->_fixed[$fixed_name])) - return; - - foreach($models as $model) - $closure($this->ensureForModelUnderRoot($model, $this->_fixed[$fixed_name])); - } - - - public function findLibraryNoveltyFor($library_id) { - return ($library = Class_Bib::find((int)$library_id)) - ? $this->_ensureLibraryNoveltyThesaurus($library) - : null; - } - - - public function ensureRecordNovelty() { - $this->recordNoveltyFor(true); - $this->recordNoveltyFor(false); - } - - - /** @param $flag boolean */ - public function recordNoveltyFor($flag) { - $attributes = ((bool) $flag) - ? ['Id' => 1, 'Libelle' => $this->_('Oui')] - : ['Id' => 2, 'Libelle' => $this->_('Non')]; - - return $this->ensureForModelUnderRoot(new Class_Entity($attributes), - $this->_fixed['RecordNovelty']); - } - - - public function ensureForModelUnderRoot($model, Class_CodifThesaurusFixed $definition) { - return ($root = $definition->getThesaurus()) - ? $root->getOrCreateChild($model->getId(), $model->getLibelle()) - : null; - } - - - protected function _ensureLibraryNoveltyThesaurus($model) { - return $this->ensureForModelUnderRoot($model, $this->_fixed['LibraryNovelty']); - } - - - protected function _ensureAnnexeNoveltyThesaurus($model) { - return $this->ensureForModelUnderRoot($model, $this->_fixed['AnnexeNovelty']); - } - - - public function findForCustomField($field) { - return Class_CodifThesaurus::findForCustomFieldMeta($field->getMeta()); - } - - - public function getOrCreateForCustomField($field) { - return Class_CodifThesaurus::getOrCreateForCustomFieldMeta($field->getMeta()); - } - - - public function findForCustomFieldMeta($meta) { - return Class_CodifThesaurus::getLoader() - ->findFirstBy(['id_origine' => $meta->getId(), - 'code' => Class_CodifThesaurus::fixedCodeOf('CustomField')]); - } - - - public function getOrCreateForCustomFieldMeta($meta) { - return Class_CodifThesaurus::findCustomFieldsRoot() - ->getOrCreateChild($meta->getId(), $meta->getLabel()); - } - - - public function findCustomFieldsRoot() { - $definition = $this->_fixed['CustomField']; - return Class_CodifThesaurus::findRootOfId($definition->getId(), - $definition->getCode(), - $definition->getLabel()); - } - - - public function findForItemLibraryNovelty($item) { - if(!$library = $item->getBib()) - return null; - - return ($item = $this->ensureForModelUnderRoot($library, $this->_fixed['LibraryNovelty'])) - ? $item->getFacetteIndex() - : ''; - } - - - public function findForItemAnnexeNovelty($item) { - if(!$model = $item->getCodifAnnexe()) - return null; - - return ($item = $this->ensureForModelUnderRoot($model, $this->_fixed['AnnexeNovelty'])) - ? $item->getFacetteIndex() - : ''; - } - - - public function countChildrenOf($id_thesaurus) { - $where = sprintf('id_thesaurus like "%s%%" and LENGTH(id_thesaurus) > %s', - $id_thesaurus, - strlen($id_thesaurus)); - - return Class_CodifThesaurus::countBy(['where' => $where]); - } - - - public function findChildrenOfWith($id_thesaurus, $limit, $order) { - $where = sprintf('id_thesaurus like "%s%%" and LENGTH(id_thesaurus) = %s', - $id_thesaurus, - (strlen($id_thesaurus) + 4)); - - return Class_CodifThesaurus::findAllBy(['where' => $where, - 'limitPage' => $limit, - 'order' => $order]); - } - - - public function findRootOfId($id, $code, $label) { - if ($codif = Class_CodifThesaurus::findFirstBy(['id_thesaurus' => $id])) - return $codif; - - $attributes = ['id_thesaurus' => $id, - 'libelle' => $label, - 'code' => $code]; - - $codif = Class_CodifThesaurus::newInstance($attributes); - - return $codif->save() ? $codif : null; - } - - - public function addFacetForSigb($facet_name, $facet_rules, $comm_sigb) { - if (!Class_IntBib::findFirstBy(['comm_sigb' => $comm_sigb])) - return; - - $parts = explode('$', trim($facet_rules)); - if (2 !== count($parts)) - return; - - $zone = $parts[0]; - $label_field = $parts[1]; - - $list_rules = (new Class_CodifThesaurus_ListRules()) - ->setListZone([$zone]) - ->setListLabelField([$label_field]); - - if (Class_CodifThesaurus::findFirstBy(['rules' => $list_rules->format()])) - return ; - - Class_CodifThesaurus::newInstance(['libelle' => $facet_name, - 'libelle_facette' => $facet_name, - 'rule_list_zone' => [$zone], - 'rule_list_label_field' => [$label_field]]) - ->save(); - } - - - public function getLibelleHierarchique($enreg) { - if (!$enreg) - return ''; - - if (!$parent = Class_CodifThesaurus::findParent($enreg->getIdThesaurus())) - return $enreg->getLibelle(); - - if (strlen($parent->getIdThesaurus()) <= 8) - return $parent->getLibelle() . ' : ' . $enreg->getLibelle(); - - return $this->getLibelleHierarchique($parent) . ' : ' . $enreg->getLibelle(); - } - - - public function findParent($id_thesaurus) { - $parent_str = substr($id_thesaurus, - 0, - strlen($id_thesaurus) - Class_CodifThesaurus::ID_KEY_LENGTH); - if (!$parent_str) - return null; - - $parent = Class_CodifThesaurus::findFirstBy(['id_thesaurus' => $parent_str]); - if (!$parent) - return $this->findParent($parent_str); - - return $parent; - } - - - /** @return string */ - public function findNextThesaurusChildId($code, $parentid_thesaurus) { - Class_CodifThesaurus::clearCache(); - $last_thesaurus = Class_CodifThesaurus::findFirstBy(['code' => $code, - Class_CodifThesaurus::clauseStart('id_thesaurus', $parentid_thesaurus), - 'order' => 'id_thesaurus desc']); - if (!$last_thesaurus) - return $parentid_thesaurus.'0001'; - - if (strlen($parentid_thesaurus) >=strlen($last_thesaurus->getIdThesaurus())) - return $parentid_thesaurus.'0001'; - - return $this->incrementId(substr($last_thesaurus->getIdThesaurus(),0, strlen($parentid_thesaurus)+4)) ; - } - - - public function incrementId($id) { - $last=base_convert(substr($id,strlen($id)-4), 36, 10); - $first_part=substr($id,0,strlen($id)-4); - $last++; - $last = strtoupper(base_convert($last, 10, 36)); - return $first_part.$this->getCodeSur4Chiffres($last,true); - } - - - public function findNextRacineCatalogue() { - $last_thesaurus = Class_CodifThesaurus::findFirstBy(['where' => 'code like "catalogue" and LENGTH(id_thesaurus) in (1,8)', - 'order' => 'id_thesaurus desc']); - - return $last_thesaurus - ? $this->incrementId($last_thesaurus->getIdThesaurus()) - : Class_CodifThesaurus::fixedIdOf('Domain') . '0001'; - } - - - public function deleteAllWithIdOrigineAndCode($id_origine, $code_thesaurus) { - foreach (Class_CodifThesaurus::findAllBy(['id_origine' => $id_origine, - 'code' => $code_thesaurus ]) - as $thesaurus) - Class_CodifThesaurus::deleteAllFrom($thesaurus); - } - - - public function deleteAllFrom($thesaurus) { - if ($thesaurus && '' != $thesaurus->getIdThesaurus()) - $this->basicDeleteBy([Class_CodifThesaurus::clauseStart('id_thesaurus', - $thesaurus->getIdThesaurus())]); - } - - - public function deleteFacetsInRecordsForThesaurusTree(Class_CodifThesaurus $thesaurus, string $where='') : int { - return $this->_deleteFacetsInRecordsByPattern('\\\\b' . $thesaurus->getFacetCode() . '\\\\d*\\\\b', - $where); - } - - - public function deleteFacetsInRecordsForThesaurus(Class_CodifThesaurus $thesaurus, string $where='') : int { - return $this->_deleteFacetsInRecordsByPattern('\\\\b' . $thesaurus->getFacetCode() . '\\\\b', - $where); - } - - - protected function _deleteFacetsInRecordsByPattern(string $pattern, string $where='') : int { - return Class_Notice::deleteFacetsInRecordsByPattern($pattern, $where); - } - - - /** - * @param int - * $return Class_CodifThesaurus - */ - public function findByIdOrigineAndCode($id_origine, $code_thesaurus) { - return Class_CodifThesaurus::findFirstBy(['id_origine' => $id_origine, - 'code' => $code_thesaurus ]); - } - - - public static function getCodeSur4Chiffres($code,$before=false) { - $length=strlen($code); - while (strlen($code) %4 != 0) { - if ($before) - $code = '0'.$code; - else - $code .='0'; - } - return $code; - } - - - public function getIndices($pere, $all = false ) { - if (Class_CodifThesaurus::CODE_ROOT != $pere) { - $pere = $this->getCodeSur4Chiffres($pere); - $length = strlen($pere); - - return Class_CodifThesaurus::findAllBy(['where' => 'id_thesaurus like "'.$pere.'%" and LENGTH(id_thesaurus) in ('.($length+1).','.($length+4).')', - 'order'=> 'id_thesaurus']); - } - - // while search result do not handle item novelty correctly - $to_exclude = [$this->fixedIdOf('LibraryNovelty'), - $this->fixedIdOf('AnnexeNovelty')]; - if (!$all) - $to_exclude[] = $this->fixedIdOf('Domain'); - - return $this->_findAllFromRootExcluding($to_exclude); - } - - - public function findAllForDomainCriteria() { - // novelty is a criteria in itself - // and no domains in domains - - $exclude = [$this->fixedIdOf('RecordNovelty'), - $this->fixedIdOf('LibraryNovelty'), - $this->fixedIdOf('AnnexeNovelty'), - $this->fixedIdOf('Domain'), - ...array_map(fn($thesaurus) => $thesaurus->getIdThesaurus(), - $this->findDomainFacets())]; - return $this - ->_findAllFromRootExcluding($exclude); - } - - - protected function _findAllFromRootExcluding($to_exclude=[]) { - return Class_CodifThesaurus::findAllBy(['where' => sprintf('LENGTH(id_thesaurus) in (1,%d)', - Class_CodifThesaurus::ID_KEY_LENGTH), - 'id_origine' => null, - 'id_thesaurus not' => $to_exclude, - 'order' => 'id_thesaurus']); - } - - - public function getIndicesRoot() { - return $this->getIndices(Class_CodifThesaurus::CODE_ROOT); - } - - - public function fixedCodeOf($name) { - return isset($this->_fixed[$name]) ? $this->_fixed[$name]->getCode() : ''; - } - - - public function fixedIdOf($name) { - return isset($this->_fixed[$name]) ? $this->_fixed[$name]->getId() : ''; - } - - - public function fixedLabelOf($name) { - return isset($this->_fixed[$name]) ? $this->_fixed[$name]->getLabel() : ''; - } - - - public function getFacettesIndex() { - return array_map(function($item) { return $item->getFacetteIndex(); }, - Class_CodifThesaurus::getFacettesThesauri()); - } - - - public function getFacettesThesauri() { - $filter = function($item) { - return Class_CodifThesaurus::fixedIdOf('CustomField') != $item->getIdThesaurus(); - }; - - $thesauri = array_filter(Class_CodifThesaurus::getIndices(Class_CodifThesaurus::CODE_ROOT, true), $filter); - - foreach(Class_CodifThesaurus::findCustomFieldsRoot()->getChildren() as $item) - $thesauri[] = $item; - - return $thesauri; - } - - - public function findDomainFacets() : array { - return Class_CodifThesaurus::findAllBy(['code' => Class_CodifThesaurusFixed::CODE_DOMAIN_FACET, - Class_CodifThesaurus::clauseGreater('rules', - '')]); - } - - - public function findChildrenOf($parent) { - if (!$parent || !$id_thesaurus = $parent->getIdThesaurus()) - return []; - - $where = sprintf('id_thesaurus like "%s%%" and LENGTH(id_thesaurus) = %s', - $id_thesaurus, strlen($id_thesaurus) + 4); - - return Class_CodifThesaurus::findAllBy(['where' => $where, - 'order' => 'libelle']); - } - - - public function getFacetGroup($facet) { - return substr($facet, 0, $this->isCustomFieldsFacet($facet) ? 9 : 5); - } - - - public function getMultiOptionsFrom($facet) { - $items = ['' => $this->_('tous')]; - if (!$root = Class_CodifThesaurus::findFirstBy(['id_thesaurus' => substr($facet, 1)])) - return $items; - - foreach($root->getChildrenItems() as $child) - $items[$child->getIdThesaurus()] = $child->getLibelleFacette(); - - return $items; - } - - - protected function isCustomFieldsFacet($facet) { - return $this->startsWith($facet, $this->getCustomFieldsFacetPrefix()); - } - - - protected function startsWith($value, $prefix) { - return $prefix == substr($value, 0, strlen($prefix)); - } - - - protected function getCustomFieldsFacetPrefix() { - if (!isset($this->_customfields_facet_prefix)) - return $this->_customfields_facet_prefix = Class_CodifThesaurus::CODE_FACETTE . Class_CodifThesaurus::fixedIdOf('CustomField'); - return $this->_customfields_facet_prefix; - } - - - public function suggestFrom($recherche, $mode, $limite_resultat, $theme) { - if (!$req = $this->_suggestQueryFor((int)$mode, $theme, $recherche, $limite_resultat)) - return []; - - $resultat=fetchAll($req); - - if (!$resultat) - return []; - - foreach($resultat as $enreg) { - $thesaurus = Class_CodifThesaurus::find($enreg["id"]); - $libelle = Class_CodifThesaurus::getLibelleHierarchique($thesaurus); - $liste[] = [$enreg["id_thesaurus"], - $enreg["id_origine"]." : ".$libelle]; - } - - return $liste; - } - - - protected function _suggestQueryFor($mode, $parent, $term, $limit) { - $parent_clause = $this->_fieldStartsWith('id_thesaurus', $parent); - - if (Class_CodifThesaurus::SUGGEST_HIERARCHY_CONTAINS == $mode) { - return (3 <= strlen($term)) - ? $this->_orderAndLimit("select distinct(id), id, id_thesaurus, id_origine " - ."from codif_thesaurus where id_thesaurus regexp (select group_concat(concat(id_thesaurus,'.*') separator '|') from codif_thesaurus where ". $parent_clause ." and id_origine is not null and " . $this->_fieldContains('libelle', $term) . ")", - $limit) - : null; - } - - $basic_select = "select id, id_thesaurus, id_origine from codif_thesaurus where ". $parent_clause; - if (Class_CodifThesaurus::SUGGEST_LABEL_STARTS_WITH == $mode) - return $this->_orderAndLimit($basic_select . ' and ' . $this->_fieldStartsWith('libelle', $term), - $limit); - - if (Class_CodifThesaurus::SUGGEST_LABEL_CONTAINS == $mode) - return $this->_orderAndLimit($basic_select . ' and ' . $this->_fieldContains('libelle', $term), - $limit); - - if (Class_CodifThesaurus::SUGGEST_INDEX_STARTS_WITH == $mode) - return $this->_orderAndLimit($basic_select . ' and ' . $this->_fieldStartsWith('id_origine', $term), - $limit); - } - - - protected function _orderAndLimit($sql, $limit) { - return $sql . ' order by id_thesaurus limit ' . $limit; - } - - - protected function _fieldStartsWith($field, $value) { - return $this->_like($field, addslashes($value) . '%'); - } - - - protected function _fieldContains($field, $value) { - return $this->_like($field, '%' . addslashes($value) . '%'); - } - - - protected function _like($field, $clause) { - return $field . ' like \''. $clause . '\''; - } - - - public function findAllDynamicFacets() { - if (isset($this->_all_by_dynamic_facets)) - return $this->_all_by_dynamic_facets; - - return $this->_all_by_dynamic_facets = Class_CodifThesaurus::findAllBy(['rules not' => null, - 'code not' => null, - 'id_thesaurus not' => null]); - } - - - public function getDynamicCodes() { - $params = []; - foreach(Class_CodifThesaurus::findAllDynamicFacets() as $facet) - $params [] = $facet->getCode(); - - return array_unique($params); - } - - - public function root() { - return Class_CodifThesaurus::newInstance(); - } - - - public function newIdThesaurusForLabel($label) { - $id = substr(strtoupper($label), 0, Class_CodifThesaurus::ID_KEY_LENGTH); - - if (strlen($id) == Class_CodifThesaurus::ID_KEY_LENGTH - && !Class_CodifThesaurus::findFirstBy(['id_thesaurus' => $id])) - return $id; - - $label = substr(strtoupper($label), 0, 3); - $suffixes = array_merge(range(0, 9), range('a', 'z')); - - while(!empty($suffixes)) { - $suffix = strtoupper(array_shift($suffixes)); - $id = sprintf("%'".$suffix."-4s", $label); - - if (!Class_CodifThesaurus::findFirstBy(['id_thesaurus' => $id])) - return $id; - } - } - - - public function withDynamicFacetsHavingIdFieldDo($closure) { - (new Storm_Model_Collection(Class_CodifThesaurus::findAllBy(['rules not' => null, - 'rules not' => '', - 'id_thesaurus not' => null, - 'order' => 'libelle']))) - ->select('hasRuleListIdField') - ->eachDo($closure); - } - - - public function getListeSuggestion($recherche, $mode, $limite_resultat, $theme) { - return $this->suggestFrom($recherche, $mode, $limite_resultat, $theme); - } -} @@ -607,7 +40,7 @@ class Class_CodifThesaurus extends Storm_Model_Abstract { CODE_FACETTE = 'H'; - protected $_loader_class = 'CodifThesaurusLoader'; + protected $_loader_class = 'Class_CodifThesaurus_Loader'; protected $_table_name = 'codif_thesaurus'; protected $_table_primary = 'id'; protected $_default_attribute_values = ['libelle' => '', diff --git a/library/Class/CodifThesaurus/Loader.php b/library/Class/CodifThesaurus/Loader.php new file mode 100644 index 00000000000..758faf95c89 --- /dev/null +++ b/library/Class/CodifThesaurus/Loader.php @@ -0,0 +1,608 @@ +<?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_CodifThesaurus_Loader extends Storm_Model_Loader { + use Trait_Translator; + + const WORD_BOUNDARY = '\\\\b'; + + protected + $_fixed = [], + $_customfields_facet_prefix, + $_all_by_dynamic_facets; + + public function __construct($class) { + parent::__construct($class); + $this->_fixed = Class_CodifThesaurusFixed::getAll(); + } + + + public function findFixed($key) { + return isset($this->_fixed[$key]) + ? $this->_fixed[$key] + : null; + } + + + public function findThesaurusForCatalogue($catalogue_id) { + return Class_CodifThesaurus::getLoader() + ->findFirstBy(['id_origine'=> $catalogue_id, + 'code' => Class_CodifThesaurus::fixedCodeOf('Domain')]); + } + + + public function collectForModelsUnderFixed($fixed_name, $models, $closure) { + if (!isset($this->_fixed[$fixed_name])) + return; + + foreach($models as $model) + $closure($this->ensureForModelUnderRoot($model, $this->_fixed[$fixed_name])); + } + + + public function findLibraryNoveltyFor($library_id) { + return ($library = Class_Bib::find((int)$library_id)) + ? $this->_ensureLibraryNoveltyThesaurus($library) + : null; + } + + + public function ensureRecordNovelty() { + $this->recordNoveltyFor(true); + $this->recordNoveltyFor(false); + } + + + /** @param $flag boolean */ + public function recordNoveltyFor($flag) { + $attributes = ((bool) $flag) + ? ['Id' => 1, 'Libelle' => $this->_('Oui')] + : ['Id' => 2, 'Libelle' => $this->_('Non')]; + + return $this->ensureForModelUnderRoot(new Class_Entity($attributes), + $this->_fixed['RecordNovelty']); + } + + + public function ensureForModelUnderRoot($model, Class_CodifThesaurusFixed $definition) { + return ($root = $definition->getThesaurus()) + ? $root->getOrCreateChild($model->getId(), $model->getLibelle()) + : null; + } + + + protected function _ensureLibraryNoveltyThesaurus($model) { + return $this->ensureForModelUnderRoot($model, $this->_fixed['LibraryNovelty']); + } + + + protected function _ensureAnnexeNoveltyThesaurus($model) { + return $this->ensureForModelUnderRoot($model, $this->_fixed['AnnexeNovelty']); + } + + + public function findForCustomField($field) { + return Class_CodifThesaurus::findForCustomFieldMeta($field->getMeta()); + } + + + public function getOrCreateForCustomField($field) { + return Class_CodifThesaurus::getOrCreateForCustomFieldMeta($field->getMeta()); + } + + + public function findForCustomFieldMeta($meta) { + return Class_CodifThesaurus::getLoader() + ->findFirstBy(['id_origine' => $meta->getId(), + 'code' => Class_CodifThesaurus::fixedCodeOf('CustomField')]); + } + + + public function getOrCreateForCustomFieldMeta($meta) { + return Class_CodifThesaurus::findCustomFieldsRoot() + ->getOrCreateChild($meta->getId(), $meta->getLabel()); + } + + + public function findCustomFieldsRoot() { + $definition = $this->_fixed['CustomField']; + return Class_CodifThesaurus::findRootOfId($definition->getId(), + $definition->getCode(), + $definition->getLabel()); + } + + + public function findForItemLibraryNovelty($item) { + if(!$library = $item->getBib()) + return null; + + return ($item = $this->ensureForModelUnderRoot($library, $this->_fixed['LibraryNovelty'])) + ? $item->getFacetteIndex() + : ''; + } + + + public function findForItemAnnexeNovelty($item) { + if(!$model = $item->getCodifAnnexe()) + return null; + + return ($item = $this->ensureForModelUnderRoot($model, $this->_fixed['AnnexeNovelty'])) + ? $item->getFacetteIndex() + : ''; + } + + + public function countChildrenOf($id_thesaurus) { + $where = sprintf('id_thesaurus like "%s%%" and LENGTH(id_thesaurus) > %s', + $id_thesaurus, + strlen($id_thesaurus)); + + return Class_CodifThesaurus::countBy(['where' => $where]); + } + + + public function findChildrenOfWith($id_thesaurus, $limit, $order) { + $where = sprintf('id_thesaurus like "%s%%" and LENGTH(id_thesaurus) = %s', + $id_thesaurus, + (strlen($id_thesaurus) + 4)); + + return Class_CodifThesaurus::findAllBy(['where' => $where, + 'limitPage' => $limit, + 'order' => $order]); + } + + + public function findRootOfId($id, $code, $label) { + if ($codif = Class_CodifThesaurus::findFirstBy(['id_thesaurus' => $id])) + return $codif; + + $attributes = ['id_thesaurus' => $id, + 'libelle' => $label, + 'code' => $code]; + + $codif = Class_CodifThesaurus::newInstance($attributes); + + return $codif->save() ? $codif : null; + } + + + public function addFacetForSigb($facet_name, $facet_rules, $comm_sigb) { + if (!Class_IntBib::findFirstBy(['comm_sigb' => $comm_sigb])) + return; + + $parts = explode('$', trim($facet_rules)); + if (2 !== count($parts)) + return; + + $zone = $parts[0]; + $label_field = $parts[1]; + + $list_rules = (new Class_CodifThesaurus_ListRules()) + ->setListZone([$zone]) + ->setListLabelField([$label_field]); + + if (Class_CodifThesaurus::findFirstBy(['rules' => $list_rules->format()])) + return ; + + Class_CodifThesaurus::newInstance(['libelle' => $facet_name, + 'libelle_facette' => $facet_name, + 'rule_list_zone' => [$zone], + 'rule_list_label_field' => [$label_field]]) + ->save(); + } + + + public function getLibelleHierarchique($enreg) { + if (!$enreg) + return ''; + + if (!$parent = Class_CodifThesaurus::findParent($enreg->getIdThesaurus())) + return $enreg->getLibelle(); + + if (strlen($parent->getIdThesaurus()) <= 8) + return $parent->getLibelle() . ' : ' . $enreg->getLibelle(); + + return $this->getLibelleHierarchique($parent) . ' : ' . $enreg->getLibelle(); + } + + + public function findParent($id_thesaurus) { + $parent_str = substr($id_thesaurus, + 0, + strlen($id_thesaurus) - Class_CodifThesaurus::ID_KEY_LENGTH); + if (!$parent_str) + return null; + + $parent = Class_CodifThesaurus::findFirstBy(['id_thesaurus' => $parent_str]); + if (!$parent) + return $this->findParent($parent_str); + + return $parent; + } + + + /** @return string */ + public function findNextThesaurusChildId($code, $parentid_thesaurus) { + Class_CodifThesaurus::clearCache(); + $last_thesaurus = Class_CodifThesaurus::findFirstBy(['code' => $code, + Class_CodifThesaurus::clauseStart('id_thesaurus', $parentid_thesaurus), + 'order' => 'id_thesaurus desc']); + if (!$last_thesaurus) + return $parentid_thesaurus.'0001'; + + if (strlen($parentid_thesaurus) >=strlen($last_thesaurus->getIdThesaurus())) + return $parentid_thesaurus.'0001'; + + return $this->incrementId(substr($last_thesaurus->getIdThesaurus(),0, strlen($parentid_thesaurus)+4)) ; + } + + + public function incrementId($id) { + $last=base_convert(substr($id,strlen($id)-4), 36, 10); + $first_part=substr($id,0,strlen($id)-4); + $last++; + $last = strtoupper(base_convert($last, 10, 36)); + return $first_part.$this->getCodeSur4Chiffres($last,true); + } + + + public function findNextRacineCatalogue() { + $last_thesaurus = Class_CodifThesaurus::findFirstBy(['where' => 'code like "catalogue" and LENGTH(id_thesaurus) in (1,8)', + 'order' => 'id_thesaurus desc']); + + return $last_thesaurus + ? $this->incrementId($last_thesaurus->getIdThesaurus()) + : Class_CodifThesaurus::fixedIdOf('Domain') . '0001'; + } + + + public function deleteAllWithIdOrigineAndCode($id_origine, $code_thesaurus) { + foreach (Class_CodifThesaurus::findAllBy(['id_origine' => $id_origine, + 'code' => $code_thesaurus ]) + as $thesaurus) + Class_CodifThesaurus::deleteAllFrom($thesaurus); + } + + + public function deleteAllFrom($thesaurus) { + if ($thesaurus && '' != $thesaurus->getIdThesaurus()) + $this->basicDeleteBy([Class_CodifThesaurus::clauseStart('id_thesaurus', + $thesaurus->getIdThesaurus())]); + } + + + public function deleteFacetsInRecordsForThesaurusTree(Class_CodifThesaurus $thesaurus, string $where='') : int { + return $this->_deleteFacetsInRecordsByPattern(static::WORD_BOUNDARY . $thesaurus->getFacetCode() . '\\\\d*' . static::WORD_BOUNDARY, + $where); + } + + + public function deleteFacetsInRecordsForThesaurus(Class_CodifThesaurus $thesaurus, string $where='') : int { + return $this->_deleteFacetsInRecordsByPattern(static::WORD_BOUNDARY . $thesaurus->getFacetCode() . static::WORD_BOUNDARY, + $where); + } + + + protected function _deleteFacetsInRecordsByPattern(string $pattern, string $where='') : int { + return Class_Notice::deleteFacetsInRecordsByPattern($pattern, $where); + } + + + /** + * @param int + * $return Class_CodifThesaurus + */ + public function findByIdOrigineAndCode($id_origine, $code_thesaurus) { + return Class_CodifThesaurus::findFirstBy(['id_origine' => $id_origine, + 'code' => $code_thesaurus ]); + } + + + public static function getCodeSur4Chiffres($code,$before=false) { + $length=strlen($code); + while (strlen($code) %4 != 0) { + if ($before) + $code = '0'.$code; + else + $code .='0'; + } + return $code; + } + + + public function getIndices($pere, $all = false ) { + if (Class_CodifThesaurus::CODE_ROOT != $pere) { + $pere = $this->getCodeSur4Chiffres($pere); + $length = strlen($pere); + + return Class_CodifThesaurus::findAllBy(['where' => 'id_thesaurus like "'.$pere.'%" and LENGTH(id_thesaurus) in ('.($length+1).','.($length+4).')', + 'order'=> 'id_thesaurus']); + } + + // while search result do not handle item novelty correctly + $to_exclude = [$this->fixedIdOf('LibraryNovelty'), + $this->fixedIdOf('AnnexeNovelty')]; + if (!$all) + $to_exclude[] = $this->fixedIdOf('Domain'); + + return $this->_findAllFromRootExcluding($to_exclude); + } + + + public function findAllForDomainCriteria() { + // novelty is a criteria in itself + // and no domains in domains + + $exclude = [$this->fixedIdOf('RecordNovelty'), + $this->fixedIdOf('LibraryNovelty'), + $this->fixedIdOf('AnnexeNovelty'), + $this->fixedIdOf('Domain'), + ...array_map(fn($thesaurus) => $thesaurus->getIdThesaurus(), + $this->findDomainFacets())]; + return $this + ->_findAllFromRootExcluding($exclude); + } + + + protected function _findAllFromRootExcluding($to_exclude=[]) { + return Class_CodifThesaurus::findAllBy(['where' => sprintf('LENGTH(id_thesaurus) in (1,%d)', + Class_CodifThesaurus::ID_KEY_LENGTH), + 'id_origine' => null, + 'id_thesaurus not' => $to_exclude, + 'order' => 'id_thesaurus']); + } + + + public function getIndicesRoot() { + return $this->getIndices(Class_CodifThesaurus::CODE_ROOT); + } + + + public function fixedCodeOf($name) { + return isset($this->_fixed[$name]) ? $this->_fixed[$name]->getCode() : ''; + } + + + public function fixedIdOf($name) { + return isset($this->_fixed[$name]) ? $this->_fixed[$name]->getId() : ''; + } + + + public function fixedLabelOf($name) { + return isset($this->_fixed[$name]) ? $this->_fixed[$name]->getLabel() : ''; + } + + + public function getFacettesIndex() { + return array_map(function($item) { return $item->getFacetteIndex(); }, + Class_CodifThesaurus::getFacettesThesauri()); + } + + + public function getFacettesThesauri() { + $filter = function($item) { + return Class_CodifThesaurus::fixedIdOf('CustomField') != $item->getIdThesaurus(); + }; + + $thesauri = array_filter(Class_CodifThesaurus::getIndices(Class_CodifThesaurus::CODE_ROOT, true), $filter); + + foreach(Class_CodifThesaurus::findCustomFieldsRoot()->getChildren() as $item) + $thesauri[] = $item; + + return $thesauri; + } + + + public function findDomainFacets() : array { + return Class_CodifThesaurus::findAllBy(['code' => Class_CodifThesaurusFixed::CODE_DOMAIN_FACET, + Class_CodifThesaurus::clauseGreater('rules', + '')]); + } + + + public function findChildrenOf($parent) { + if (!$parent || !$id_thesaurus = $parent->getIdThesaurus()) + return []; + + $where = sprintf('id_thesaurus like "%s%%" and LENGTH(id_thesaurus) = %s', + $id_thesaurus, strlen($id_thesaurus) + 4); + + return Class_CodifThesaurus::findAllBy(['where' => $where, + 'order' => 'libelle']); + } + + + public function getFacetGroup($facet) { + return substr($facet, 0, $this->isCustomFieldsFacet($facet) ? 9 : 5); + } + + + public function getMultiOptionsFrom($facet) { + $items = ['' => $this->_('tous')]; + if (!$root = Class_CodifThesaurus::findFirstBy(['id_thesaurus' => substr($facet, 1)])) + return $items; + + foreach($root->getChildrenItems() as $child) + $items[$child->getIdThesaurus()] = $child->getLibelleFacette(); + + return $items; + } + + + protected function isCustomFieldsFacet($facet) { + return $this->startsWith($facet, $this->getCustomFieldsFacetPrefix()); + } + + + protected function startsWith($value, $prefix) { + return $prefix == substr($value, 0, strlen($prefix)); + } + + + protected function getCustomFieldsFacetPrefix() { + if (!isset($this->_customfields_facet_prefix)) + return $this->_customfields_facet_prefix = Class_CodifThesaurus::CODE_FACETTE . Class_CodifThesaurus::fixedIdOf('CustomField'); + return $this->_customfields_facet_prefix; + } + + + public function suggestFrom($recherche, $mode, $limite_resultat, $theme) { + if (!$req = $this->_suggestQueryFor((int)$mode, $theme, $recherche, $limite_resultat)) + return []; + + $resultat=fetchAll($req); + + if (!$resultat) + return []; + + foreach($resultat as $enreg) { + $thesaurus = Class_CodifThesaurus::find($enreg["id"]); + $libelle = Class_CodifThesaurus::getLibelleHierarchique($thesaurus); + $liste[] = [$enreg["id_thesaurus"], + $enreg["id_origine"]." : ".$libelle]; + } + + return $liste; + } + + + protected function _suggestQueryFor($mode, $parent, $term, $limit) { + $parent_clause = $this->_fieldStartsWith('id_thesaurus', $parent); + + if (Class_CodifThesaurus::SUGGEST_HIERARCHY_CONTAINS == $mode) { + return (3 <= strlen($term)) + ? $this->_orderAndLimit("select distinct(id), id, id_thesaurus, id_origine " + ."from codif_thesaurus where id_thesaurus regexp (select group_concat(concat(id_thesaurus,'.*') separator '|') from codif_thesaurus where ". $parent_clause ." and id_origine is not null and " . $this->_fieldContains('libelle', $term) . ")", + $limit) + : null; + } + + $basic_select = "select id, id_thesaurus, id_origine from codif_thesaurus where ". $parent_clause; + if (Class_CodifThesaurus::SUGGEST_LABEL_STARTS_WITH == $mode) + return $this->_orderAndLimit($basic_select . ' and ' . $this->_fieldStartsWith('libelle', $term), + $limit); + + if (Class_CodifThesaurus::SUGGEST_LABEL_CONTAINS == $mode) + return $this->_orderAndLimit($basic_select . ' and ' . $this->_fieldContains('libelle', $term), + $limit); + + if (Class_CodifThesaurus::SUGGEST_INDEX_STARTS_WITH == $mode) + return $this->_orderAndLimit($basic_select . ' and ' . $this->_fieldStartsWith('id_origine', $term), + $limit); + } + + + protected function _orderAndLimit($sql, $limit) { + return $sql . ' order by id_thesaurus limit ' . $limit; + } + + + protected function _fieldStartsWith($field, $value) { + return $this->_like($field, addslashes($value) . '%'); + } + + + protected function _fieldContains($field, $value) { + return $this->_like($field, '%' . addslashes($value) . '%'); + } + + + protected function _like($field, $clause) { + return $field . ' like \''. $clause . '\''; + } + + + public function findAllDynamicFacets() { + if (isset($this->_all_by_dynamic_facets)) + return $this->_all_by_dynamic_facets; + + return $this->_all_by_dynamic_facets = Class_CodifThesaurus::findAllBy(['rules not' => null, + 'code not' => null, + 'id_thesaurus not' => null]); + } + + + public function getDynamicCodes() { + $params = []; + foreach(Class_CodifThesaurus::findAllDynamicFacets() as $facet) + $params [] = $facet->getCode(); + + return array_unique($params); + } + + + public function root() { + return Class_CodifThesaurus::newInstance(); + } + + + public function newIdThesaurusForLabel($label) { + $id = substr(strtoupper($label), 0, Class_CodifThesaurus::ID_KEY_LENGTH); + + if (strlen($id) == Class_CodifThesaurus::ID_KEY_LENGTH + && !Class_CodifThesaurus::findFirstBy(['id_thesaurus' => $id])) + return $id; + + $label = substr(strtoupper($label), 0, 3); + $suffixes = array_merge(range(0, 9), range('a', 'z')); + + while(!empty($suffixes)) { + $suffix = strtoupper(array_shift($suffixes)); + $id = sprintf("%'".$suffix."-4s", $label); + + if (!Class_CodifThesaurus::findFirstBy(['id_thesaurus' => $id])) + return $id; + } + } + + + public function withDynamicFacetsHavingIdFieldDo($closure) { + (new Storm_Model_Collection(Class_CodifThesaurus::findAllBy(['rules not' => null, + 'rules not' => '', + 'id_thesaurus not' => null, + 'order' => 'libelle']))) + ->select('hasRuleListIdField') + ->eachDo($closure); + } + + + public function getListeSuggestion($recherche, $mode, $limite_resultat, $theme) { + return $this->suggestFrom($recherche, $mode, $limite_resultat, $theme); + } + + + public function findAllIdsForDomainsIds(array $domain_ids) : array { + $query = 'select id_thesaurus from codif_thesaurus where id_thesaurus like "' . $this->fixedIdOf('Domain') . '%" and length(id_thesaurus)=8 and id_origine in (' + . implode(', ', + array_map(fn($id) => '"' . $id . '"', + $domain_ids)) + . ')'; + + return Zend_Registry::get('sql')->fetchAllByColumn($query); + } + + + public function findAllFacetsForDomainsIds(array $domain_ids) : array { + return array_map(fn($id) => Class_CodifThesaurus::CODE_FACETTE . $id, + $this->findAllIdsForDomainsIds($domain_ids)); + } +} diff --git a/library/Class/Cosmogramme/Integration/PhaseDomains.php b/library/Class/Cosmogramme/Integration/PhaseDomains.php index d04b64cb264..ac306656ccf 100644 --- a/library/Class/Cosmogramme/Integration/PhaseDomains.php +++ b/library/Class/Cosmogramme/Integration/PhaseDomains.php @@ -63,9 +63,7 @@ class Class_Cosmogramme_Integration_PhaseDomains foreach (Class_Catalogue::findAllCataloguesAIndexer() as $domain) $this->_runOneDomain($domain); - $this->_summarize(); - - return $this; + return $this->_summarize(); } @@ -122,41 +120,36 @@ class Class_Cosmogramme_Integration_PhaseDomains $clear_count = Class_NoticeDomain::clearNotPseudoRecordsWithPanier(); $this->_logInfo($this->_plural($clear_count, - 'Aucun lien notice/domaine à supprimer', - '1 lien notice/domaine supprimé', - '%d liens notice/domaine supprimés', + 'Aucune liaison par panier à supprimer', + 'Une liaison par panier supprimée', + '%d liaisons par panier supprimées', $clear_count)); $clear_count = Class_Catalogue::clearDomainFacets(); $this->_logInfo($this->_plural($clear_count, - 'Aucune notices à désindexer', - '1 notice désindexée', - '%d notices désindexées', + 'Aucune notices à délier des domaines', + 'Une a été déliée des domaines', + '%d notices ont été déliées des domaines', $clear_count)); $this->_indexed_count = 0; foreach (Class_PanierNotice::findAllWithCatalogue() as $panier) $this->_runOnePanier($panier); - $this->_summarize(); - - return $this; + return $this->_summarize(); } protected function _runOnePanier(Class_PanierNotice $panier) : self { $this->_logInfo($this->_('Indexation du panier : %s', $panier->getLibelle())); - if (!$linked_domains = $panier->rawLinkedDomains()) { - $this->_logError($this->_('Impossible d\'indexer un panier qui n\'est pas rattaché à au moins un domaine')); - return $this; - } - if (!$keys = $panier->getClesNotices()) { $this->_logInfo($this->_('Inutile d\'indexer un panier vide')); return $this; } + $linked_domains = $panier->rawLinkedDomains(); + $domains_id = array_map(fn($row) => $row['id_catalogue'], $linked_domains); @@ -170,9 +163,9 @@ class Class_Cosmogramme_Integration_PhaseDomains $inserted_count = Class_NoticeDomain::createAllForPanier($panier, $domains_id, $keys); $this->_logInfo($this->_plural($inserted_count, - 'Aucun lien notice/domaine créé', - '1 lien notice/domaine créé', - '%d liens notice/domaine créés', + 'Aucune liaison par panier créée', + 'Une liaison par panier créée', + '%d liaisons par panier créées', $inserted_count)); return $this; @@ -197,9 +190,9 @@ class Class_Cosmogramme_Integration_PhaseDomains $where)); $this->_logInfo($this->_plural($indexed_count, - 'Aucune notices à indexer', - '1 notice indexée', - '%d notices indexées', + 'Aucune notice à lier aux domaines', + 'Une notice a été liée aux domaines', + '%d notices ont été liées aux domaines', $indexed_count)); $this->_indexed_count += $indexed_count; @@ -215,17 +208,10 @@ class Class_Cosmogramme_Integration_PhaseDomains if (!$with_thesaurus) return $facets; - $query = 'select id_thesaurus from codif_thesaurus where id_thesaurus like "CCCC%" and length(id_thesaurus)=8 and id_origine in (' - . implode(', ', - array_map(fn($id) => '"' . $id . '"', - $with_thesaurus)) - . ')'; - - if (!$ids = Zend_Registry::get('sql')->fetchAllByColumn($query)) + if (!$thesaurus_facets = Class_CodifThesaurus::findAllFacetsForDomainsIds($with_thesaurus)) return $facets; - $facets->addAll(array_map(fn($id) => Class_CodifThesaurus::CODE_FACETTE.$id, - $ids)); + $facets->addAll($thesaurus_facets); return $facets; } diff --git a/library/Class/Notice/Loader.php b/library/Class/Notice/Loader.php index e547a615a9c..d13e24b4172 100644 --- a/library/Class/Notice/Loader.php +++ b/library/Class/Notice/Loader.php @@ -210,12 +210,9 @@ class Class_Notice_Loader extends Storm_Model_Loader { } - public function pseudoRecordsTypes(?Closure $callback=null) : string { - if (null === $callback) - $callback = fn($type) => '"' . $type. '"'; - + public function pseudoRecordsTypes(string $prefix='', string $suffix='') : string { return implode(', ', - array_map($callback, + array_map(fn($type) => '"' . $prefix . $type . $suffix . '"', [Class_TypeDoc::ARTICLE, Class_TypeDoc::RSS, Class_TypeDoc::SITE])); diff --git a/library/Class/NoticeDomain.php b/library/Class/NoticeDomain.php index df240abedc3..9dae9c927c4 100644 --- a/library/Class/NoticeDomain.php +++ b/library/Class/NoticeDomain.php @@ -111,7 +111,7 @@ class NoticeDomainLoader extends Storm_Model_Loader { * @see Class_Indexation_PseudoNotice::_getFacettes() */ public function clearNotPseudoRecordsWithPanier() : int { - $pseudo_records_key_ends = Class_Notice::pseudoRecordsTypes(fn($type) => '"-'. $type .'"'); + $pseudo_records_key_ends = Class_Notice::pseudoRecordsTypes('-'); $where = 'panier_id != 0' . ' and substring(record_alpha_key, -2) not in ('. $pseudo_records_key_ends .')'; diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseDomainsTest.php b/tests/library/Class/Cosmogramme/Integration/PhaseDomainsTest.php index 0b5401f09ae..af1d01578ed 100644 --- a/tests/library/Class/Cosmogramme/Integration/PhaseDomainsTest.php +++ b/tests/library/Class/Cosmogramme/Integration/PhaseDomainsTest.php @@ -159,14 +159,14 @@ class PhaseDomainsCronTest extends PhaseDomainsTestCase { /** @test */ - public function logShouldContains8LiensNoticeDomaineSupprimés() { - $this->assertLogContains('8 liens notice/domaine supprimés'); + public function logShouldContains8LiaisonsParPanierSupprimées() { + $this->assertLogContains('8 liaisons par panier supprimées'); } /** @test */ - public function logShouldContains5NoticesDésindexées() { - $this->assertLogContains('5 notices désindexées'); + public function logShouldContains5NoticesOntÉtéDéliées() { + $this->assertLogContains('5 notices ont été déliées des domaines'); } @@ -177,13 +177,13 @@ class PhaseDomainsCronTest extends PhaseDomainsTestCase { /** @test */ - public function logShouldContains2LiensNoticeDomaineCréés() { - $this->assertLogContains('2 liens notice/domaine créés'); + public function logShouldContains2LiaisonsParPanierCréées() { + $this->assertLogContains('2 liaisons par panier créées'); } /** @test */ - public function logShouldContains2NoticesIndexées() { - $this->assertLogContains('2 notices indexées'); + public function logShouldContains2NoticesOntÉtéLiéesAuxDomaines() { + $this->assertLogContains('2 notices ont été liées aux domaines'); } } -- GitLab