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