diff --git a/FEATURES/189214 b/FEATURES/189214
new file mode 100644
index 0000000000000000000000000000000000000000..404bda52862006344da70d2a10f1e165b5360741
--- /dev/null
+++ b/FEATURES/189214
@@ -0,0 +1,10 @@
+        '189214' =>
+            ['Label' => $this->_('Choix des bibliothèques gérées pour les modérateurs et administrateurs'),
+             'Desc' => $this->_('Les modérateurs et administrateurs bib ou portail se voient affecter une liste de bibliothèques qu\'ils peuvent gérer en fonction de leurs droits'),
+             'Image' => '',
+             'Video' => '',
+             'Category' => '',
+             'Right' => function($feature_description, $user) {return true;},
+             'Wiki' => '',
+             'Test' => '',
+             'Date' => '2024-05-02'],
\ No newline at end of file
diff --git a/FEATURES/203399 b/FEATURES/203399
new file mode 100644
index 0000000000000000000000000000000000000000..8fe8a5f10e5806550df91ebf440efcbba945151f
--- /dev/null
+++ b/FEATURES/203399
@@ -0,0 +1,10 @@
+        '203399' =>
+            ['Label' => $this->_('Filtrage bibliothèques à choix multiples pour les profils et les groupes utilisateur'),
+             'Desc' => '',
+             'Image' => '',
+             'Video' => '',
+             'Category' => '',
+             'Right' => function($feature_description, $user) {return true;},
+             'Wiki' => '',
+             'Test' => '',
+             'Date' => '2024-06-19'],
\ No newline at end of file
diff --git a/VERSIONS_WIP/189214 b/VERSIONS_WIP/189214
new file mode 100644
index 0000000000000000000000000000000000000000..6edc7067abe8b12d1094765f19631772eb5c0f5c
--- /dev/null
+++ b/VERSIONS_WIP/189214
@@ -0,0 +1 @@
+ - fonctionnalité #189214 : Choix des bibliothèques gérées pour les modérateurs et administrateurs
\ No newline at end of file
diff --git a/VERSIONS_WIP/203399 b/VERSIONS_WIP/203399
new file mode 100644
index 0000000000000000000000000000000000000000..f14f22db7086c893042bfbd107650da0d036a3e9
--- /dev/null
+++ b/VERSIONS_WIP/203399
@@ -0,0 +1 @@
+ - fonctionnalité #203399 : [Ariège] Filtrage bibliothèques à choix multiples pour les profils et les groupes utilisateur
\ No newline at end of file
diff --git a/application/modules/admin/controllers/BibController.php b/application/modules/admin/controllers/BibController.php
index 347169ee5cecd8fc2933342550d51b28d8d4bde3..18882a3e9454f8f94e34de9f2c2593821211f4eb 100644
--- a/application/modules/admin/controllers/BibController.php
+++ b/application/modules/admin/controllers/BibController.php
@@ -45,7 +45,7 @@ class Admin_BibController extends ZendAfi_Controller_Action {
 
     $user = Class_Users::getIdentity();
     $this->view->libraries = $user->isRoleLibraryLimited()
-      ? [$user->getBib()]
+      ? $user->managedLibraries()
       : Class_Bib::findAllByIdZone($this->id_zone);
   }
 
diff --git a/application/modules/admin/controllers/CatalogueController.php b/application/modules/admin/controllers/CatalogueController.php
index 496f97686f37d93409ab6de745f5fa4cb7c92cd2..e9f706a9e62b852680a2df1cfedbf80b82a275cd 100644
--- a/application/modules/admin/controllers/CatalogueController.php
+++ b/application/modules/admin/controllers/CatalogueController.php
@@ -109,6 +109,9 @@ class Admin_CatalogueController extends ZendAfi_Controller_Action {
 
 
   public function addAction() {
+    if (!$this->_canAdd())
+      $this->_redirectClose($this->_getReferer());
+
     $catalogue = $this->_newCatalogue();
     $form = $this->_getForm($catalogue);
 
@@ -367,4 +370,23 @@ class Admin_CatalogueController extends ZendAfi_Controller_Action {
                           (new Class_Catalogue_TreeSelectJson())->render(),
                           (new Class_PanierNotice())->getPaniersAdminsNotInCatalogueJson()]);
   }
+
+
+  protected function _canAdd()
+  {
+    if ( ! ($id_bib = $this->_getParam('id_bib', null))
+         || ! ($library = Class_Bib::find($id_bib)))
+      return true;
+
+    if (!$logged_in = Class_Users::getIdentity())
+      return false;
+
+    if ($logged_in->isModoPortailOrMore()
+        || $logged_in->canManageLibrary($library))
+      return true;
+
+    $this->_helper->notify($this->_('Vous ne disposez pas des permissions suffisantes pour gérer la bibliothèque %s.',
+                                    $library->getLabel()));
+    return false;
+  }
 }
diff --git a/application/modules/admin/controllers/CmsController.php b/application/modules/admin/controllers/CmsController.php
index a8bed9aa334962eb9372d9ff669fddc0ac1c59fc..0a773e93d11563cfe5a9b47478a2062012d93446 100644
--- a/application/modules/admin/controllers/CmsController.php
+++ b/application/modules/admin/controllers/CmsController.php
@@ -41,10 +41,6 @@ class Admin_CmsController extends ZendAfi_Controller_Action {
 
   protected function _renderList() {
     $bibs = Class_Bib::findAllForCurrentUserAndPortal();
-    $current_library = (Class_Users::isCurrentUserCanAccessAllBibs())
-      ? null
-      : $this->identity->getBib();
-
     $ids = array_map(fn($model) => $model->getId(), $bibs);
 
     $search = $this->_getParam('title_search', '');
@@ -52,10 +48,12 @@ class Admin_CmsController extends ZendAfi_Controller_Action {
     $order = $this->_getParam('order', 'titre');
     $status = $this->_getParam(ZendAfi_Controller_Action_Helper_ListViewMode_Article::STATUS_SEARCH, '');
 
-    $id_bib = $this->_getParam('id_bib',
-                               ($current_library
-                                ? $current_library->getId()
-                                : null));
+    $id_bib = $this->_getParam('id_bib', null);
+
+    $current_library = 1 === count($bibs) ? array_shift($bibs) : null;
+    if ( ! $id_bib && $current_library)
+      $id_bib = $current_library->getId();
+
 
     $article = ($id_article = $this->_getParam('id', null))
       ? Class_Article::find($id_article)
diff --git a/application/modules/admin/controllers/ModulesController.php b/application/modules/admin/controllers/ModulesController.php
index eafcea23679b62535f475a539f9769225ffd705f..104ac585cd58b702d1dabad168093cf49be29f4b 100644
--- a/application/modules/admin/controllers/ModulesController.php
+++ b/application/modules/admin/controllers/ModulesController.php
@@ -60,7 +60,7 @@ class Admin_ModulesController extends ZendAfi_Controller_Action {
       ZendAfi_View_Helper_Accueil_Base::getComboTemplates($this->preferences['boite'],
                                                           $this->profil);
     $this->view->id_profil = $this->profil->getId();
-    $this->view->id_bib = $this->profil->getIdSite();
+    $this->view->id_bibs = $this->profil->getLibraryIds();
     $this->view->action = $this->_getParam('type_module').'_'.$this->_getParam('action1');
   }
 
diff --git a/application/modules/admin/controllers/ProfilController.php b/application/modules/admin/controllers/ProfilController.php
index 0337854cb579745c68076a07a82d8e822255d382..9e1ab4fba97571b4207495caf9a1d34d31e8883c 100644
--- a/application/modules/admin/controllers/ProfilController.php
+++ b/application/modules/admin/controllers/ProfilController.php
@@ -26,7 +26,6 @@ class Admin_ProfilController extends ZendAfi_Controller_Action {
   private $id_zone;         // Id zone sélectionnée (pour les combos de sélection)
   private $id_bib;          // Id bib sélectionnée (pour les combos de sélection)
 
-
   public function getPlugins() : array {
     $plugins = [ZendAfi_Controller_Plugin_Versionning_Profile::class];
     if ( ! Class_Template::current()->isLegacy())
@@ -58,14 +57,22 @@ class Admin_ProfilController extends ZendAfi_Controller_Action {
 
 
   public function indexAction() {
-    $user = ZendAfi_Auth::getInstance()->getIdentity();
+    $user = Class_Users::getIdentity();
     $profils = Class_Profil::findAllByZoneAndBib($this->id_zone,
                                                  $this->id_bib);
 
     $profils_by_bib = [];
     foreach ($profils as $profil) {
 
-      if ($profil->hasParentProfil() || $user->ROLE_LEVEL <= 5 && $user->ID_SITE != $profil->getIdSite()) continue;
+      if ($profil->hasParentProfil())
+        continue;
+
+      if ($user->isModo())
+        continue;
+
+      if ($user->isAdminBib()
+          && !$profil->hasOneOfManagedLibraries($user->managedLibraryIds()))
+        continue;
 
       $libelle = $profil->isInPortail() ? 'Portail' : $profil->getBibLibelle();
 
@@ -79,7 +86,7 @@ class Admin_ProfilController extends ZendAfi_Controller_Action {
 
     $this->view->titre = $this->_('Gestion des profils');
     $this->view->profils_by_bib = $profils_by_bib;
-    $this->view->can_add_profil = ($user->ROLE_LEVEL > 5);
+    $this->view->can_add_profil = ($user->getRoleLevel() > ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
   }
 
 
@@ -409,6 +416,9 @@ class Admin_ProfilController extends ZendAfi_Controller_Action {
   public function editAction() {
     $profil = Class_Profil::find($this->id_profil);
 
+    if (!$this->_canEdit($profil))
+      $this->_doOnCannotEdit($profil);
+
     $params = array_merge($profil->toArray(),
                           $profil->getCfgSiteAsArray());
 
@@ -495,4 +505,19 @@ class Admin_ProfilController extends ZendAfi_Controller_Action {
     $export = new Class_Profil_Export($this->_profil);
     $this->_response->setBody($export->toString());
   }
+
+
+  protected function _canEdit($profil): bool
+  {
+    return ($user = Class_Users::getIdentity()) && $user->isAdminBib()
+      ? $profil->hasOneOfManagedLibraries($user->managedLibraryIds())
+      : true;
+  }
+
+
+  protected function _doOnCannotEdit($profil) {
+    $this->_helper->notify($this->_('Vous n\'avez pas la permission pour le profil "%s"',
+                                    $profil->getLibelle()));
+    return $this->_redirectClose('/admin');
+  }
 }
diff --git a/application/modules/admin/views/scripts/users/index.phtml b/application/modules/admin/views/scripts/users/index.phtml
index 3e56303f1e16809aad671940d63abd315ece39ea..de21c86a0a747184f56a390b27958017004af6aa 100644
--- a/application/modules/admin/views/scripts/users/index.phtml
+++ b/application/modules/admin/views/scripts/users/index.phtml
@@ -1,5 +1,5 @@
 <?php
-if (Class_Users::isCurrentUserAdmin())
+if (Class_Users::isCurrentUserAdmin() || Class_Users::isCurrentUserAdminBib())
   echo $this->Button_New((new Class_Button)
                          ->setText($this->_('Ajouter un utilisateur')));
 
diff --git a/cosmogramme/sql/patch/patch_471.php b/cosmogramme/sql/patch/patch_471.php
new file mode 100644
index 0000000000000000000000000000000000000000..8548ec7995bb3ad08d01af77e67dca51d1363c92
--- /dev/null
+++ b/cosmogramme/sql/patch/patch_471.php
@@ -0,0 +1,11 @@
+<?php
+$adapter = Zend_Db_Table_Abstract::getDefaultAdapter();
+
+try {
+  $adapter
+    ->query('ALTER TABLE `bib_admin_users` ADD COLUMN IF NOT EXISTS managed_libraries varchar(255) default null');
+
+  $adapter
+    ->query('UPDATE bib_admin_users SET managed_libraries = id_site WHERE id_site != 0 and role_level >= 3');
+} catch(Exception $e) {
+}
diff --git a/cosmogramme/sql/patch/patch_472.php b/cosmogramme/sql/patch/patch_472.php
new file mode 100644
index 0000000000000000000000000000000000000000..5bbf1c1491cac50034db8e6f753fa08d79897d78
--- /dev/null
+++ b/cosmogramme/sql/patch/patch_472.php
@@ -0,0 +1,19 @@
+<?php
+$adapter = Zend_Db_Table_Abstract::getDefaultAdapter();
+$translator = Zend_Registry::get('translate');
+
+$groups = [['id' => ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL,
+            'label' => $translator->_('Administrateurs portail')],
+           ['id' => ZendAfi_Acl_AdminControllerRoles::SUPER_ADMIN,
+            'label' => $translator->_('Super administrateurs')]];
+
+try {
+  $system_category_id = Class_UserGroupCategorie::findFirstBy(['libelle' => 'Système'])
+    ->getId();
+
+  foreach($groups as $group)
+    if ($existing = Class_UserGroup::findFirstBy(['libelle' => $group['label'],
+                                                  'id_cat' => $system_category_id]))
+      $existing->setRightsToken(Class_UserGroup::getRightsTokenForAllRights())
+               ->save();
+} catch(Exception $e) { echo($e->getMessage()); }
diff --git a/cosmogramme/sql/patch/patch_473.php b/cosmogramme/sql/patch/patch_473.php
new file mode 100644
index 0000000000000000000000000000000000000000..9897b924c88a1638f410151ca74985c6839cd083
--- /dev/null
+++ b/cosmogramme/sql/patch/patch_473.php
@@ -0,0 +1,6 @@
+<?php
+$adapter = Zend_Db_Table_Abstract::getDefaultAdapter();
+
+try {
+  $adapter->query('ALTER TABLE `bib_admin_profil` CHANGE `ID_SITE` `ID_SITE` mediumtext NOT NULL');
+} catch(Exception $e) {}
diff --git a/library/Class/Article/Select.php b/library/Class/Article/Select.php
index 3acae0aa9ac7892ac283259774c7645626db62d0..079ed89b1679fe5946e9204b8719d2a6cf7926a9 100644
--- a/library/Class/Article/Select.php
+++ b/library/Class/Article/Select.php
@@ -380,15 +380,20 @@ class Class_Article_Select {
    * @param array $preferences
    * @return array
    */
-  protected function _byIdBib($id_bib) {
-    if (0 === $id_bib || null === $id_bib)
+  protected function _byIdBib($id_bibs) {
+    if (!is_array($id_bibs))
+      $id_bibs = [$id_bibs];
+
+    $id_bibs = $id_bibs ? array_filter($id_bibs) : [];
+    if ( ! $id_bibs)
       return $this;
 
     $this->_select
       ->join('cms_categorie',
              'cms_categorie.ID_CAT = cms_article.ID_CAT',
-             [])
-      ->where('cms_categorie.ID_SITE=?', $id_bib);
+             array())
+      ->where('cms_categorie.ID_SITE IN ('
+              . "'" . implode("','", $id_bibs) . "')");
     return $this;
   }
 
diff --git a/library/Class/Bib.php b/library/Class/Bib.php
index b0629717ee78c38f7549fa5469f95056b7095564..9b63e33a299bbcb4269cce6014d4899fa2d4c5f7 100644
--- a/library/Class/Bib.php
+++ b/library/Class/Bib.php
@@ -150,6 +150,26 @@ class BibLoader extends Storm_Model_Loader
   }
 
 
+  public function findManagedLibraries(): array
+  {
+    $libraries = [];
+
+    if (!$user = Class_Users::getIdentity())
+      return $libraries;
+
+    foreach (Class_Bib::query()
+             ->select(['id_site', 'libelle'])
+             ->in('id_site', Class_Users::getIdentity()->managedLibraryIds())
+             ->order_desc('libelle')
+             ->fetchAll() as $library)
+      $libraries[$library->id_site] = $library->getLibelle();
+
+    return (count($libraries) > 1)
+      ? $libraries
+      : [];
+  }
+
+
   public function findAllVisible() {
     return Class_Bib::findAllBy(['order' => 'libelle',
                                  'visibilite not' => Class_Bib::V_INVISIBLE]);
@@ -186,6 +206,9 @@ class BibLoader extends Storm_Model_Loader
       return $labels;
     }
 
+    if (Class_Users::isCurrentUserAdminBib() && $user !== Class_Users::getIdentity())
+      return Class_Bib::findManagedLibraries();
+
     $availables_libraries = [$portail];
 
     if ($user === Class_Users::getIdentity() && $library = $user->getBib())
@@ -264,14 +287,16 @@ class BibLoader extends Storm_Model_Loader
 
 
   public function findAllForCurrentUserAndPortal() : array {
-    return ['0' => Class_Bib::getPortail(), ...$this->_findAllForCurrentUser()];
+    return Class_Users::getIdentity()->isModoPortailOrMore()
+      ? ['0' => Class_Bib::getPortail(), ...$this->_findAllForCurrentUser()]
+      : $this->_findAllForCurrentUser();
   }
 
 
   protected function _findAllForCurrentUser() : array {
-    return (! Class_Users::isCurrentUserCanAccessAllBibs()) && ($user_library = Class_Users::getIdentity()->getBib())
-      ? [$user_library]
-    : Class_Bib::findAllBy(['order' => 'libelle']);
+    return (! Class_Users::isCurrentUserCanAccessAllBibs())
+      ? Class_Users::getIdentity()->managedLibraries()
+      : Class_Bib::findAllBy(['order' => 'libelle']);
   }
 }
 
diff --git a/library/Class/Calendar.php b/library/Class/Calendar.php
index 08622f0b7459c00187b5ca30c474519c1d5d5977..9d8bc3210977a34a554c5141b4461da77a9baf71 100644
--- a/library/Class/Calendar.php
+++ b/library/Class/Calendar.php
@@ -50,7 +50,7 @@ class Class_Calendar {
     $this->year = (int)substr($this->year_month, 0, 4);
     $this->month = (int)substr($this->year_month, -2);
 
-    $this->id_bib = Class_Profil::getCurrentProfil()->getIdSite();
+    $this->id_bib = Class_Profil::getCurrentProfil()->getLibraryIds();
 
     if (!array_isset('display_cat_select', $this->preferences))
       $this->preferences['display_cat_select'] = false;
diff --git a/library/Class/Catalogue.php b/library/Class/Catalogue.php
index a06f2135386361c486c729e0074f4437fb7a30b3..a6d4c18d60ab8d130e769c97dfb6cb34c43190eb 100644
--- a/library/Class/Catalogue.php
+++ b/library/Class/Catalogue.php
@@ -537,7 +537,7 @@ class Class_Catalogue extends Storm_Model_Abstract
       return true;
 
     if (Class_AdminVar::isModuleEnabled('ENABLE_DOMAINS_PER_LIBRARIES')
-        && (!in_array($this->getOwnOrParentLibraryId(), [0, $user->getIdSite()])))
+        && (!in_array($this->getOwnOrParentLibraryId(), $user->managedLibraryIds())))
       return false;
 
     if ($user->hasRightToAccess(Class_UserGroup::RIGHT_USER_DOMAINES_TOTAL_ACCESS))
diff --git a/library/Class/CriteresRecherche.php b/library/Class/CriteresRecherche.php
index 17f6f8cecffd80bf17eb162fac3ebd7a78fd0c57..868cebed8cd9a45bed13e6e59acf364d82b23e49 100644
--- a/library/Class/CriteresRecherche.php
+++ b/library/Class/CriteresRecherche.php
@@ -982,8 +982,8 @@ class Class_CriteresRecherche extends Class_CriteresRecherche_Abstract {
   public function getBibs() : array {
     $bibs = explode(',', $this->getParam('bib_select',''));
     if ($this->_profil
-        && ($selection_bib = $this->_profil->getIdSite()))
-      $bibs [] = $selection_bib;
+        && ($selection_bibs = $this->_profil->getLibraryIds()))
+      $bibs = array_merge($bibs,$selection_bibs);
 
     return array_filter($bibs);
   }
diff --git a/library/Class/Profil.php b/library/Class/Profil.php
index 6d79ccbf15727179874b76960a7a4f8fa505f2e3..5361ff85ebf749e5b9ba4b58be050c03b8c9114b 100644
--- a/library/Class/Profil.php
+++ b/library/Class/Profil.php
@@ -55,17 +55,70 @@ class ProfilLoader extends Storm_Model_Loader {
 
 
   public function findAllByZoneAndBib($id_zone = 0, $id_bib = 0) {
-    $conditions = ['order' => 'libelle'];
-    if ($id_zone && $id_zone !="ALL")
-      $conditions["ID_SITE"] = $id_zone=="PORTAIL" ? 0 : ["select ID_SITE from bib_c_site where ID_ZONE=$id_zone"];
+    $by_zone = null;
+    if ($id_zone && $id_zone !="ALL" && $id_zone != 'PORTAIL')
+      $by_zone = $id_zone;
 
-    if($id_bib && $id_bib!="ALL") {
+    $by_idbib = null;
+    if($id_bib and $id_bib!="ALL") {
       if($id_bib=="PORTAIL")
         $id_bib=0;
-      $conditions["ID_SITE"] = $id_bib;
+      $by_idbib = $id_bib;
     }
 
-    return  Class_Profil::findAllBy($conditions);
+    $profils = Class_Profil::findAllBy(['order' => 'libelle']);
+
+    if (isset($by_zone))
+      $profils = $this->_filterOnIdZone($profils, $by_zone);
+
+    if (isset($by_idbib))
+      $profils = $this->_filterOnIdBib($profils, $by_idbib);
+
+    if (Class_Users::getIdentity()->isAdminBib())
+      $profils = $this->_filterByManagedLibraries($profils);
+
+    return $profils;
+  }
+
+
+  protected function _filterOnIdZone(array $profils, int $id_zone): array
+  {
+    $filtered = [];
+    $bibs = array_map(fn($bib) => $bib->getId(),
+                      Class_Bib::findAllBy(['id_zone' => $id_zone]));
+
+    foreach ($profils as $profil)
+      if ($profil->hasOneOfManagedLibraries($bibs))
+        $filtered[] = $profil;
+
+    return $filtered;
+
+  }
+
+
+  protected function _filterOnIdBib(array $profils, int $id_bib): array
+  {
+    $filtered = [];
+
+    foreach ($profils as $profil)
+      if (in_array($id_bib, $profil->getLibraryIds()))
+        $filtered[] = $profil;
+
+    return $filtered;
+  }
+
+
+  protected function _filterByManagedLibraries(array $profils): array
+  {
+    $filtered = [];
+    $managed_libraries = array_filter(Class_Users::getIdentity()
+                                      ->managedLibraryIds());
+
+    foreach ($profils as $profil)
+      if ($profil->hasOneOfManagedLibraries($managed_libraries))
+        $filtered[] = $profil;
+
+    return $filtered;
   }
 
 
@@ -384,7 +437,7 @@ class Class_Profil extends Storm_Model_Abstract {
          'display_current_profil_on_breadcrumb' => false,
          'ref_description' => '',
          'ref_tags' => '',
-         'id_site' => 0,
+         'id_site' => '',
          'sel_section' => '',
          'sel_annexe' => '',
          'sel_type_doc' => '',
@@ -2536,6 +2589,29 @@ class Class_Profil extends Storm_Model_Abstract {
   }
 
 
+  public function hasOneOfManagedLibraries(array $managed_library_ids): bool
+  {
+    foreach ($this->getLibraryIds() as $library_id)
+      if (in_array($library_id, $managed_library_ids))
+        return true;
+
+    return false;
+  }
+
+
+  public function setLibraryIds($ids): self
+  {
+    $this->setIdSite(implode(' ', explode(';', $ids)));
+    return $this;
+  }
+
+
+  public function getLibraryIds(): array
+  {
+    return explode(' ', $this->getIdSite());
+  }
+
+
   public function getAlienLoginPage() {
     return ($login_page = $this->getLoginPage())
       && !$this->isMyselfMyOwnLoginPage()
diff --git a/library/Class/Profil/ItemsFilter.php b/library/Class/Profil/ItemsFilter.php
index 8bc57c361cc75d2d762211033a8755d30d05eac8..3dc810a395314c876e04f4db1520a5171f51e4e5 100644
--- a/library/Class/Profil/ItemsFilter.php
+++ b/library/Class/Profil/ItemsFilter.php
@@ -22,7 +22,7 @@
 
 class Class_Profil_ItemsFilter {
   public function select($profil, $items) : array {
-    $filter_item_from_profil = ['id_bib' => array_filter([$profil->getIdSite()]),
+    $filter_item_from_profil = ['id_bib' => array_filter($profil->getLibraryIds()),
                                 'annexe' => $profil->getSelAnnexCodes(),
                                 'section' => $profil->getSelSectionIds()];
 
@@ -46,4 +46,4 @@ class Class_Profil_ItemsFilter {
                         fn($item) => in_array($item->callGetterByAttributeName($item_attribute),
                                         $values));
   }
-}
\ No newline at end of file
+}
diff --git a/library/Class/User/SearchCriteria.php b/library/Class/User/SearchCriteria.php
index bb93ffce57ad07d398fdd9fbdf9acccf6f5fba4f..b4ec4de14df9f8a5714de99c6cf8e813b2b70d1c 100644
--- a/library/Class/User/SearchCriteria.php
+++ b/library/Class/User/SearchCriteria.php
@@ -55,28 +55,77 @@ class Class_User_SearchCriteriaLibrary extends Class_SearchCriteria_Select {
   protected string $_name = 'id_site';
 
   public function buildElement() : ?Zend_Form_Element {
-    return $this->_isAdminBib()
-      ? null
-      : (parent::buildElement()
-         ->setLabel($this->_('Bibliothèque'))
-         ->setMultiOptions(['all' => $this->_('Toutes')] + Class_Bib::findAllLabels()));
+    $labels = ($this->_isModoPortailOrMore())
+      ? Class_Bib::findAllLabels()
+      : Class_Bib::findManagedLibraries();
+
+    return ($labels)
+      ? parent::buildElement()->setLabel($this->_('Bibliothèque'))
+                              ->setMultiOptions(['all' => $this->_('Toutes')] + $labels)
+      : null;
   }
 
 
   public function acceptSearchVisitor($visitor) : Class_SearchCriteria_Abstract {
-    if ( ! $this->_isAdminBib())
+    if ( ! $this->_isAdminBib() && ! $this->_isRedacteurBib())
       return parent::acceptSearchVisitor($visitor);
 
-    $visitor->addQueryClause(fn($query) => $query->eq($this->_name,
-                                                      Class_Users::getIdentity()->getIdSite()));
 
+    $visitor->addQueryClause(fn($query) => $query
+                             ->in($this->_name,
+                                  $this->_isAllValues()
+                                  ? Class_Users::getIdentity()->managedLibraryIds()
+                                  : [$this->_value]));
     return $this;
   }
 
 
+  protected function _isModoPortailOrMore(): bool
+  {
+    return ($user = Class_Users::getIdentity()) && $user->isModoPortailOrMore();
+  }
+
+
   protected function _isAdminBib() : bool {
     return ($user = Class_Users::getIdentity()) && $user->isAdminBib();
   }
+
+
+  protected function _isRedacteurBib(): bool
+  {
+    return ($user = Class_Users::getIdentity()) && $user->isRedacteurBib();
+  }
+}
+
+
+
+
+class Class_User_SearchCriteriaMultiLibraries extends Class_User_SearchCriteriaLibrary
+{
+
+  public function buildElement(): ?Zend_Form_Element
+  {
+    return new ZendAfi_Form_Element_CochesSuggestion($this->getName(),
+                                                     ['label' => $this->_('Bibliothèques'),
+                                                      'rubrique' => 'libraries',
+                                                      'value' => $this->_value]);
+  }
+
+
+  public function acceptSearchVisitor($visitor): Class_SearchCriteria_Abstract
+  {
+    if ( ! $this->_isAllValues())
+      $visitor->addQueryClause(fn($query) => $query
+                               ->in($this->_name, explode(';', $this->_value)));
+
+    return $this;
+  }
+
+
+  public function modelMatch(Storm_Model_Abstract $user): bool
+  {
+    return $this->_isAllValues() || in_array($user->getIdSite(), explode(';', $this->_value));
+  }
 }
 
 
diff --git a/library/Class/UserGroup.php b/library/Class/UserGroup.php
index 4bcf97f5b8633cb59c6b9b45c7a37e0406483832..ec7b1c20b704f9bd200642825dfdc4f3c7fa85de 100644
--- a/library/Class/UserGroup.php
+++ b/library/Class/UserGroup.php
@@ -248,6 +248,7 @@ class Class_UserGroup extends Storm_Model_Abstract {
   const RIGHT_EDITER_BIB = 43;
   const RIGHT_ADMIN_CONTENT_SUPERVISION = 44;
   const RIGHT_USER_SEE_PRO_CARDS = 45;
+  const RIGHT_ADMIN_PROFILE = 46;
 
   // Type de groupe
   const TYPE_MANUAL = 0;
@@ -307,6 +308,7 @@ class Class_UserGroup extends Storm_Model_Abstract {
        static::RIGHT_USER_RENDEZ_VOUS => $t->_('Administration: accès à la gestion des rendez-vous'),
        static::RIGHT_ADMIN_CONTENT_SUPERVISION => $t->_('Contenu: Superviser la surveillance des contenus'),
        static::RIGHT_USER_SEE_PRO_CARDS => $t->_('Panier: Voir les paniers des professionels'),
+       static::RIGHT_ADMIN_PROFILE => $t->_('Administration: Gestion des profils'),
       ];
   }
 
diff --git a/library/Class/UserGroup/Filter.php b/library/Class/UserGroup/Filter.php
index 8ffe3340d87386157adfa94834a8289b211d34fc..b1584d625a6742a02bae2c2b76d1787dc2ad9bb3 100644
--- a/library/Class/UserGroup/Filter.php
+++ b/library/Class/UserGroup/Filter.php
@@ -24,6 +24,8 @@ class Class_UserGroup_Filter extends Class_User_SearchCriteria {
   public function __construct($params) {
     parent::__construct($params);
     $this->replaceCriteria(Class_User_SearchCriteria_RoleLevelLimited::class,
-                           new Class_User_SearchCriteria_RequiredRoleLevel($params));
+                           new Class_User_SearchCriteria_RequiredRoleLevel($params))
+         ->replaceCriteria(Class_User_SearchCriteriaLibrary::class,
+                           new Class_User_SearchCriteriaMultiLibraries($params));
   }
 }
diff --git a/library/Class/Users.php b/library/Class/Users.php
index 57d2cef1ba28c007ee44bd15ffeb2f3b6463ed9a..4a6e184632c7e23087e74f2068859ffbcdb094ea 100644
--- a/library/Class/Users.php
+++ b/library/Class/Users.php
@@ -156,6 +156,12 @@ class UsersLoader extends Storm_Model_Loader {
   }
 
 
+  public function isCurrentUserAdminBib(): bool
+  {
+    return ($user = Class_Users::getIdentity()) && $user->isAdminBib();
+  }
+
+
   public function isCurrentUserSuperAdmin() {
     if (!$user = Class_Users::getIdentity())
       return false;
@@ -502,7 +508,8 @@ class Class_Users extends Storm_Model_Abstract {
                                   'statut' => 0,
                                   'id_int_bib' => null,
                                   'parental_authorization' => self::UNDEFINED_DATA,
-                                  'multimedia_access' => self::UNDEFINED_DATA];
+                                  'multimedia_access' => self::UNDEFINED_DATA,
+                                  'managed_libraries' => ''];
 
 
   public static function currentUserId() {
@@ -571,6 +578,31 @@ class Class_Users extends Storm_Model_Abstract {
   }
 
 
+  public function managedLibraries(): array
+  {
+    return array_filter(array_map(fn($id) => Class_Bib::find($id),
+                                  $this->managedLibraryIds()));
+  }
+
+
+  public function managedLibraryIds(): array
+  {
+    return explode(';', $this->getManagedLibraries());
+  }
+
+
+  public function canManageLibrary(?Class_Bib $library): bool
+  {
+    return ($library && in_array($library->getId(), $this->managedLibraryIds()));
+  }
+
+
+  public function canEditManagedLibrariesFor(Class_Users $user): bool
+  {
+    return ($this->getId() != $user->getId() && ($this->getRoleLevel() > $user->getRoleLevel()));
+  }
+
+
   public function getLibraryUrl() {
     return ($library = $this->getBib())
       ? $library->getUrl()
@@ -634,6 +666,19 @@ class Class_Users extends Storm_Model_Abstract {
   }
 
 
+  public function isModoPortailOrMore(): bool
+  {
+    return $this->getRoleLevel() >= ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL;
+  }
+
+
+  public function isModo(): bool
+  {
+    return $this->getRoleLevel() == ZendAfi_Acl_AdminControllerRoles::MODO_BIB
+      || $this->getRoleLevel() == ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL;
+  }
+
+
   /**
    * @return bool
    */
@@ -670,6 +715,18 @@ class Class_Users extends Storm_Model_Abstract {
   }
 
 
+  public function isAdminBibOrMore(): bool
+  {
+    return $this->getRoleLevel() >= ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB;
+  }
+
+
+  public function isRedacteurBib(): bool
+  {
+    return $this->getRoleLevel() == ZendAfi_Acl_AdminControllerRoles::MODO_BIB;
+  }
+
+
   public function hasRightsOnLibraries() {
     return (new ZendAfi_Acl_AdminControllerGroup)->isAllowed($this, 'bib', 'index');
   }
@@ -679,11 +736,7 @@ class Class_Users extends Storm_Model_Abstract {
     if ( ! $this->hasRightsOnLibraries())
       return false;
 
-    $id_site = (string) $this->getIdSite();
-
-    return ( $id_site === $id) || ( '0' === $id_site)
-      ? true
-      : $this->isAdmin();
+    return $this->isModoPortailOrMore() || $this->canManageLibrary(Class_Bib::find($id));
   }
 
 
@@ -2069,7 +2122,7 @@ class Class_Users extends Storm_Model_Abstract {
       return true;
 
     return $this->isAdminBib()
-      ? ($this->getIdSite() === $profile->getIdSite())
+      ? $profile->hasOneOfManagedLibraries($this->managedLibraryIds())
       : $this->hasRightConfigFront() ;
   }
 
diff --git a/library/ZendAfi/Acl/AdminControllerRoles.php b/library/ZendAfi/Acl/AdminControllerRoles.php
index 1c699e57001548b3b6b647615f8f7ee12ab11b40..f7402570ceb3f99457a739f92619271386711530 100644
--- a/library/ZendAfi/Acl/AdminControllerRoles.php
+++ b/library/ZendAfi/Acl/AdminControllerRoles.php
@@ -81,8 +81,11 @@ class ZendAfi_Acl_AdminControllerRoles extends Zend_Acl {
     $this->add(new Zend_Acl_Resource('session-activity'));
     $this->add(new Zend_Acl_Resource('session-activity-inscription'));
     $this->add(new Zend_Acl_Resource('newsletter'));
-    $this->add(new Zend_Acl_Resource('profil'));
+    $this->add(new Zend_Acl_Resource('profil/accueil'));
+    $this->add(new Zend_Acl_Resource('profil/edit'));
+    $this->add(new Zend_Acl_Resource('profil/index'));
     $this->add(new Zend_Acl_Resource('profil/export'));
+    $this->add(new Zend_Acl_Resource('profil'));
     $this->add(new Zend_Acl_Resource('stat'));
     $this->add(new Zend_Acl_Resource('lieu'));
     $this->add(new Zend_Acl_Resource('upload'));
@@ -202,6 +205,10 @@ class ZendAfi_Acl_AdminControllerRoles extends Zend_Acl {
     $this->allow('modo_bib','drive-checkout');
     $this->allow('modo_bib','feature');
     $this->allow('modo_bib', 'content-watch');
+    $this->deny('modo_bib','profil/edit');
+    $this->deny('modo_bib','profil/index');
+    $this->deny('modo_bib','profil/accueil');
+    $this->deny('modo_bib','profil/export');
 
     $this->allow('admin_bib','rss');
     $this->allow('admin_bib','catalogue');
@@ -222,6 +229,10 @@ class ZendAfi_Acl_AdminControllerRoles extends Zend_Acl {
     $this->allow('admin_bib','usergroup');
     $this->allow('admin_bib','ouvertures');
     $this->allow('admin_bib','profil');
+    $this->allow('admin_bib','profil/edit');
+    $this->allow('admin_bib','profil/export');
+    $this->allow('admin_bib','profil/accueil');
+    $this->allow('admin_bib','profil/index');
     $this->allow('admin_bib','modo');
     $this->allow('admin_bib','menus');
     $this->allow('admin_bib','external-agendas');
@@ -247,7 +258,12 @@ class ZendAfi_Acl_AdminControllerRoles extends Zend_Acl {
     $this->deny('modo_portail','pnb');
     $this->deny('modo_portail','oai');
     $this->deny('modo_portail','frbr-link');
+    $this->deny('modo_portail','profil/export');
     $this->deny('modo_portail','profil');
+    $this->deny('modo_portail','profil/index');
+    $this->deny('modo_portail','profil/accueil');
+    $this->deny('modo_portail','profil/export');
+    $this->deny('modo_portail','profil/edit');
     $this->deny('modo_portail','print');
     $this->deny('modo_portail','zone');
     $this->deny('modo_portail','bib');
diff --git a/library/ZendAfi/Controller/Action/Helper/ListViewMode/Catalogue.php b/library/ZendAfi/Controller/Action/Helper/ListViewMode/Catalogue.php
index 663b2c9ff00e41dd3c29b42d00c189342cd4de40..bab5fd3aec892d4aff6793f7bb68cc6f0e6a2715 100644
--- a/library/ZendAfi/Controller/Action/Helper/ListViewMode/Catalogue.php
+++ b/library/ZendAfi/Controller/Action/Helper/ListViewMode/Catalogue.php
@@ -124,8 +124,14 @@ class ZendAfi_Controller_Action_Helper_ListViewMode_Catalogue
     $params = ['order' => 'libelle',
                'parent_id' => $parent_id];
 
+    if (array_key_exists('id_bib', $this->_params)
+        && !Class_Users::getIdentity()->isModoPortailOrMore()
+        && !Class_Users::getIdentity()->canManageLibrary(Class_Bib::find($this->_params['id_bib'])))
+      return new Storm_Model_Collection();
+
     if ((null === $parent_id) && array_key_exists('id_bib', $this->_params))
       $params['library_id'] = $this->_params['id_bib'] ?: null;
+
     return new Storm_Model_Collection(Class_Catalogue::findAllBy($params));
   }
 
diff --git a/library/ZendAfi/Controller/Plugin/DefineURLs.php b/library/ZendAfi/Controller/Plugin/DefineURLs.php
index 3e826cc9bed3ad7ee027435f2d760b904bae838c..1bfc490dc2b53698052e230a362b3fcfdf2f2ba6 100644
--- a/library/ZendAfi/Controller/Plugin/DefineURLs.php
+++ b/library/ZendAfi/Controller/Plugin/DefineURLs.php
@@ -180,7 +180,7 @@ class ZendAfi_Controller_Plugin_DefineURLs extends Zend_Controller_Plugin_Abstra
 
     if (!array_key_exists(static::ADMIN, $_SESSION))
       $_SESSION[static::ADMIN] = ['filtre_localisation' => ['id_zone' => 'ALL',
-                                                      'id_bib' => 'ALL']];
+                                                            'id_bib' => 'ALL']];
       $session=$_SESSION["admin"]["filtre_localisation"];
 
 
@@ -188,13 +188,12 @@ class ZendAfi_Controller_Plugin_DefineURLs extends Zend_Controller_Plugin_Abstra
       $id_zone= 'ALL';
 
       // Si role admin_site on force la zone et la bib
-      if (
-        (null !== ($user = Class_Users::getLoader()->getIdentity()))
-        && (null !== ($bib = $user->getBib()))
+      if ((null !== ($user = Class_Users::getLoader()->getIdentity()))
+          && (null !== ($bib = $user->getBib()))
+          && (!$user->isAdminBibOrMore())
       ) {
         $id_bib = $bib->getId();
         $id_zone = $bib->getIdZone();
-
       } else  {
         // Zone
         $id_zone = $request->getParam('z');
@@ -207,7 +206,7 @@ class ZendAfi_Controller_Plugin_DefineURLs extends Zend_Controller_Plugin_Abstra
         if($id_bib!="ALL" && $id_bib != "PORTAIL") $id_bib=intval($id_bib);
         if(!$id_bib) $id_bib=$session["id_bib"];
         if(intval($id_bib) > 0)
-          $id_zone=fetchOne("select ID_ZONE from bib_c_site where ID_SITE=$id_bib");
+          $id_zone = fetchOne("select ID_ZONE from bib_c_site where ID_SITE=$id_bib");
       }
 
       // On remet dans la session
@@ -267,4 +266,4 @@ class ZendAfi_Controller_Plugin_DefineURLs_ProfileDetector {
   public function isDetectedByName() {
     return $this->_by_name;
   }
-}
\ No newline at end of file
+}
diff --git a/library/ZendAfi/Controller/Plugin/Manager/Article.php b/library/ZendAfi/Controller/Plugin/Manager/Article.php
index bf93b2c3643fca0d979cbba3f680981602af294d..f344b6a0a9a314fb918f0f5546c79e997b0e7ca0 100644
--- a/library/ZendAfi/Controller/Plugin/Manager/Article.php
+++ b/library/ZendAfi/Controller/Plugin/Manager/Article.php
@@ -213,6 +213,13 @@ class ZendAfi_Controller_Plugin_Manager_Article extends ZendAfi_Controller_Plugi
   protected function _canEdit($model) {
     $this->_setParam('id_cat', null);
 
+    if (!$user = Class_Users::getIdentity())
+      return false;
+
+    if (($user->isAdminBib() || $user->isRedacteurBib())
+        && !$user->canManageLibrary($model->getBib()))
+      return false;
+
     return (new Class_Article_Permission($model))
       ->isEditableBy(Class_Users::getIdentity());
   }
diff --git a/library/ZendAfi/Controller/Plugin/Manager/ArticleCategory.php b/library/ZendAfi/Controller/Plugin/Manager/ArticleCategory.php
index b30aef08d161b2ff7c043bdb7bd4c99b45f6ffb6..a2d5b66a674f6988132cc3ff86c1d63d6bc870a4 100644
--- a/library/ZendAfi/Controller/Plugin/Manager/ArticleCategory.php
+++ b/library/ZendAfi/Controller/Plugin/Manager/ArticleCategory.php
@@ -93,9 +93,13 @@ class ZendAfi_Controller_Plugin_Manager_ArticleCategory extends ZendAfi_Controll
 
   protected function getDefaultBib() {
     $identity = Class_Users::getIdentity();
+    $requested_bib_id = (int)$this->_getParam('id_bib');
 
-    return ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB >= $identity->getRoleLevel()  ?
-      $identity->getBib() : Class_Bib::find((int)$this->_getParam('id_bib'));
+    if ($identity->getRoleLevel() > ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB
+        || in_array($requested_bib_id, $identity->managedLibraryIds()))
+        return Class_Bib::find($requested_bib_id);
+
+    return $identity->getBib();
   }
 
 
diff --git a/library/ZendAfi/Controller/Plugin/Manager/Catalogue.php b/library/ZendAfi/Controller/Plugin/Manager/Catalogue.php
index 0dfaa9e197b17cc4be7e835ca04e492326b35b40..3c883514433988649948ba01dbf579e8bc40a670 100644
--- a/library/ZendAfi/Controller/Plugin/Manager/Catalogue.php
+++ b/library/ZendAfi/Controller/Plugin/Manager/Catalogue.php
@@ -36,12 +36,14 @@ class ZendAfi_Controller_Plugin_Manager_Catalogue extends ZendAfi_Controller_Plu
 
 
   protected function _getLibraryActions($library) {
-    return [
-                ['url' => '/admin/catalogue/add/id_bib/' . $library->getId(),
-                 'icon' => 'add_page',
-                 'label' => $this->_('Ajouter un domaine à la bibliothèque %s',
-                                     $library->getLibelle())]
-    ];
+    if (!Class_Users::getIdentity()->isModoPortailOrMore()
+        && !Class_Users::getIdentity()->canManageLibrary($library))
+      return [];
+
+    return [['url' => '/admin/catalogue/add/id_bib/' . $library->getId(),
+             'icon' => 'add_page',
+             'label' => $this->_('Ajouter un domaine à la bibliothèque %s',
+                                 $library->getLibelle())]];
   }
 
 
diff --git a/library/ZendAfi/Controller/Plugin/Manager/Library.php b/library/ZendAfi/Controller/Plugin/Manager/Library.php
index 256096c7421f1aec0cec1b0e058d9d126a701ca2..694c0c563189cda4880c9cc4f4f1d0f44c83b65b 100644
--- a/library/ZendAfi/Controller/Plugin/Manager/Library.php
+++ b/library/ZendAfi/Controller/Plugin/Manager/Library.php
@@ -108,4 +108,18 @@ class ZendAfi_Controller_Plugin_Manager_Library extends ZendAfi_Controller_Plugi
         'label' => $this->_('Planification des ouvertures du drive'),
         'condition' => fn($library) => Class_AdminVar::isDriveCheckoutEnabled() && $library->isDriveEnabled()]];
   }
+
+
+  protected function _canEdit($model): bool
+  {
+    if (!$user = Class_Users::getIdentity())
+      return false;
+
+    if ($user->isModoPortailOrMore())
+      return true;
+
+    return ($user->isAdminBib() || $user->isRedacteurBib())
+      && $user->canManageLibrary($model);
+
+  }
 }
diff --git a/library/ZendAfi/Controller/Plugin/Manager/User.php b/library/ZendAfi/Controller/Plugin/Manager/User.php
index 439385e39208b5dbab164e545f8d8288ce036964..16d884d1bc5ba70a7d707f4b3a90fb72d2179bee 100644
--- a/library/ZendAfi/Controller/Plugin/Manager/User.php
+++ b/library/ZendAfi/Controller/Plugin/Manager/User.php
@@ -143,16 +143,20 @@ class ZendAfi_Controller_Plugin_Manager_User extends ZendAfi_Controller_Plugin_M
     if ( $user->getId() === $model->getId())
       return true;
 
-    if ($user->isRedacteur())
-      return false;
-
     if ($user->isSuperAdmin())
       return true;
 
     if ($model->isSuperAdmin())
       return false;
 
-    return $user->getRoleLevel() >= $model->getRoleLevel();
+    if ($model->getRoleLevel() > $user->getRoleLevel())
+      return false;
+
+    if ($user->isModoPortailOrMore())
+      return true;
+
+    return ($user->isAdminBib() || $user->isRedacteurBib())
+      && $user->canManageLibrary($model->getBib());
   }
 
 
diff --git a/library/ZendAfi/Form/Admin/User.php b/library/ZendAfi/Form/Admin/User.php
index 075045d5f2cb4c93403fa9d1f9e6dc62468927f4..721e962086b81eee16f1e760f3088bd69ba73ecf 100644
--- a/library/ZendAfi/Form/Admin/User.php
+++ b/library/ZendAfi/Form/Admin/User.php
@@ -27,6 +27,16 @@ class ZendAfi_Form_Admin_User extends ZendAfi_Form {
     $_menu_back_entries = [],
     $_menu_front_entries = [];
 
+  public function init()
+  {
+    parent::init();
+
+    Class_ScriptLoader::getInstance()
+      ->addJQueryReady(sprintf("if ($('#role_level').val() != %d && $('#role_level').val() != %d) { $('#managed_libraries').parent().parent().hide() } else { $('#managed_libraries').parent().parent().show() }",
+                               ZendAfi_Acl_AdminControllerRoles::MODO_BIB,
+                               ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB));
+  }
+
 
   public static function newWith($datas = [], $custom_form = null) {
     $form = (new static());
@@ -140,14 +150,31 @@ class ZendAfi_Form_Admin_User extends ZendAfi_Form {
     $this
       ->addElement('select',
                    'role_level',
-                   ['label' => $this->_('Niveau d\'accès'),
+                   ['onchange' => sprintf("if (event.target.value != %d && event.target.value != %d) { $('#managed_libraries').parent().parent().hide() } else { $('#managed_libraries').parent().parent().show() }",
+                                          ZendAfi_Acl_AdminControllerRoles::MODO_BIB,
+                                          ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB),
+                    'label' => $this->_('Niveau d\'accès'),
                     'multiOptions' => ZendAfi_Acl_AdminControllerRoles::getAvailableRolesFor($this->_user)])
 
       ->addElement('select',
                    'id_site',
-                   ['label' => $this->_('Bibliothèque'),
+                   ['label' => $this->_('Bibliothèque de rattachement'),
                     'multiOptions' => Class_Bib::canBeDeletedOrModifyByUser($this->_user)]);
 
+    $this->addElement('cochesSuggestion',
+                      'managed_libraries',
+                      ['label' => $this->_('Bibliothèque(s) gérée(s)'),
+                       'rubrique' => 'libraries',
+                       'style' => $this->_user->isRedacteurBib() || $this->_user->isAdminBib()
+                       ? ''
+                       : 'display:none',
+                       'disabled' => Class_Users::getIdentity()
+                       ->canEditManagedLibrariesFor($this->_user)
+                       ? null
+                       : 'disabled',
+                       'selected_all_means_nothing' => false]);
+
+
     if (Class_Users::getIdentity()->isAdminBib() || Class_Users::getIdentity()->isAdmin())
       $this->addElement('userGroup',
                         'user_group_ids',
@@ -160,6 +187,7 @@ class ZendAfi_Form_Admin_User extends ZendAfi_Form {
     $this
       ->addDisplayGroup(['role_level',
                          'id_site',
+                         'managed_libraries',
                          'user_group_ids'],
                         'admin_user_info',
                         ['legend' => $this->_('Droits')]);
diff --git a/library/ZendAfi/Form/Configuration/Profile.php b/library/ZendAfi/Form/Configuration/Profile.php
index c1e210080224a60af391ea9879d29952d692a545..c1885adb69d63a8477d6bbd0d0aeeb522bc54fd3 100644
--- a/library/ZendAfi/Form/Configuration/Profile.php
+++ b/library/ZendAfi/Form/Configuration/Profile.php
@@ -303,9 +303,12 @@ class ZendAfi_Form_Configuration_Profile extends ZendAfi_Form {
                    'tags_info',
                    ['value' => $this->_('Entrez la liste des mots-clef et expressions qui caractérisent votre site séparés par des virgules.')])
 
-      ->addElement('comboLibraries',
-                   'id_site',
-                   ['label' => $this->_('Bibliothèque')])
+      ->addElement('cochesSuggestion',
+                   'library_ids',
+                   ['label' => $this->_('Bibliothèque(s)'),
+                    'name' => 'library_ids',
+                    'rubrique' => 'libraries',
+                    'selected_all_means_nothing' => false])
 
       ->addElement('cochesSuggestion',
                    'sel_annexe',
@@ -378,7 +381,7 @@ class ZendAfi_Form_Configuration_Profile extends ZendAfi_Form {
                         'referencement_group',
                         ['legend' => $this->_('Référencement')])
 
-      ->addDisplayGroup(['id_site',
+      ->addDisplayGroup(['library_ids',
                          'sel_annexe',
                          'sel_section',
                          'sel_type_doc',
@@ -406,4 +409,11 @@ class ZendAfi_Form_Configuration_Profile extends ZendAfi_Form {
       $datas[$domain->getId()] = $domain->getLibelle();
     return $datas;
   }
-}
\ No newline at end of file
+
+  public function populate(array $values) : self {
+    $values['library_ids'] = implode(';', explode(' ', $values['id_site'] ?? ''));
+    parent::populate($values);
+
+    return $this;
+  }
+}
diff --git a/library/ZendAfi/View/Helper/Admin/ProfileSelect.php b/library/ZendAfi/View/Helper/Admin/ProfileSelect.php
index 7efc8787a85491bbaa966397df2b3ec74e553ada..b09f9072e1e8f3c007f346328ee74e2188e42991 100644
--- a/library/ZendAfi/View/Helper/Admin/ProfileSelect.php
+++ b/library/ZendAfi/View/Helper/Admin/ProfileSelect.php
@@ -130,12 +130,16 @@ class ZendAfi_View_Helper_Admin_ProfileSelect extends ZendAfi_View_Helper_BaseHe
                                 string $id_bib,
                                 bool $portail,
                                 bool $all,
-                                string $url) : string {
-    $bibs = ($zone = Class_Zone::find((int)$id_zone))
-      ? $zone->getBibs()
-      : [];
-
-    return $this->user->isRoleLibraryLimited()
+                                string $url): string
+  {
+    if ($managed_libraries = $this->user->managedLibraries())
+      $bibs = $managed_libraries;
+    else
+      $bibs = ($zone = Class_Zone::find((int)$id_zone))
+        ? $zone->getBibs()
+        : [];
+
+    return ($this->user->isRoleLibraryLimited() && count($bibs)==1)
       ? $this->_libraryLimitedBibSelect($bibs)
       : $this->_unlimitedBibSelect($bibs, $id_zone, $id_bib, $portail, $all, $url);
   }
@@ -157,6 +161,9 @@ class ZendAfi_View_Helper_Admin_ProfileSelect extends ZendAfi_View_Helper_BaseHe
       $options[] = $this->_option(new ProfileSelect_Model('PORTAIL', $this->_('Portail')),
                                   $id_bib);
 
+    if ($all && !$this->user->isRoleMoreThanModoBib())
+      $bibs = Class_Bib::findAllBy([]);
+
     foreach ($bibs as $bib)
       $options[] = $this->_option(ProfileSelect_Model::newFrom($bib), $id_bib);
 
@@ -172,14 +179,17 @@ class ZendAfi_View_Helper_Admin_ProfileSelect extends ZendAfi_View_Helper_BaseHe
 
   protected function _libraryLimitedBibSelect(array $bibs) : string {
     $options = (new Storm_Model_Collection($bibs))
-      ->select(fn($bib) => $bib->getId() == $this->user->getIdSite())
       ->collect(fn($bib) => $this->_option(ProfileSelect_Model::newFrom($bib)));
 
+    $params = ['name' => 'bib',
+               'id' => 'bib'];
+
+    if (count($bibs) === 1)
+      $param['disabled'] = 'disabled';
+
     return $this->_tag('select',
                        implode('', $options->getArrayCopy()),
-                       ['name' => 'bib',
-                        'id' => 'bib',
-                        'disabled' => 'disabled']);
+                       $params);
   }
 
 
diff --git a/library/ZendAfi/View/Helper/ComboCategories.php b/library/ZendAfi/View/Helper/ComboCategories.php
index 089f6f72b96899424e948b9b015c94130f6b5e72..107d6c20a3a5c530705041665265f74ea4677fe4 100644
--- a/library/ZendAfi/View/Helper/ComboCategories.php
+++ b/library/ZendAfi/View/Helper/ComboCategories.php
@@ -31,15 +31,7 @@ class ZendAfi_View_Helper_ComboCategories extends ZendAfi_View_Helper_BaseHelper
 
     $this->_categories_filter = $categories_filter;
 
-    if (Class_Users::isCurrentUserCanAccessAllBibs())
-      $bibs = Class_Bib::findAllWithPortail();
-    else {
-      $bib = $category->getBib();
-      if (0 == $bib->getId())
-        $bib = Class_Bib::getPortail();
-      $bibs = [$bib];
-    }
-
+    $bibs = $this->_getAllLibraries();
 
     $none_option = $options['allow_none']
       ? $this->view->tag('option', $this->_('Aucune'), ['value' => 0])
@@ -55,6 +47,14 @@ class ZendAfi_View_Helper_ComboCategories extends ZendAfi_View_Helper_BaseHelper
   }
 
 
+  protected function _getAllLibraries(): array
+  {
+    return Class_Users::isCurrentUserCanAccessAllBibs()
+      ? Class_Bib::findAllWithPortail()
+      : Class_Users::getIdentity()->managedLibraries();
+  }
+
+
   protected function _getAllBibCategories($bibs, $category, $category_class) {
     $html = '';
 
@@ -109,6 +109,4 @@ class ZendAfi_View_Helper_ComboCategories extends ZendAfi_View_Helper_BaseHelper
 
     return $html;
   }
-
-
-}
\ No newline at end of file
+}
diff --git a/library/ZendAfi/View/Helper/TagListArray/Element.php b/library/ZendAfi/View/Helper/TagListArray/Element.php
index cbd4734b5e8ff92beaec25dcc7dc320f3735aa12..cdb68311ff743597b177cc8c2d5840d60a37866b 100644
--- a/library/ZendAfi/View/Helper/TagListArray/Element.php
+++ b/library/ZendAfi/View/Helper/TagListArray/Element.php
@@ -25,7 +25,7 @@ class ZendAfi_View_Helper_TagListArray_Element extends ZendAfi_View_Helper_BaseH
     return  $this->view->tag('li',
                              $this->view->tag('a',
                                               $element->label,
-                                              ['clef' => $element->id,
+                                              ['data-clef' => $element->id,
                                                'href' => '#',
                                                'onclick' => $this->_getJsFunctionFor($element, $autorite).'; return false']),
                              ['class' => 'tag_liste'
diff --git a/library/ZendAfi/View/Helper/TagListeCoches.php b/library/ZendAfi/View/Helper/TagListeCoches.php
index 45313b3bff956ef440680ad770977667d760b46a..dcb783ca7452dcf9ecc5995ac71f1da37f8b44e4 100644
--- a/library/ZendAfi/View/Helper/TagListeCoches.php
+++ b/library/ZendAfi/View/Helper/TagListeCoches.php
@@ -69,6 +69,9 @@ class ZendAfi_View_Helper_TagListeCoches extends ZendAfi_View_Helper_BaseHelper
     if(is_callable($data))
       return call_user_func($data);
 
+    $libraries = $this->_simpleSourceFor('Class_Bib');
+    $user = Class_Users::getIdentity();
+
     $datas =
       [static::SOURCE_TYPE_DOC => new ZendAfi_View_Helper_TagListeCochesSourceDocType(),
        'section' => $this->_simpleSourceFor('Class_CodifSection'),
@@ -82,6 +85,8 @@ class ZendAfi_View_Helper_TagListeCoches extends ZendAfi_View_Helper_BaseHelper
        'bibliotheque' => $this->_simpleSourceFor('Class_Bib')
        ->setWhere(['visibilite' => '2']),
 
+       'libraries' => $libraries,
+
        'annexe' => (new ZendAfi_View_Helper_TagListeCochesSourceAnnexe())
        ->setWhere(array_filter(['id_bib' => $library_id,
                                 'invisible' => 0])),
@@ -160,7 +165,7 @@ class ZendAfi_View_Helper_TagListeCoches extends ZendAfi_View_Helper_BaseHelper
     $attribs = ['type' => 'checkbox',
                 'style' => 'width: inherit;',
                 'value' => 1,
-                'clef' => $clef,
+                'data-clef' => $clef,
                 'onclick' => 'getCoches(\'' . $this->_name . '\',' . $this->_cant_select_all . ')'
     ];
 
diff --git a/library/ZendAfi/View/Helper/TagListeCochesSuggestion.php b/library/ZendAfi/View/Helper/TagListeCochesSuggestion.php
index 6a156965adb2568076bcc7a8b354b9978a4ff159..bfeaa410549080ea3777123f0697268e1f22f44d 100644
--- a/library/ZendAfi/View/Helper/TagListeCochesSuggestion.php
+++ b/library/ZendAfi/View/Helper/TagListeCochesSuggestion.php
@@ -39,7 +39,7 @@ class ZendAfi_View_Helper_TagListeCochesSuggestion extends ZendAfi_View_Helper_T
     $attribs = ['type' => 'checkbox',
                 'style' => 'width: inherit;',
                 'value' => 1,
-                'clef' => $clef,
+                'data-clef' => $clef,
                 'onclick' => 'getCoches(\'' . $this->_name . '\',' . $this->_cant_select_all . ')'
     ];
     $attribs += $this->_element_attribs;
@@ -48,6 +48,12 @@ class ZendAfi_View_Helper_TagListeCochesSuggestion extends ZendAfi_View_Helper_T
         && $this->_coche[$clef])
       $attribs['checked'] = 'checked';
 
+    foreach (['selected_all_means_nothing',
+              'helper'] as $key){
+      $attribs['data-'.$key] = $attribs[$key];
+      unset($attribs[$key]);
+    }
+
     return $this->_tag('input', null, $attribs)
       . $libelle
       . $this->_tag('br');
diff --git a/library/ZendAfi/View/Helper/TagListeSuggestion.php b/library/ZendAfi/View/Helper/TagListeSuggestion.php
index 57eb948a2e135df157d08a18efa84217f31da92f..76d7ff8d614156650f21e4405cd8ba2720072ebe 100644
--- a/library/ZendAfi/View/Helper/TagListeSuggestion.php
+++ b/library/ZendAfi/View/Helper/TagListeSuggestion.php
@@ -189,7 +189,7 @@ class ZendAfi_View_Helper_TagListeSuggestion
                        $label,
                        [
                         'class' => 'selected tag-remove',
-                        'clef' => $value,
+                        'data-clef' => $value,
                         'onclick' => sprintf("selectSuggest('%s',this);",$this->_name)
                        ]);
   }
diff --git a/library/ZendAfi/View/Helper/Template/TagListeCoches.php b/library/ZendAfi/View/Helper/Template/TagListeCoches.php
index e1a707a6751533ad02590b3468a259083b2d7e3e..d36b0902e94c501f58fa7c69f38fed588bbaf924 100644
--- a/library/ZendAfi/View/Helper/Template/TagListeCoches.php
+++ b/library/ZendAfi/View/Helper/Template/TagListeCoches.php
@@ -71,7 +71,7 @@ class ZendAfi_View_Helper_Template_TagListeCoches extends ZendAfi_View_Helper_Ta
     $attribs = ['type' => 'checkbox',
                 'style' => 'width: inherit;',
                 'value' => 1,
-                'clef' => $clef,
+                'data-clef' => $clef,
                 'onclick' => 'getCoches(\'' . $this->_name . '\',' . $this->_cant_select_all . ')',
                 'onkeypress' => 'if (event.keyCode == 13) { $(this).trigger(\'click\');}'
     ];
diff --git a/public/opac/js/tag_selection/tag_selection.js b/public/opac/js/tag_selection/tag_selection.js
index ff7093d8d86c7457cd2f762a8469fa05f815b45a..2ccf4ceff8cce6015bf9a9963663ff33946deb67 100644
--- a/public/opac/js/tag_selection/tag_selection.js
+++ b/public/opac/js/tag_selection/tag_selection.js
@@ -34,39 +34,40 @@ function ouvrirFermer(oImg, sId)
 
 function getCoches(sIdChamp,allSelectedAsNothingSelected)
 {
-  // Handles
-  oChampCodes=getId(sIdChamp);
-  oContainer=getId(sIdChamp +"_saisie");
-  oChampAff=getId(sIdChamp +"_aff");
-  
-  // Get elements cochés
-  oChampCodes.value="";
-  sAff="";
-  bToutEstCoche=true;
-  var listItems = oContainer.getElementsByTagName('INPUT');
-  for(var no=0;no<listItems.length;no++)
-  {
-    oCheckBox=listItems[no];
-    if(oCheckBox.getAttribute("type") != "checkbox") continue;
-    if(oCheckBox.checked == true)
-    {
-      sLibelle=oCheckBox.nextSibling.data;
-      if(oChampCodes.value > "")
-	oChampCodes.value += ";";
-      oChampCodes.value+=oCheckBox.getAttribute("clef");
-      if( sAff > "")
-	sAff +=" ";
-      sAff+='<span class="selected">' + sLibelle + '</span>';
-    }
-    else bToutEstCoche=false;
-  }
-  if(bToutEstCoche == true && allSelectedAsNothingSelected)
-  {
+    // Handles
+    oChampCodes=getId(sIdChamp);
+    oContainer=getId(sIdChamp +"_saisie");
+    oChampAff=getId(sIdChamp +"_aff");
+    
+    // Get elements cochés
     oChampCodes.value="";
     sAff="";
-  }
-  oChampAff.innerHTML=sAff;
-  setFlagMaj(true);
+    bToutEstCoche=true;
+    var listItems = oContainer.getElementsByTagName('INPUT');
+    for(var no=0;no<listItems.length;no++)
+    {
+	oCheckBox=listItems[no];
+	if(oCheckBox.getAttribute("type") != "checkbox") continue;
+	if(oCheckBox.checked == true)
+	{
+	    sLibelle=oCheckBox.nextSibling.data;
+
+	    if(oChampCodes.value > "")
+		oChampCodes.value += ";";
+	    oChampCodes.value+=oCheckBox.getAttribute('data-clef');
+	    if( sAff > "")
+		sAff +=" ";
+	    sAff+='<span class="selected">' + sLibelle + '</span>';
+	}
+	else bToutEstCoche=false;
+    }
+    if(bToutEstCoche == true && allSelectedAsNothingSelected)
+    {
+	oChampCodes.value="";
+	sAff="";
+    }
+    oChampAff.innerHTML=sAff;
+    setFlagMaj(true);
 }
 
 
@@ -105,7 +106,7 @@ function selectSuggest(sIdChamp, oItem)
   var sCodes = oChampCodes.value;
  
   // Controle s'il est deja la
-  var sClef = oItem.getAttribute('clef');
+  var sClef = oItem.getAttribute('data-clef');
   var sControle = ';' + sCodes + ';';
 
   if (sControle.indexOf(';' + sClef + ';') >= 0) {
@@ -121,7 +122,7 @@ function selectSuggest(sIdChamp, oItem)
     
     oChampCodes.value = sControle;
 
-    $(oChampAff).find('span[clef="' + sClef + '"]').remove();
+    $(oChampAff).find('span[data-clef="' + sClef + '"]').remove();
     $('#'+sIdChamp).change();
     setFlagMaj(true);
     return;
@@ -142,7 +143,7 @@ function displayElementInCodif(label, sIdChamp, oItem){
     sAff = oChampAff.innerHTML;
     if( sAff > '')
 	sAff += ' ';
-    sAff += '<span class="selected tag-remove" clef="' + label + '" onclick="selectSuggest(\'' + sIdChamp + '\',this)">' + oItem.innerHTML + '</span>';
+    sAff += '<span class="selected tag-remove" data-clef="' + label + '" onclick="selectSuggest(\'' + sIdChamp + '\',this)">' + oItem.innerHTML + '</span>';
     oChampAff.innerHTML = sAff;
   
     $('#' + sIdChamp).change();
diff --git a/tests/application/modules/AbstractControllerTestCase.php b/tests/application/modules/AbstractControllerTestCase.php
index 9afeda4b2475596b4cfe944163da97dafe48059e..a921a4ce7b2a5a8caf89930282f342263bb6cbb0 100644
--- a/tests/application/modules/AbstractControllerTestCase.php
+++ b/tests/application/modules/AbstractControllerTestCase.php
@@ -98,6 +98,7 @@ abstract class AbstractControllerTestCase extends Zend_Test_PHPUnit_ControllerTe
                     'password' => 'mdp',
                     'role_level' => $account->ROLE_LEVEL,
                     'id_site' => $account->ID_SITE,
+                    'managed_libraries' => $account->ID_SITE,
                     'date_maj' => '',
                     'last_login' => 0,
                     'idabon' => '1',
diff --git a/tests/application/modules/admin/controllers/AlbumControllerTest.php b/tests/application/modules/admin/controllers/AlbumControllerTest.php
index e49c5aee656ebc91f2f65cb5e3b3b1bf9cbbb737..c559971926721c60b080b71dd9edc830197670cf 100644
--- a/tests/application/modules/admin/controllers/AlbumControllerTest.php
+++ b/tests/application/modules/admin/controllers/AlbumControllerTest.php
@@ -1590,7 +1590,7 @@ class Admin_AlbumControllerEditAlbumMesBDTest extends Admin_AlbumControllerEditA
 
   /** @test */
   public function tagSelectionNatureDocShouldContainsCollection() {
-    $this->assertXPath('//div[@id="nature_doc_saisie"]//input[@type="checkbox"][@clef="1"]');
+    $this->assertXPath('//div[@id="nature_doc_saisie"]//input[@type="checkbox"][@data-clef="1"]');
     $this->assertXPathContentContains('//div[@id="nature_doc_saisie"]', 'Collection');
   }
 
@@ -1644,7 +1644,7 @@ class Admin_AlbumControllerEditAlbumMesBDTest extends Admin_AlbumControllerEditA
 
   /** @test */
   public function tagSelectionBibShouldContainsAnnecy() {
-    $this->assertXPath('//div[@id="bibliotheques_saisie"]//input[@type="checkbox"][@clef="74"]');
+    $this->assertXPath('//div[@id="bibliotheques_saisie"]//input[@type="checkbox"][@data-clef="74"]');
   }
 
 
diff --git a/tests/application/modules/admin/controllers/BibControllerManagedLibrariesTest.php b/tests/application/modules/admin/controllers/BibControllerManagedLibrariesTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c9c910097c34dc96762346ada477b4a4ec4251cd
--- /dev/null
+++ b/tests/application/modules/admin/controllers/BibControllerManagedLibrariesTest.php
@@ -0,0 +1,282 @@
+<?php
+/**
+ * Copyright (c) 2012-2024, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+abstract class BibControllerManagedLibrariesTestCase extends Admin_AbstractControllerTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->fixture(Class_Bib::class, ['id' => 20,
+                                      'libelle' => 'Albert-Camus']);
+
+    $this->fixture(Class_Bib::class, ['id' => 21,
+                                      'libelle' => 'Hôtel-Dieu']);
+
+    $this->fixture(Class_Bib::class, ['id' => 22,
+                                      'libelle' => 'Musée Pasteur']);
+
+    $this->fixture(Class_Bib::class, ['id' => 23,
+                                      'libelle' => 'Authume']);
+
+    ZendAfi_Auth::getInstance()->logUser($this->_getLoggedUser());
+  }
+
+
+  protected function _createLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Libraries manager',
+                             'rights' => [Class_UserGroup::RIGHT_EDITER_BIB]]);
+
+    return $this->fixture(Class_Users::class,
+                          ['id' => 1,
+                           'login' => 'logged_in',
+                           'password' => 'secret',
+                           'id_site' => 1,
+                           'managed_libraries' => '',
+                           'role_level' => '',
+                           'last_login' => 0])
+                ->addUserGroup($group);
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser();
+  }
+}
+
+
+
+
+class BibControllerManagedLibrariesIndexModoBibTest
+  extends BibControllerManagedLibrariesTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+    $this->dispatch('/admin/bib');
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setIdSite('23')
+                ->setManagedLibraries('20;21')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function librariesTableShouldContainAlbertCamus()
+  {
+    $this->assertXPathContentContains('//tbody/tr/td', 'Albert-Camus');
+  }
+
+
+  /** @test */
+  public function librariesTableShouldContainHotelDieu()
+  {
+    $this->assertXPathContentContains('//tbody/tr/td', 'Hôtel-Dieu');
+  }
+
+
+  /** @test */
+  public function librariesTableShouldNotContainMuseePasteur()
+  {
+    $this->assertNotXPathContentContains('//tbody/tr/td', 'Musée Pasteur');
+  }
+
+
+
+  /** @test */
+  public function librariesTableShouldNotContainAuthume()
+  {
+    $this->assertNotXPathContentContains('//tbody/tr/td', 'Authume');
+  }
+}
+
+
+
+
+class BibControllerManagedLibrariesIndexAdminBibTest
+  extends BibControllerManagedLibrariesTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+    $this->dispatch('/admin/bib');
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('22')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB);
+  }
+
+
+  /** @test */
+  public function librariesTableShouldNotContainAlbertCamus()
+  {
+    $this->assertNotXPathContentContains('//tbody/tr/td', 'Albert-Camus');
+  }
+
+
+  /** @test */
+  public function librariesTableShouldNotContainHotelDieu()
+  {
+    $this->assertNotXPathContentContains('//tbody/tr/td', 'Hôtel-Dieu');
+  }
+
+
+  /** @test */
+  public function librariesTableShouldContainMuseePasteur()
+  {
+    $this->assertXPathContentContains('//tbody/tr/td', 'Musée Pasteur');
+  }
+
+
+  /** @test */
+  public function librariesTableShouldNotContainAuthume()
+  {
+    $this->assertNotXPathContentContains('//tbody/tr/td', 'Authume');
+  }
+}
+
+
+
+
+class BibControllerManagedLibrariesEditModoBibManageAlbertCamusMuseePasteurTest
+  extends BibControllerManagedLibrariesTestCase {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('20;22')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function shouldRenderLibraryAlbertCamus()
+  {
+    $this->dispatch('/admin/bib/edit/id/20');
+    $this->assertXPath('//form[@action="/admin/bib/edit/id/20"]');
+  }
+
+
+  /** @test */
+  public function shouldNotRenderLibraryHotelDieu()
+  {
+    $this->dispatch('/admin/bib/edit/id/21');
+    $this->assertRedirect('opac/index');
+  }
+
+
+  /** @test */
+  public function shouldRenderLibraryMuseePasteur()
+  {
+    $this->dispatch('/admin/bib/edit/id/22');
+    $this->assertXPath('//form[@action="/admin/bib/edit/id/22"]');
+  }
+}
+
+
+
+
+class BibControllerManagedLibrariesEditAdminBibManageHotelDieuTest
+  extends BibControllerManagedLibrariesTestCase {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('21')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB);
+  }
+
+
+  /** @test */
+  public function shouldNotRenderLibraryAlbertCamus()
+  {
+    $this->dispatch('/admin/bib/edit/id/20');
+    $this->assertRedirect('opac/index');
+  }
+
+
+  /** @test */
+  public function shouldRenderLibraryHotelDieu()
+  {
+    $this->dispatch('/admin/bib/edit/id/21');
+    $this->assertXPath('//form[@action="/admin/bib/edit/id/21"]');
+  }
+
+
+  /** @test */
+  public function shouldNotRenderLibraryMuseePasteur()
+  {
+    $this->dispatch('/admin/bib/edit/id/22');
+    $this->assertRedirect('opac/index');
+  }
+}
+
+
+
+
+class BibControllerManagedLibrariesEditModoPortailManageHotelDieuTest
+  extends BibControllerManagedLibrariesTestCase {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('21')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
+  }
+
+
+  /** @test */
+  public function shouldRenderLibraryAlbertCamus()
+  {
+    $this->dispatch('/admin/bib/edit/id/20');
+    $this->assertXPath('//form[@action="/admin/bib/edit/id/20"]');
+  }
+
+
+  /** @test */
+  public function shouldRenderLibraryHotelDieu()
+  {
+    $this->dispatch('/admin/bib/edit/id/21');
+    $this->assertXPath('//form[@action="/admin/bib/edit/id/21"]');
+  }
+
+
+  /** @test */
+  public function shouldRenderLibraryMuseePasteur()
+  {
+    $this->dispatch('/admin/bib/edit/id/22');
+    $this->assertXPath('//form[@action="/admin/bib/edit/id/22"]');
+  }
+}
diff --git a/tests/application/modules/admin/controllers/BibControllerTest.php b/tests/application/modules/admin/controllers/BibControllerTest.php
index 437f27ed635eb4aee171fc7dad1877cf264ce3ea..f6075c3322089be4c2e2a4fab4888cb8756f938c 100644
--- a/tests/application/modules/admin/controllers/BibControllerTest.php
+++ b/tests/application/modules/admin/controllers/BibControllerTest.php
@@ -37,6 +37,7 @@ abstract class BibControllerTestCase extends Admin_AbstractControllerTestCase {
 
     $profil_cran = $this->fixture(Class_Profil::class,
                                   ['id' => 34,
+                                   'id_site' => '2',
                                    'libelle' => 'Cran/Accueil']);
 
     $this->fixture(Class_CosmoVar::class,
@@ -415,6 +416,7 @@ abstract class BibControllerWithModerateurBibWithRightEditBibTestCase
     Class_Users::getIdentity()
       ->setPassword('toto')
       ->setIdSite('2')
+      ->setManagedLibraries('2')
       ->setUserGroups([$this->fixture(Class_UserGroup::class,
                                       ['id' => 23])->addRightEditerBib()])
       ->assertSave();
@@ -2008,7 +2010,7 @@ class BibControllerLocalisationMajTest extends BibControllerTestCase {
 
   /** @test */
   public function documentTypesShouldBeDisplayed() {
-    $this->assertXPath('//input[@type="checkbox"][@clef="8"]');
+    $this->assertXPath('//input[@type="checkbox"][@data-clef="8"]');
   }
 
 
@@ -2332,6 +2334,7 @@ class BibControllerDispatchIndexWithLibraryAdmin extends AbstractControllerTestC
                      ['id' => 89,
                       'login' => 'monteux',
                       'password' => 'ishould',
+                      'managed_libraries' => 56,
                       'id_site' => 56]);
 
     $monteux->beAdminBib()->save();
diff --git a/tests/application/modules/admin/controllers/CatalogueControllerManagedLibrariesTest.php b/tests/application/modules/admin/controllers/CatalogueControllerManagedLibrariesTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..fe412683840c3485221b8d6eaefd86550930f3c0
--- /dev/null
+++ b/tests/application/modules/admin/controllers/CatalogueControllerManagedLibrariesTest.php
@@ -0,0 +1,478 @@
+<?php
+/**
+ * Copyright (c) 2012-2024, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+abstract class CatalogueControllerManagedLibrariesTestCase extends Admin_AbstractControllerTestCase
+{
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    // Tester sans ce paramètre.
+    Class_AdminVar::set('ENABLE_DOMAINS_PER_LIBRARIES', 1);
+
+    $this->fixture(Class_Bib::class,
+                   ['id' => 301,
+                    'libelle' => 'Bib 301']);
+
+    $this->fixture(Class_Bib::class,
+                   ['id' => 302,
+                    'libelle' => 'Bib 302']);
+
+    $this->fixture(Class_Catalogue::class,
+                   ['id' => 10001,
+                    'parent_id' => null,
+                    'libelle' => 'Domain of bib 301',
+                    'library_id' => 301]);
+
+    $this->fixture(Class_Catalogue::class,
+                   ['id' => 10002,
+                    'parent_id' => null,
+                    'libelle' => 'Domain of bib 302',
+                    'library_id' => 302]);
+
+    ZendAfi_Auth::getInstance()->logUser($this->_getLoggedUser());
+  }
+
+
+  protected function _createLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Domains manager',
+                             'rights' => [Class_UserGroup::RIGHT_USER_DOMAINES_SUPPRESSION_LIMIT,
+                                          Class_UserGroup::RIGHT_USER_DOMAINES_TOTAL_ACCESS]]);
+
+    return $this->fixture(Class_Users::class,
+                          ['id' => 1,
+                           'login' => 'logged_in',
+                           'password' => 'secret',
+                           'id_site' => 1,
+                           'managed_libraries' => '',
+                           'role_level' => '',
+                           'last_login' => 0])
+                ->addUserGroup($group);
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser();
+  }
+}
+
+
+
+
+class CatalogueControllerManagedLibrariesAccessBibFoldersModoBibTest
+  extends CatalogueControllerManagedLibrariesTestCase
+{
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setIdSite('301')
+                ->setManagedLibraries('302')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function userShouldNotAccessBib301Folder()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/301');
+    $this->assertNotXPathContentContains('//table[@id="items_Class_Catalogue"]/tbody/tr/td',
+                                         'Domain of bib 301');
+  }
+
+
+  /** @test */
+  public function userShouldNotSeeAddDomainLinkForBib301()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/301');
+    $this->assertNotXPath('//div[@class="actions"]/a[contains(@href,"catalogue/add/id_bib/301")]');
+  }
+
+
+  /** @test */
+  public function userShouldAccessBib302Folder()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/302');
+    $this->assertXPathContentContains('//table[@id="items_Class_Catalogue"]/tbody/tr/td',
+                                      'Domain of bib 302');
+  }
+
+
+  /** @test */
+  public function userShouldSeeAddDomainLinkForBib302()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/302');
+    $this->assertXPath('//div[@class="actions"]/a[contains(@href,"catalogue/add/id_bib/302")]');
+  }
+}
+
+
+
+
+class CatalogueControllerManagedLibrariesAccessBibFoldersAdminBibTest
+  extends CatalogueControllerManagedLibrariesTestCase
+{
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setIdSite('301')
+                ->setManagedLibraries('301')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB);
+  }
+
+
+  /** @test */
+  public function userShouldAccessBib301Folder()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/301');
+    $this->assertXPathContentContains('//table[@id="items_Class_Catalogue"]/tbody/tr/td',
+                                      'Domain of bib 301');
+  }
+
+
+  /** @test */
+  public function userShouldSeeAddDomainLinkForBib301()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/301');
+    $this->assertXPath('//div[@class="actions"]/a[contains(@href,"catalogue/add/id_bib/301")]');
+  }
+
+
+  /** @test */
+  public function userShouldNotAccessBib302Folder()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/302');
+    $this->assertNotXPathContentContains('//table[@id="items_Class_Catalogue"]/tbody/tr/td',
+                                         'Domain of bib 302');
+  }
+
+
+  /** @test */
+  public function userShouldNotSeeAddDomainLinkForBib302()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/301');
+    $this->assertNotXPath('//div[@class="actions"]/a[contains(@href,"catalogue/add/id_bib/302")]');
+  }
+}
+
+
+
+
+class CatalogueControllerManagedLibrariesAccessBibFoldersModoPortailTest
+  extends CatalogueControllerManagedLibrariesTestCase
+{
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setIdSite('301')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
+  }
+
+
+  /** @test */
+  public function userShouldAccessBib301Folder()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/301');
+    $this->assertXPathContentContains('//table[@id="items_Class_Catalogue"]/tbody/tr/td',
+                                      'Domain of bib 301');
+  }
+
+
+  /** @test */
+  public function userShouldSeeAddDomainLinkForBib301()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/301');
+    $this->assertXPath('//div[@class="actions"]/a[contains(@href,"catalogue/add/id_bib/301")]');
+  }
+
+
+  /** @test */
+  public function userShouldAccessBib302Folder()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/302');
+    $this->assertXPathContentContains('//table[@id="items_Class_Catalogue"]/tbody/tr/td',
+                                      'Domain of bib 302');
+  }
+
+
+  /** @test */
+  public function userShouldSeeAddDomainLinkForBib302()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/302');
+    $this->assertXPath('//div[@class="actions"]/a[contains(@href,"catalogue/add/id_bib/302")]');
+  }
+}
+
+
+
+
+class CatalogueControllerManagedLibrariesAccessBibFoldersAdminPortailTest
+  extends CatalogueControllerManagedLibrariesTestCase
+{
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setIdSite('301')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL);
+  }
+
+
+  /** @test */
+  public function userShouldAccessBib301Folder()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/301');
+    $this->assertXPathContentContains('//table[@id="items_Class_Catalogue"]/tbody/tr/td',
+                                      'Domain of bib 301');
+  }
+
+
+  /** @test */
+  public function userShouldSeeAddDomainLinkForBib301()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/301');
+    $this->assertXPath('//div[@class="actions"]/a[contains(@href,"catalogue/add/id_bib/301")]');
+  }
+
+
+  /** @test */
+  public function userShouldAccessBib302Folder()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/302');
+    $this->assertXPathContentContains('//table[@id="items_Class_Catalogue"]/tbody/tr/td',
+                                      'Domain of bib 302');
+  }
+
+
+  /** @test */
+  public function userShouldSeeAddDomainLinkForBib302()
+  {
+    $this->dispatch('/admin/catalogue/index/id_bib/302');
+    $this->assertXPath('//div[@class="actions"]/a[contains(@href,"catalogue/add/id_bib/302")]');
+  }
+}
+
+
+
+
+class CatalogueControllerManagedLibrariesAddNewDomainModoBibTest
+  extends CatalogueControllerManagedLibrariesTestCase
+{
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setIdSite('301')
+                ->setManagedLibraries('302')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function userShouldNotAccessAddFormForBib301()
+  {
+    $this->dispatch('/admin/catalogue/add/id_bib/301');
+    $this->assertRedirect('opac/index');
+  }
+
+
+  /** @test */
+  public function userShouldNotSubmitForBib301()
+  {
+    $this->postDispatch('/admin/catalogue/add/id_bib/301', ['libelle' => 'My domain']);
+    $this->assertRedirect('opac/index');
+  }
+
+
+
+  /** @test */
+  public function userShouldAccessAddFormForBib302()
+  {
+    $this->dispatch('/admin/catalogue/add/id_bib/302');
+    $this->assertXPath('//form[@action="/admin/catalogue/add/id_bib/302"]');
+  }
+
+
+  /** @test */
+  public function userShouldSubmitForBib302()
+  {
+    $this->postDispatch('/admin/catalogue/add/id_bib/302', ['libelle' => 'My domain']);
+    $this->assertRedirect('admin/catalogue/edit/id_catalogue/');
+  }
+}
+
+
+
+
+class CatalogueControllerManagedLibrariesAddNewDomainAdminBibTest
+  extends CatalogueControllerManagedLibrariesTestCase
+{
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setIdSite('301')
+                ->setManagedLibraries('301')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB);
+  }
+
+
+  /** @test */
+  public function userShouldAccessAddFormForBib301()
+  {
+    $this->dispatch('/admin/catalogue/add/id_bib/301');
+    $this->assertXPath('//form[@action="/admin/catalogue/add/id_bib/301"]');
+  }
+
+
+  /** @test */
+  public function userShouldSubmitForBib301()
+  {
+    $this->postDispatch('/admin/catalogue/add/id_bib/301', ['libelle' => 'My domain']);
+    $this->assertRedirect('admin/catalogue/edit/id_catalogue/');
+  }
+
+
+  /** @test */
+  public function userShouldNotAccessAddFormForBib302()
+  {
+    $this->dispatch('/admin/catalogue/add/id_bib/302');
+    $this->assertRedirect('opac/index');
+  }
+
+
+  /** @test */
+  public function userShouldNotSubmitForBib302()
+  {
+    $this->postDispatch('/admin/catalogue/add/id_bib/302', ['libelle' => 'My domain']);
+    $this->assertRedirect('opac/index');
+  }
+}
+
+
+
+
+class CatalogueControllerManagedLibrariesAddNewDomainModoPortailTest
+  extends CatalogueControllerManagedLibrariesTestCase
+{
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setIdSite('301')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
+  }
+
+
+  /** @test */
+  public function userShouldAccessAddFormForBib301()
+  {
+    $this->dispatch('/admin/catalogue/add/id_bib/301');
+    $this->assertXPath('//form[@action="/admin/catalogue/add/id_bib/301"]');
+  }
+
+
+  /** @test */
+  public function userShouldSubmitForBib301()
+  {
+    $this->postDispatch('/admin/catalogue/add/id_bib/301', ['libelle' => 'My domain']);
+    $this->assertRedirect('admin/catalogue/edit/id_catalogue/');
+  }
+
+
+  /** @test */
+  public function userShouldAccessAddFormForBib302()
+  {
+    $this->dispatch('/admin/catalogue/add/id_bib/302');
+    $this->assertXPath('//form[@action="/admin/catalogue/add/id_bib/302"]');
+  }
+
+
+  /** @test */
+  public function userShouldSubmitForBib302()
+  {
+    $this->postDispatch('/admin/catalogue/add/id_bib/302', ['libelle' => 'My domain']);
+    $this->assertRedirect('admin/catalogue/edit/id_catalogue/');
+  }
+}
+
+
+
+
+class CatalogueControllerManagedLibrariesAddNewDomainAdminPortailTest
+  extends CatalogueControllerManagedLibrariesTestCase
+{
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setIdSite('301')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL);
+  }
+
+
+  /** @test */
+  public function userShouldAccessAddFormForBib301()
+  {
+    $this->dispatch('/admin/catalogue/add/id_bib/301');
+    $this->assertXPath('//form[@action="/admin/catalogue/add/id_bib/301"]');
+  }
+
+
+  /** @test */
+  public function userShouldSubmitForBib301()
+  {
+    $this->postDispatch('/admin/catalogue/add/id_bib/301', ['libelle' => 'My domain']);
+    $this->assertRedirect('admin/catalogue/edit/id_catalogue/');
+  }
+
+
+  /** @test */
+  public function userShouldAccessAddFormForBib302()
+  {
+    $this->dispatch('/admin/catalogue/add/id_bib/302');
+    $this->assertXPath('//form[@action="/admin/catalogue/add/id_bib/302"]');
+  }
+
+
+  /** @test */
+  public function userShouldSubmitForBib302()
+  {
+    $this->postDispatch('/admin/catalogue/add/id_bib/302', ['libelle' => 'My domain']);
+    $this->assertRedirect('admin/catalogue/edit/id_catalogue/');
+  }
+}
diff --git a/tests/application/modules/admin/controllers/CatalogueControllerTest.php b/tests/application/modules/admin/controllers/CatalogueControllerTest.php
index d4bc9e842553e6c65b4b038e67dbdc032995e149..a97c91238b7d645ea6d3f30301906d7b61a352bd 100644
--- a/tests/application/modules/admin/controllers/CatalogueControllerTest.php
+++ b/tests/application/modules/admin/controllers/CatalogueControllerTest.php
@@ -792,13 +792,13 @@ class CatalogueControllerEditCatalogueTest extends CatalogueControllerEditCatalo
 
   /** @test */
   public function annexe12ChoiceShouldBePresent() {
-    $this->assertXPath('//div[@id="annexe_saisie"]//input[@type="checkbox"][@clef=12]');
+    $this->assertXPath('//div[@id="annexe_saisie"]//input[@type="checkbox"][@data-clef=12]');
   }
 
 
   /** @test */
   public function annexe24ChoiceShouldBePresent() {
-    $this->assertXPath('//div[@id="annexe_saisie"]//input[@type="checkbox"][@clef=24]');
+    $this->assertXPath('//div[@id="annexe_saisie"]//input[@type="checkbox"][@data-clef=24]');
   }
 
 
diff --git a/tests/application/modules/admin/controllers/CatalogueEditControllerTest.php b/tests/application/modules/admin/controllers/CatalogueEditControllerTest.php
index 67da14ccc26145e691a4df143042d01befb98467..9bc12167e7c6a4171f83f2adbfecb1ed4467fceb 100644
--- a/tests/application/modules/admin/controllers/CatalogueEditControllerTest.php
+++ b/tests/application/modules/admin/controllers/CatalogueEditControllerTest.php
@@ -82,7 +82,7 @@ class AdminCatalogueControllerEditSelectedMatiere extends AbstractControllerTest
 
   /** @test */
   public function MatiereShouldBeDisplayedWithDeleteCross() {
-    $this->assertXPathContentContains("//div[@id='matiere_aff']//span[@class='selected tag-remove'][@clef='78308']","Histoire du feminisme");
+    $this->assertXPathContentContains("//div[@id='matiere_aff']//span[@class='selected tag-remove'][@data-clef='78308']","Histoire du feminisme");
   }
 }
 
diff --git a/tests/application/modules/admin/controllers/CmsControllerManagedLibrariesTest.php b/tests/application/modules/admin/controllers/CmsControllerManagedLibrariesTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..8ce4492e71d12c33071965f518f9e57d07f4243f
--- /dev/null
+++ b/tests/application/modules/admin/controllers/CmsControllerManagedLibrariesTest.php
@@ -0,0 +1,638 @@
+<?php
+/**
+ * Copyright (c) 2012-2024, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+abstract class CmsControllerManagedLibrariesTestCase extends Admin_AbstractControllerTestCase {
+
+  protected
+    $_group,
+    $_camus_category,
+    $_hotel_category,
+    $_musee_category,
+    $_authume_category;
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->_setArticlesListMode();
+
+    $this->fixture(Class_Permission::class, ['id' => 330,
+                                            'module' => 'ARTICLE',
+                                            'code' => 'ARTICLE']);
+
+    $this->_camus_category = $this->fixture(Class_ArticleCategorie::class,
+                                            ['id' => 10,
+                                             'libelle' => 'Albert-Camus Category']);
+
+    $this->fixture(Class_Article::class, ['id' => 40,
+                                          'categorie' => $this->_camus_category,
+                                          'titre' => 'Albert-Camus article',
+                                          'contenu' => 'Albert-Camus article']);
+
+    $this->fixture(Class_Bib::class, ['id' => 20,
+                                      'libelle' => 'Albert-Camus'])
+         ->setArticleCategories([$this->_camus_category])
+         ->assertSave();
+
+    $this->_hotel_category = $this->fixture(Class_ArticleCategorie::class,
+                                            ['id' => 11,
+                                             'libelle' => 'Hôtel-Dieu Category']);
+
+    $this->fixture(Class_Article::class, ['id' => 41,
+                                          'categorie' => $this->_hotel_category,
+                                          'titre' => 'Hôtel-Dieu article',
+                                          'contenu' => 'Hôtel-Dieu article']);
+
+    $this->fixture(Class_Bib::class, ['id' => 21,
+                                      'libelle' => 'Hôtel-Dieu'])
+         ->setArticleCategories([$this->_hotel_category])
+         ->assertSave();
+
+    $this->_musee_category = $this->fixture(Class_ArticleCategorie::class,
+                                            ['id' => 12,
+                                             'libelle' => 'Musée Pasteur Category']);
+
+    $this->fixture(Class_Article::class, ['id' => 42,
+                                          'categorie' => $this->_musee_category,
+                                          'titre' => 'Musée Pasteur article',
+                                          'contenu' => 'Musée Pasteur article']);
+
+    $this->fixture(Class_Bib::class, ['id' => 22,
+                                      'libelle' => 'Musée Pasteur'])
+         ->setArticleCategories([$this->_musee_category])
+         ->assertSave();
+
+    $this->_authume_category = $this->fixture(Class_ArticleCategorie::class,
+                                              ['id' => 13,
+                                               'libelle' => 'Musée Pasteur Category']);
+    $this->fixture(Class_Article::class, ['id' => 43,
+                                          'categorie' => $this->_authume_category,
+                                          'titre' => 'Authume article',
+                                          'contenu' => 'Authume article']);
+
+    $this->fixture(Class_Bib::class, ['id' => 23,
+                                      'libelle' => 'Authume'])
+         ->setArticleCategories([$this->_authume_category])
+         ->assertSave();
+
+    ZendAfi_Auth::getInstance()->logUser($this->_getLoggedUser());
+  }
+
+
+  protected function _createLoggedUser(): Class_Users
+  {
+    $this->_group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Libraries manager',
+                             'rights' => [Class_UserGroup::RIGHT_USER_ACCES_ARTICLES]]);
+
+    return $this->fixture(Class_Users::class,
+                          ['id' => 1,
+                           'login' => 'logged_in',
+                           'password' => 'secret',
+                           'id_site' => 1,
+                           'managed_libraries' => '',
+                           'role_level' => '',
+                           'last_login' => 0])
+                ->addUserGroup($this->_group);
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser();
+  }
+
+
+  protected function _setArticlesListMode(): void
+  {
+    Class_AdminVar::set('ARTICLES_LIST_MODE', '0');
+  }
+}
+
+
+
+
+class CmsControllerManagedLibrariesIndexModoBibWithoutBibTest
+  extends CmsControllerManagedLibrariesTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+    $this->dispatch('/admin/cms');
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setIdSite('')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function pageShouldNotContainLibraryPortail()
+  {
+    $this->assertNotXPathContentContains('//a', 'Portail');
+  }
+
+
+  /** @test */
+  public function pageShouldNotContainLibraryAlbertCmaus()
+  {
+    $this->assertNotXPathContentContains('//a', 'Albert-Camus');
+  }
+
+
+  /** @test */
+  public function pageShouldNotContainLibraryHotelDieu()
+  {
+    $this->assertNotXPathContentContains('//a', 'Hôtel-Dieu');
+  }
+
+
+  /** @test */
+  public function pageShouldNotContainLibraryMuseePasteur()
+  {
+    $this->assertNotXPathContentContains('//a', 'Musée Pasteur');
+  }
+
+
+  /** @test */
+  public function pageShouldNotContainLibraryAuthume()
+  {
+    $this->assertNotXPathContentContains('//a', 'Authume');
+  }
+}
+
+
+
+
+class CmsControllerManagedLibrariesIndexModoBibWithoutBibArticleListModeTest
+  extends CmsControllerManagedLibrariesIndexModoBibWithoutBibTest {
+
+  protected function _setArticlesListMode(): void
+  {
+    Class_AdminVar::set('ARTICLES_LIST_MODE', '1');
+  }
+}
+
+
+
+
+class CmsControllerManagedLibrariesIndexModoBibTest
+  extends CmsControllerManagedLibrariesTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+    $this->dispatch('/admin/cms');
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('20;21')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function pageShouldNotContainLibraryPortail()
+  {
+    $this->assertNotXPathContentContains('//a', 'Portail');
+  }
+
+
+  /** @test */
+  public function pageShouldContainLibraryAlbertCmaus()
+  {
+    $this->assertXPathContentContains('//a', 'Albert-Camus');
+  }
+
+
+  /** @test */
+  public function pageShouldContainLibraryHotelDieu()
+  {
+    $this->assertXPathContentContains('//a', 'Hôtel-Dieu');
+  }
+
+
+  /** @test */
+  public function pageShouldNotContainLibraryMuseePasteur()
+  {
+    $this->assertNotXPathContentContains('//a', 'Musée Pasteur');
+  }
+
+
+  /** @test */
+  public function pageShouldNotContainLibraryAuthume()
+  {
+    $this->assertNotXPathContentContains('//a', 'Authume');
+  }
+}
+
+
+
+
+class CmsControllerManagedLibrariesIndexModoBibArticleListModeTest
+  extends CmsControllerManagedLibrariesIndexModoBibTest {
+
+  protected function _setArticlesListMode(): void
+  {
+    Class_AdminVar::set('ARTICLES_LIST_MODE', '1');
+  }
+}
+
+
+
+
+class CmsControllerManagedLibrariesIndexAdminBibTest
+  extends CmsControllerManagedLibrariesTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+    $this->dispatch('/admin/cms');
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setIdSite('23')
+                ->setManagedLibraries('21')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB);
+  }
+
+
+  /** @test */
+  public function pageShouldNotContainLibraryPortail()
+  {
+    $this->assertNotXPathContentContains('//a', 'Portail');
+  }
+
+
+  /** @test */
+  public function pageShouldNotContainLibraryAlbertCmaus()
+  {
+    $this->assertNotXPathContentContains('//a', 'Albert-Camus');
+  }
+
+
+  /** @test */
+  public function pageShouldContainLibraryHotelDieu()
+  {
+    $this->assertXPathContentContains('//a', 'Hôtel-Dieu');
+  }
+
+
+  /** @test */
+  public function pageShouldNotContainLibraryMuseePasteur()
+  {
+    $this->assertNotXPathContentContains('//a', 'Musée Pasteur');
+  }
+
+
+  /** @test */
+  public function pageShouldNotContainLibraryAuthume()
+  {
+    $this->assertNotXPathContentContains('//a', 'Authume');
+  }
+}
+
+
+
+
+class CmsControllerManagedLibrariesIndexAdminBibArticleListModeTest
+  extends CmsControllerManagedLibrariesIndexAdminBibTest {
+
+  protected function _setArticlesListMode(): void
+  {
+    Class_AdminVar::set('ARTICLES_LIST_MODE', '1');
+  }
+}
+
+
+
+
+class CmsControllerManagedLibrariesIndexModoPortailTest
+  extends CmsControllerManagedLibrariesTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+    $this->dispatch('/admin/cms');
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
+  }
+
+
+  /** @test */
+  public function pageShouldContainLibraryPortail()
+  {
+    $this->assertXPathContentContains('//a', 'Portail');
+  }
+
+
+  /** @test */
+  public function pageShouldContainLibraryAlbertCmaus()
+  {
+    $this->assertXPathContentContains('//a', 'Albert-Camus');
+  }
+
+
+  /** @test */
+  public function pageShouldContainLibraryHotelDieu()
+  {
+    $this->assertXPathContentContains('//a', 'Hôtel-Dieu');
+  }
+
+
+  /** @test */
+  public function pageShouldContainLibraryMuseePasteur()
+  {
+    $this->assertXPathContentContains('//a', 'Musée Pasteur');
+  }
+
+
+  /** @test */
+  public function pageShouldContainLibraryAuthume()
+  {
+    $this->assertXPathContentContains('//a', 'Authume');
+  }
+}
+
+
+
+
+class CmsControllerManagedLibrariesIndexModoPortailArticleListModeTest
+  extends CmsControllerManagedLibrariesIndexModoPortailTest {
+
+  protected function _setArticlesListMode(): void
+  {
+    Class_AdminVar::set('ARTICLES_LIST_MODE', '1');
+  }
+}
+
+
+
+
+class CmsControllerManagedLibrariesIndexAdminPortailTest
+  extends CmsControllerManagedLibrariesTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+    $this->dispatch('/admin/cms');
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL);
+  }
+
+
+  /** @test */
+  public function pageShouldContainLibraryPortail()
+  {
+    $this->assertXPathContentContains('//a', 'Portail');
+  }
+
+
+  /** @test */
+  public function pageShouldContainLibraryAlbertCmaus()
+  {
+    $this->assertXPathContentContains('//a', 'Albert-Camus');
+  }
+
+
+  /** @test */
+  public function pageShouldContainLibraryHotelDieu()
+  {
+    $this->assertXPathContentContains('//a', 'Hôtel-Dieu');
+  }
+
+
+  /** @test */
+  public function pageShouldContainLibraryMuseePasteur()
+  {
+    $this->assertXPathContentContains('//a', 'Musée Pasteur');
+  }
+
+
+  /** @test */
+  public function pageShouldContainLibraryAuthume()
+  {
+    $this->assertXPathContentContains('//a', 'Authume');
+  }
+}
+
+
+
+
+class CmsControllerManagedLibrariesIndexAdminPortailArticleListModeTest
+  extends CmsControllerManagedLibrariesIndexAdminPortailTest {
+
+  protected function _setArticlesListMode(): void
+  {
+    Class_AdminVar::set('ARTICLES_LIST_MODE', '1');
+  }
+}
+
+
+
+
+class CmsControllerManagedLibrariesEditModoBibLibraryTest
+  extends CmsControllerManagedLibrariesTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    Class_Permission::createArticle()->permitTo($this->_group, $this->_camus_category);
+    Class_Permission::createArticle()->permitTo($this->_group, $this->_hotel_category);
+    Class_Permission::createArticle()->permitTo($this->_group, $this->_authume_category);
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setIdSite('23')
+                ->setManagedLibraries('20')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function withRightAndBibShouldRenderArticleAlbertCamusForm()
+  {
+    $this->dispatch('/admin/cms/edit/id/40');
+    $this->assertXPath('//form[@action="/admin/cms/edit/id/40"]');
+  }
+
+
+  /** @test */
+  public function withRightButWithoutLibraryShouldNotRenderArticleHotelDieu()
+  {
+    $this->dispatch('/admin/cms/edit/id/41');
+    $this->assertRedirect('opac/index');
+  }
+
+
+  /** @test */
+  public function withoutRightAndWithoutLibraryShouldNotRenderArticleMuseePasteur()
+  {
+    $this->dispatch('/admin/cms/edit/id/42');
+    $this->assertRedirect('opac/index');
+  }
+
+
+  /** @test */
+  public function withRightAndWithLibraryShouldRenderArticleAuthume()
+  {
+    $this->dispatch('/admin/cms/edit/id/43');
+    $this->assertRedirect('opac/index');
+  }
+}
+
+
+
+
+class CmsControllerManagedLibrariesEditAdminBibLibraryTest
+  extends CmsControllerManagedLibrariesTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    Class_Permission::createArticle()->permitTo($this->_group, $this->_hotel_category);
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('20;21;22')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB);
+  }
+
+
+  /** @test */
+  public function withRightButNoLibraryShouldNotRenderArticleAlbertCamusForm()
+  {
+    $this->dispatch('/admin/cms/edit/id/40');
+    $this->assertRedirect('opac/index');
+  }
+
+
+  /** @test */
+  public function withRightAndLibraryShouldRenderArticleHotelDieu()
+  {
+    $this->dispatch('/admin/cms/edit/id/41');
+    $this->assertXPath('//form[@action="/admin/cms/edit/id/41"]');
+  }
+
+
+  /** @test */
+  public function withoutRightButWithLibraryShouldNotRenderMuseePasteur()
+  {
+    $this->dispatch('/admin/cms/edit/id/42');
+    $this->assertRedirect('opac/index');
+  }
+
+
+  /** @test */
+  public function withNoRightAndNoLibraryShouldNotRenderArticleAuthume()
+  {
+    $this->dispatch('/admin/cms/edit/id/43');
+    $this->assertRedirect('opac/index');
+  }
+}
+
+
+
+
+class CmsControllerManagedLibrariesEditModoPortalLibraryTest
+  extends CmsControllerManagedLibrariesTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    Class_Permission::createArticle()->permitTo($this->_group, $this->_hotel_category);
+    Class_Permission::createArticle()->permitTo($this->_group, $this->_musee_category);
+    Class_Permission::createArticle()->permitTo($this->_group, $this->_authume_category);
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('20;22')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
+  }
+
+
+  /** @test */
+  public function withRightButNoLibraryShouldNotRenderArticleAlbertCamusForm()
+  {
+    $this->dispatch('/admin/cms/edit/id/40');
+    $this->assertRedirect('opac/index');
+  }
+
+
+  /** @test */
+  public function withRightButNoLibraryShouldRenderArticleHotelDieu()
+  {
+    $this->dispatch('/admin/cms/edit/id/41');
+    $this->assertXPath('//form[@action="/admin/cms/edit/id/41"]');
+  }
+
+
+  /** @test */
+  public function withoutRightButWithLibraryShouldNotRenderMuseePasteur()
+  {
+    $this->dispatch('/admin/cms/edit/id/42');
+    $this->assertXPath('//form[@action="/admin/cms/edit/id/42"]');
+  }
+
+
+  /** @test */
+  public function withRightButWithoutLibraryShouldRenderArticleAuthume()
+  {
+    $this->dispatch('/admin/cms/edit/id/43');
+    $this->assertXPath('//form[@action="/admin/cms/edit/id/43"]');
+
+  }
+
+}
diff --git a/tests/application/modules/admin/controllers/CmsControllerTest.php b/tests/application/modules/admin/controllers/CmsControllerTest.php
index 3a317365b4ed67cf5eeaab3ed1733e44fc7c8cef..5d1f72095f050fbe07691344b5fd53020adbc31d 100644
--- a/tests/application/modules/admin/controllers/CmsControllerTest.php
+++ b/tests/application/modules/admin/controllers/CmsControllerTest.php
@@ -75,6 +75,7 @@ abstract class CmsControllerTestCase extends Admin_AbstractControllerTestCase {
                                         'nom' => 'Super',
                                         'prenom' => 'Mario',
                                         'bib' => $this->annecy,
+                                        'managed_libraries' => $this->annecy->getId(),
                                         'role' => 'admin_bib',
                                         'mail' => 'admin@afi-sa.fr',
                                         'password' => 'toto',
@@ -561,19 +562,23 @@ class CmsControllerArticleDuplicateActionTest extends CmsControllerWithPermissio
   use Trait_ManageCustomFields;
   protected
     $_admin_bib,
+    $_annecy,
     $_concert;
 
   public function setUp() {
     parent::setUp();
 
+    $this->_annecy = $this->fixture(Class_Bib::class,
+                                    ['id' => 2,
+                                     'id_zone' => 4,
+                                     'libelle' => 'Annecy']);
+
     $this->_admin_bib =
       $this->fixture(Class_Users::class,
                      ['id' => 10,
                       'login' => 'AdminBibConnected',
-                      'bib' => $this->fixture(Class_Bib::class,
-                                              ['id' => 2,
-                                               'id_zone' => 4,
-                                               'libelle' => 'Annecy']),
+                      'bib' => $this->_annecy,
+                      'managed_libraries' => 2,
                       'role' => 'admin_bib',
                       'mail' => 'admin@afi-sa.fr',
                       'password' => 'toto',
@@ -608,7 +613,8 @@ class CmsControllerArticleDuplicateActionTest extends CmsControllerWithPermissio
                     'titre' => 'Concert',
                     'categorie' => $this->fixture(Class_ArticleCategorie::class,
                                                   ['id' => 23,
-                                                   'libelle' => 'A la Une']),
+                                                   'libelle' => 'A la Une',
+                                                   'bib' => $this->_annecy]),
                     'auteur' => $this->_admin_bib,
                     'description' => 'Venez nombreux ici: <img src="'
                     . BASE_URL . '/images/bonlieu.jpg" />',
diff --git a/tests/application/modules/admin/controllers/NewsletterControllerTest.php b/tests/application/modules/admin/controllers/NewsletterControllerTest.php
index 7270c0a5d8cc90ddd0269f26e4039c52032c0e68..883738502d9c999c969d36fab3dc219ccd5ea0e0 100644
--- a/tests/application/modules/admin/controllers/NewsletterControllerTest.php
+++ b/tests/application/modules/admin/controllers/NewsletterControllerTest.php
@@ -96,7 +96,7 @@ class Admin_NewsletterControllerIndexActionTest extends Admin_NewsletterControll
 
   /** @test */
   public function requestsShouldExists() {
-    $this->assertSql("SELECT `bib_admin_users`.`id_user` AS `id` FROM `bib_admin_users` WHERE (`bib_admin_users`.`id_site` = 1 AND `bib_admin_users`.`role_level` = 2) ORDER BY `bib_admin_users`.`nom` ASC");
+    $this->assertSql("SELECT `bib_admin_users`.`id_user` AS `id` FROM `bib_admin_users` WHERE (`bib_admin_users`.`id_site` IN ('1') AND `bib_admin_users`.`role_level` = 2) ORDER BY `bib_admin_users`.`nom` ASC");
   }
 
 
diff --git a/tests/application/modules/admin/controllers/OuverturesControllerTest.php b/tests/application/modules/admin/controllers/OuverturesControllerTest.php
index d4bc627c47f3edcdceec802066ac6b60ab6785f1..09192f4248d80b47ba0bcff5fbbb0cb38b77134c 100644
--- a/tests/application/modules/admin/controllers/OuverturesControllerTest.php
+++ b/tests/application/modules/admin/controllers/OuverturesControllerTest.php
@@ -751,6 +751,7 @@ class OuverturesControllerDispatchIndexWithLibraryAdminTest extends AbstractCont
                               ['id' => 89,
                                'login' => 'monteux',
                                'password' => 'ishould',
+                               'managed_libraries' => '56',
                                'id_site' => 56]);
 
     $monteux->beAdminBib()->save();
@@ -1026,4 +1027,4 @@ class OuverturesControllerIndexActionWithClosedAMTest extends OuverturesControll
   public function pageShouldContainsTwoClosedLabels() {
     $this->assertXPathCount('//td[text()="Fermé"]', 2);
   }
-}
\ No newline at end of file
+}
diff --git a/tests/application/modules/admin/controllers/ProfilControllerIndexTest.php b/tests/application/modules/admin/controllers/ProfilControllerIndexTest.php
index eea879c762e7cc55a04503d8abd903e818542e8f..0c42918e9406878531df3d26afbc1b31853930bc 100644
--- a/tests/application/modules/admin/controllers/ProfilControllerIndexTest.php
+++ b/tests/application/modules/admin/controllers/ProfilControllerIndexTest.php
@@ -21,36 +21,44 @@
 
 require_once 'AdminAbstractControllerTestCase.php';
 
-abstract class Admin_ProfilControllerIndexTestCase extends Admin_AbstractControllerTestCase {
+abstract class ProfilControllerIndexTestCase extends Admin_AbstractControllerTestCase {
   public function setUp() {
     parent::setUp();
 
+    $this->fixture(Class_Bib::class,
+                  ['id' => 5,
+                   'libelle' => 'Annecy']);
+
+    $jeunesse = $this->fixture(Class_Profil::class,
+                               ['id' => 12,
+                                'libelle' => 'Jeunesse',
+                                'id_site' => 5])
+                     ->setAccessLevel(4);
+
+    $adulte = $this->fixture(Class_Profil::class,
+                             ['id' => 8,
+                              'libelle' => 'Adulte',
+                              'commentaire' => 'Section Adulte',
+                              'id_site' => 0]);
+
+    $portail = $this->fixture(Class_Profil::class,
+                              ['id' => 1,
+                               'libelle' => 'Portail',
+                               'commentaire' => 'Accueil du portail',
+                               'id_site' => 0]);
+
+    $smartphone = $this->fixture(Class_Profil::class,
+                                 ['id' => 3,
+                                  'libelle' => 'Smartphone',
+                                  'browser' => 'telephone',
+                                  'id_site' => 0]);
+
     Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Profil')
       ->whenCalled('findAllByZoneAndBib')
-      ->answers([Class_Profil::getLoader()
-                 ->newInstanceWithId(12)
-                 ->setLibelle("Jeunesse")
-                 ->setAccessLevel(4)
-                 ->setBib(Class_Bib::getLoader()
-                          ->newInstanceWithId(5)
-                          ->setLibelle("Annecy")),
-
-                 Class_Profil::getLoader()
-                 ->newInstanceWithId(8)
-                 ->setLibelle("Adulte")
-                 ->setCommentaire("Section Adulte")
-                 ->setIdSite(0),
-
-                 Class_Profil::getLoader()
-                 ->newInstanceWithId(1)
-                 ->setLibelle("Portail")
-                 ->setCommentaire("Accueil du portail")
-                 ->setIdSite(0),
-                 Class_Profil::getLoader()
-                 ->newInstanceWithId(3)
-                 ->setLibelle("Smartphone")
-                 ->setBrowser("telephone")
-                 ->setIdSite(0)]);
+      ->answers(array($jeunesse,
+                      $adulte,
+                      $portail,
+                      $smartphone));
 
     $this->dispatch('/admin/profil/index');
   }
@@ -58,8 +66,10 @@ abstract class Admin_ProfilControllerIndexTestCase extends Admin_AbstractControl
 
 
 
-class Admin_ProfilControllerWithAdminPortailIndexTest extends Admin_ProfilControllerIndexTestCase  {
+
+class ProfilControllerIndexWithAdminPortailTest extends ProfilControllerIndexTestCase  {
   protected $_response;
+
   protected function _loginHook($account) {
     parent::_loginHook($account);
     $account->ROLE_LEVEL = 7;
@@ -133,8 +143,7 @@ class Admin_ProfilControllerWithAdminPortailIndexTest extends Admin_ProfilContro
 
   /** @test */
   public function profilPortailShouldBeVisible() {
-    $this->assertXPathContentContains("//div/ul[1]/li[2]/div",
-                                      "Portail");
+    $this->assertXPathContentContains("//div/ul[1]/li[2]/div", "Portail");
   }
 
 
@@ -161,7 +170,8 @@ class Admin_ProfilControllerWithAdminPortailIndexTest extends Admin_ProfilContro
 
 
 
-class Admin_ProfilControllerWithAdminBibIndexTest extends Admin_ProfilControllerIndexTestCase  {
+class ProfilControllerIndexWithAdminBibTest extends ProfilControllerIndexTestCase
+{
   protected function _loginHook($account) {
     parent::_loginHook($account);
     $account->ROLE_LEVEL = ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB;
diff --git a/tests/application/modules/admin/controllers/ProfilControllerManagedLibrariesTest.php b/tests/application/modules/admin/controllers/ProfilControllerManagedLibrariesTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1ad49dfe8966fdac31f281c68a1add33b3544d4b
--- /dev/null
+++ b/tests/application/modules/admin/controllers/ProfilControllerManagedLibrariesTest.php
@@ -0,0 +1,531 @@
+<?php
+/**
+ * Copyright (c) 2012-2024, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+abstract class ProfilControllerManagedLibrariesTestCase extends Admin_AbstractControllerTestCase
+{
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->fixture(Class_Bib::class, ['id' => 21,
+                                      'libelle' => 'One']);
+
+    $this->fixture(Class_Bib::class, ['id' => 22,
+                                      'libelle' => 'Two']);
+
+    $this->fixture(Class_Bib::class, ['id' => 23,
+                                      'libelle' => 'Three']);
+
+    $this->fixture(Class_Profil::class,
+                   ['id' => 428,
+                    'libelle' => 'Accueil MyBibApp',
+                    'id_site' => '21']);
+
+    $this->fixture(Class_Profil::class,
+                   ['id' => 429,
+                    'libelle' => 'Ressources numériques',
+                    'id_site' => '22']);
+
+    $this->fixture(Class_Profil::class,
+                   ['id' => 430,
+                    'libelle' => 'Accueil principal',
+                    'id_site' => '21 23']);
+
+
+    ZendAfi_Auth::getInstance()->logUser($this->_getLoggedUser());
+  }
+
+
+  protected function _createLoggedUser(): Class_Users
+  {
+    return $this->fixture(Class_Users::class,
+                          ['id' => 1,
+                           'login' => 'logged_in',
+                           'password' => 'secret',
+                           'id_site' => 1,
+                           'managed_libraries' => '',
+                           'role_level' => ZendAfi_Acl_AdminControllerRoles::SUPER_ADMIN,
+                           'last_login' => 0])
+                ->addUserGroup($this->_group);
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser();
+  }
+}
+
+
+
+
+class ProfilControllerManagedLibrariesEditAsSuperAdminTest
+  extends ProfilControllerManagedLibrariesTestCase
+{
+
+  public function setUp()
+  {
+    parent::setUp();
+    $this->dispatch('/admin/profil/edit/id_profil/428');
+  }
+
+
+  /** @test */
+  public function multiInputLibraryIdsShouldExist()
+  {
+    $this->assertXPath('//input[@name="library_ids"]');
+  }
+
+
+  /** @test */
+  public function libraryOneShouldBeInLibraryIdsElement()
+  {
+    $this->assertxpath('//input[@data-clef="21"]');
+  }
+
+
+  /** @test */
+  public function libraryTwoShouldBeInLibraryIdsElement()
+  {
+    $this->assertxpath('//input[@data-clef="22"]');
+  }
+}
+
+
+
+
+class ProfilControllerManagedLibrariesPostEditAsSuperAdminTest
+  extends ProfilControllerManagedLibrariesTestCase
+{
+
+  public function setUp()
+  {
+    parent::setUp();
+    $this->postDispatch('/admin/profil/edit/id_profil/428',
+                        ['libelle' => 'Accueil MyBibApp',
+                         'library_ids' => '21;22']);
+  }
+
+
+  /** @test */
+  public function profileAccueilMybibappShouldHaveLibrayOneAndTwoSpaceSeparated()
+  {
+    $this->assertEquals('21 22', Class_Profil::find(428)->getIdSite());
+  }
+}
+
+
+
+
+class ProfilControllerManagedLibrariesIndexAsSuperAdminTest
+  extends ProfilControllerManagedLibrariesTestCase
+{
+
+  public function setUp()
+  {
+    parent::setUp();
+    $this->dispatch('/admin/profil/index');
+  }
+
+
+  /** @test */
+  public function libraryOneShouldBePresent()
+  {
+    $this->assertXPathContentContains('//div[@class="profils"]/h2', 'One');
+  }
+
+
+  /** @test */
+  public function libraryTwoShouldBePresent()
+  {
+    $this->assertXPathContentContains('//div[@class="profils"]/h2', 'Two');
+  }
+
+
+  /** @test */
+  public function profilAccueilMybibappShouldBePresent()
+  {
+    $this->assertXPathContentContains('//div[@class="profils"]/ul/li/div',
+                                      'Accueil MyBibApp');
+  }
+
+
+  /** @test */
+  public function profilRessourcesNumeriquesShouldBePresent()
+  {
+    $this->assertXPathContentContains('//div[@class="profils"]/ul/li/div',
+                                      'Ressources numériques');
+  }
+
+
+  /** @test */
+  public function profilAccueilPrincipalShouldBePresent()
+  {
+    $this->assertXPathContentContains('//div[@class="profils"]/ul/li/div',
+                                      'Accueil principal');
+  }
+}
+
+
+
+
+class ProfilControllerManagedLibrariesIndexAsModoBibTest
+  extends ProfilControllerManagedLibrariesTestCase
+{
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->dispatch('/admin/profil/index?z=ALL&b=ALL');
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('21;22;23')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function modoBibShouldNotAccessProfilIndex()
+  {
+    $this->assertRedirect('/opac/index');
+  }
+}
+
+
+
+
+class ProfilControllerManagedLibrariesIndexAsModoPortailTest
+  extends ProfilControllerManagedLibrariesTestCase
+{
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->dispatch('/admin/profil/index?z=ALL&b=ALL');
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('21;22;23')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
+  }
+
+
+  /** @test */
+  public function modoPortalShouldNotAccessProfilIndex()
+  {
+    $this->assertRedirect('/opac/index');
+  }
+}
+
+
+
+
+class ProfilControllerManagedLibrariesIndexAsAdminBibTest
+  extends ProfilControllerManagedLibrariesTestCase
+{
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->dispatch('/admin/profil/index?z=ALL&b=ALL');
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('22;23')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB);
+  }
+
+
+  /** @test */
+  public function libraryOneShouldNotBePresent()
+  {
+    $this->assertNotXPathContentContains('//div[@class="profils"]/h2', 'One');
+  }
+
+
+  /** @test */
+  public function libraryTwoShouldBePresent()
+  {
+    $this->assertXPathContentContains('//div[@class="profils"]/h2', 'Two');
+  }
+
+
+  /** @test */
+  public function libraryThreeShouldNotBePresent()
+  {
+    $this->assertNotXPathContentContains('//div[@class="profils"]/h2', 'Three');
+  }
+
+
+  /** @test */
+  public function profilAccueilMybibappShouldNotBePresent()
+  {
+    $this->assertNotXPathContentContains('//div[@class="profils"]/ul/li/div',
+                                      'Accueil MyBibApp');
+  }
+
+
+  /** @test */
+  public function profilRessourcesNumeriquesShouldBePresent()
+  {
+    $this->assertXPathContentContains('//div[@class="profils"]/ul/li/div',
+                                      'Ressources numériques');
+  }
+
+
+  /** @test */
+  public function profilAccueilPrincipalShouldBePresent()
+  {
+    $this->assertXPathContentContains('//div[@class="profils"]/ul/li/div',
+                                      'Accueil principal');
+  }
+}
+
+
+
+
+class ProfilControllerManagedLibrariesIndexAsAdminPortailTest
+  extends ProfilControllerManagedLibrariesTestCase
+{
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->dispatch('/admin/profil/index?z=ALL&b=ALL');
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL);
+  }
+
+
+  /** @test */
+  public function libraryOneShouldBePresent()
+  {
+    $this->assertXPathContentContains('//div[@class="profils"]/h2', 'One');
+  }
+
+
+  /** @test */
+  public function libraryTwoShouldBePresent()
+  {
+    $this->assertXPathContentContains('//div[@class="profils"]/h2', 'Two');
+  }
+
+
+  /** @test */
+  public function profilAccueilMybibappShouldBePresent()
+  {
+    $this->assertXPathContentContains('//div[@class="profils"]/ul/li/div',
+                                      'Accueil MyBibApp');
+  }
+
+
+  /** @test */
+  public function profilRessourcesNumeriquesShouldBePresent()
+  {
+    $this->assertXPathContentContains('//div[@class="profils"]/ul/li/div',
+                                      'Ressources numériques');
+  }
+
+
+  /** @test */
+  public function profilAccueilPrincipalShouldBePresent()
+  {
+    $this->assertXPathContentContains('//div[@class="profils"]/ul/li/div',
+                                      'Accueil principal');
+  }
+}
+
+
+
+
+class ProfilControllerManagedLibrariesEditAsModoBibTest
+  extends ProfilControllerManagedLibrariesTestCase
+{
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('21;22;23')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function userShouldEditAccueilMybibapp()
+  {
+    $this->dispatch('/admin/profil/edit/id_profil/428');
+    $this->assertRedirect('/opac/index');
+  }
+
+
+  /** @test */
+  public function userShouldEditRessourceNumerique()
+  {
+    $this->dispatch('/admin/profil/edit/id_profil/429');
+    $this->assertRedirect('/opac/index');
+  }
+
+
+  /** @test */
+  public function userShouldEditAccueilPrincipal()
+  {
+    $this->dispatch('/admin/profil/edit/id_profil/430');
+    $this->assertRedirect('/opac/index');
+  }
+}
+
+
+
+
+class ProfilControllerManagedLibrariesEditAsAdminBibTest
+  extends ProfilControllerManagedLibrariesTestCase
+{
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('21;23')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB);
+  }
+
+
+  /** @test */
+  public function userShouldEditAccueilMybibapp()
+  {
+    $this->dispatch('/admin/profil/edit/id_profil/428');
+    $this->assertXPath('//form[@action="/admin/profil/edit/id_profil/428"]');
+  }
+
+
+  /** @test */
+  public function userShouldEditRessourceNumerique()
+  {
+    $this->dispatch('/admin/profil/edit/id_profil/429');
+    $this->assertRedirect('/opac/index');
+  }
+
+
+  /** @test */
+  public function userShouldEditAccueilPrincipal()
+  {
+    $this->dispatch('/admin/profil/edit/id_profil/430');
+    $this->assertXPath('//form[@action="/admin/profil/edit/id_profil/430"]');
+  }
+}
+
+
+
+
+class ProfilControllerManagedLibrariesEditAsModoPortailTest
+  extends ProfilControllerManagedLibrariesTestCase
+{
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('21;22;23')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
+  }
+
+
+  /** @test */
+  public function userShouldEditAccueilMybibapp()
+  {
+    $this->dispatch('/admin/profil/edit/id_profil/428');
+    $this->assertRedirect('/opac/index');
+  }
+
+
+  /** @test */
+  public function userShouldEditRessourceNumerique()
+  {
+    $this->dispatch('/admin/profil/edit/id_profil/429');
+    $this->assertRedirect('/opac/index');
+  }
+
+
+  /** @test */
+  public function userShouldEditAccueilPrincipal()
+  {
+    $this->dispatch('/admin/profil/edit/id_profil/430');
+    $this->assertRedirect('/opac/index');
+  }
+}
+
+
+
+
+class ProfilControllerManagedLibrariesEditAsAdminPortailTest
+  extends ProfilControllerManagedLibrariesTestCase
+{
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('21;22;23')
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL);
+  }
+
+
+  /** @test */
+  public function userShouldEditAccueilMybibapp()
+  {
+    $this->dispatch('/admin/profil/edit/id_profil/428');
+    $this->assertXPath('//form[@action="/admin/profil/edit/id_profil/428"]');
+  }
+
+
+  /** @test */
+  public function userShouldEditRessourceNumerique()
+  {
+    $this->dispatch('/admin/profil/edit/id_profil/429');
+    $this->assertXPath('//form[@action="/admin/profil/edit/id_profil/429"]');
+  }
+
+
+  /** @test */
+  public function userShouldEditAccueilPrincipal()
+  {
+    $this->dispatch('/admin/profil/edit/id_profil/430');
+    $this->assertXPath('//form[@action="/admin/profil/edit/id_profil/430"]');
+  }
+}
diff --git a/tests/application/modules/admin/controllers/ProfilControllerPageAccueilTest.php b/tests/application/modules/admin/controllers/ProfilControllerPageAccueilTest.php
index 2126c9e300294455b60390d2bd1cec551fd13109..791f16eb6cd9e4b0d82a1d27dc96c2cc4c4fba3f 100644
--- a/tests/application/modules/admin/controllers/ProfilControllerPageAccueilTest.php
+++ b/tests/application/modules/admin/controllers/ProfilControllerPageAccueilTest.php
@@ -555,7 +555,7 @@ abstract class Admin_ProfilControllerPageAccueilWithWidgetInBannerTestCase exten
   public function setUp() {
     parent::setUp();
 
-    $this->fixture('Class_Profil',
+    $this->fixture(Class_Profil::class,
                    ['id' => 3,
                     'libelle' => 'My profil']);
 
@@ -631,17 +631,21 @@ class Admin_ProfilControllerPageAccueilWithMenuBoiteEnabledTest extends Admin_Ab
   public function setUp() {
     parent::setUp();
 
-  $this->fixture('Class_Profil', ['id' => 712, 'libelle' => 'Parent profile',
-                                                'cfg_accueil' => 'a:4:{s:7:"modules";a:12:{i:5;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:8:{s:4:"menu";s:3:"1-V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"1";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:7:"Valider";s:7:"Valider";s:0:"";s:0:"";}}i:2;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:16:{s:5:"titre";s:14:"ne_pas_toucher";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:1:"1";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:1:"0";s:8:"rss_avis";s:1:"0";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:10:"boite_vide";s:11:"style_liste";s:4:"none";s:13:"styles_reload";s:1:"0";s:7:"Valider";s:7:"Valider";s:0:"";s:0:"";}}i:4;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:7;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:1;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:3;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:8;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:9;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:10;a:3:{s:8:"division";s:1:"3";s:11:"type_module";s:6:"PANIER";s:11:"preferences";a:3:{s:5:"titre";s:6:"Panier";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:11;a:3:{s:8:"division";s:1:"3";s:11:"type_module";s:6:"PANIER";s:11:"preferences";a:3:{s:5:"titre";s:6:"Panier";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:12;a:3:{s:8:"division";s:1:"3";s:11:"type_module";s:6:"PANIER";s:11:"preferences";a:2:{s:5:"titre";s:6:"Panier";s:5:"boite";s:0:"";}}i:6;a:3:{s:11:"type_module";s:5:"LOGIN";s:11:"preferences";a:16:{s:5:"titre";s:18:"Mon compte lecteur";s:14:"titre_connecte";s:0:"";s:11:"identifiant";s:12:"N° de carte";s:19:"identifiant_exemple";s:0:"";s:12:"mot_de_passe";s:19:"Année de naissance";s:20:"mot_de_passe_exemple";s:0:"";s:14:"lien_connexion";s:12:"Se connecter";s:24:"lien_mot_de_passe_oublie";s:25:"» Mot de passe oublié ?";s:17:"lien_creer_compte";s:16:"» S\'enregistrer";s:16:"message_connecte";s:9:"Bienvenue";s:11:"lien_compte";s:10:"Mon compte";s:17:"lien_deconnection";s:15:"Se déconnecter";s:16:"autocomplete_off";s:1:"1";s:15:"profil_redirect";s:0:"";s:22:"profil_logout_redirect";s:0:"";s:5:"boite";s:21:"boite_banniere_droite";}s:8:"division";s:1:"4";}}s:14:"use_parent_css";s:1:"1";s:7:"sitemap";s:1:"1";s:8:"page_css";s:0:"";}']);
-
-    $this->fixture('Class_Profil', ['id' => 713,
-                                    'parent_id' => 712,
-                                    'id_site' => 0,
-                                    'libelle' => 'My page',
-                                    'cfg_accueil' => 'a:4:{s:7:"modules";a:8:{i:2;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:3;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:1;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:4;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:8;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:5;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:10;a:3:{s:8:"division";s:1:"3";s:11:"type_module";s:6:"PANIER";s:11:"preferences";a:3:{s:5:"titre";s:6:"Panier";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:11;a:3:{s:8:"division";s:1:"4";s:11:"type_module";s:5:"LOGIN";s:11:"preferences";a:17:{s:5:"titre";s:18:"Mon compte lecteur";s:14:"titre_connecte";s:0:"";s:11:"identifiant";s:12:"N° de carte";s:19:"identifiant_exemple";s:0:"";s:12:"mot_de_passe";s:19:"Année de naissance";s:20:"mot_de_passe_exemple";s:0:"";s:14:"lien_connexion";s:12:"Se connecter";s:24:"lien_mot_de_passe_oublie";s:25:"» Mot de passe oublié ?";s:17:"lien_creer_compte";s:16:"» S\'enregistrer";s:16:"message_connecte";s:9:"Bienvenue";s:11:"lien_compte";s:10:"Mon compte";s:17:"lien_deconnection";s:15:"Se déconnecter";s:16:"autocomplete_off";s:1:"1";s:15:"profil_redirect";s:0:"";s:22:"profil_logout_redirect";s:0:"";s:5:"boite";s:21:"boite_banniere_droite";s:0:"";s:0:"";}}}s:14:"use_parent_css";s:1:"1";s:7:"sitemap";s:1:"1";s:8:"page_css";s:0:"";}',
+    $this->fixture(Class_Profil::class,
+                   ['id' => 712,
+                    'libelle' => 'Parent profile',
+                    'cfg_accueil' => 'a:4:{s:7:"modules";a:12:{i:5;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:8:{s:4:"menu";s:3:"1-V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"1";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:7:"Valider";s:7:"Valider";s:0:"";s:0:"";}}i:2;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:16:{s:5:"titre";s:14:"ne_pas_toucher";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:1:"1";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:1:"0";s:8:"rss_avis";s:1:"0";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:10:"boite_vide";s:11:"style_liste";s:4:"none";s:13:"styles_reload";s:1:"0";s:7:"Valider";s:7:"Valider";s:0:"";s:0:"";}}i:4;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:7;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:1;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:3;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:8;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:9;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:10;a:3:{s:8:"division";s:1:"3";s:11:"type_module";s:6:"PANIER";s:11:"preferences";a:3:{s:5:"titre";s:6:"Panier";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:11;a:3:{s:8:"division";s:1:"3";s:11:"type_module";s:6:"PANIER";s:11:"preferences";a:3:{s:5:"titre";s:6:"Panier";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:12;a:3:{s:8:"division";s:1:"3";s:11:"type_module";s:6:"PANIER";s:11:"preferences";a:2:{s:5:"titre";s:6:"Panier";s:5:"boite";s:0:"";}}i:6;a:3:{s:11:"type_module";s:5:"LOGIN";s:11:"preferences";a:16:{s:5:"titre";s:18:"Mon compte lecteur";s:14:"titre_connecte";s:0:"";s:11:"identifiant";s:12:"N° de carte";s:19:"identifiant_exemple";s:0:"";s:12:"mot_de_passe";s:19:"Année de naissance";s:20:"mot_de_passe_exemple";s:0:"";s:14:"lien_connexion";s:12:"Se connecter";s:24:"lien_mot_de_passe_oublie";s:25:"» Mot de passe oublié ?";s:17:"lien_creer_compte";s:16:"» S\'enregistrer";s:16:"message_connecte";s:9:"Bienvenue";s:11:"lien_compte";s:10:"Mon compte";s:17:"lien_deconnection";s:15:"Se déconnecter";s:16:"autocomplete_off";s:1:"1";s:15:"profil_redirect";s:0:"";s:22:"profil_logout_redirect";s:0:"";s:5:"boite";s:21:"boite_banniere_droite";}s:8:"division";s:1:"4";}}s:14:"use_parent_css";s:1:"1";s:7:"sitemap";s:1:"1";s:8:"page_css";s:0:"";}']);
+
+    $this->fixture(Class_Profil::class,
+                   ['id' => 713,
+                    'parent_id' => 712,
+                    'id_site' => 0,
+                    'libelle' => 'My page',
+                    'cfg_accueil' => 'a:4:{s:7:"modules";a:8:{i:2;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:3;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:1;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:4;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:8;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:5;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:10;a:3:{s:8:"division";s:1:"3";s:11:"type_module";s:6:"PANIER";s:11:"preferences";a:3:{s:5:"titre";s:6:"Panier";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:11;a:3:{s:8:"division";s:1:"4";s:11:"type_module";s:5:"LOGIN";s:11:"preferences";a:17:{s:5:"titre";s:18:"Mon compte lecteur";s:14:"titre_connecte";s:0:"";s:11:"identifiant";s:12:"N° de carte";s:19:"identifiant_exemple";s:0:"";s:12:"mot_de_passe";s:19:"Année de naissance";s:20:"mot_de_passe_exemple";s:0:"";s:14:"lien_connexion";s:12:"Se connecter";s:24:"lien_mot_de_passe_oublie";s:25:"» Mot de passe oublié ?";s:17:"lien_creer_compte";s:16:"» S\'enregistrer";s:16:"message_connecte";s:9:"Bienvenue";s:11:"lien_compte";s:10:"Mon compte";s:17:"lien_deconnection";s:15:"Se déconnecter";s:16:"autocomplete_off";s:1:"1";s:15:"profil_redirect";s:0:"";s:22:"profil_logout_redirect";s:0:"";s:5:"boite";s:21:"boite_banniere_droite";s:0:"";s:0:"";}}}s:14:"use_parent_css";s:1:"1";s:7:"sitemap";s:1:"1";s:8:"page_css";s:0:"";}',
                                     ]);
 
-    $this->fixture('Class_AdminVar',['id'=>'MENU_BOITE', 'valeur' => 1]);
+    $this->fixture(Class_AdminVar::class,
+                   ['id'=>'MENU_BOITE', 'valeur' => 1]);
 
     $this->postDispatch('/admin/profil/accueil/id_profil/713', ['libelle' => 'test',
                                                                 'division1' => 'NEWS-2;NEWS-3;KIOSQUE-1;KIOSQUE-4;',
@@ -678,8 +682,9 @@ class Admin_ProfilControllerPageAccueilRegression45558Test extends Admin_ProfilC
 
   public function setUp() {
     parent::setUp();
-    $this->fixture('Class_Profil', ['id' => 23,
-                                    'libelle' => 'My page']);
+    $this->fixture(Class_Profil::class,
+                   ['id' => 23,
+                    'libelle' => 'My page']);
 
     $this->postDispatch('/admin/profil/accueil/id_profil/23',
                         ['libelle' => 'My page',
@@ -703,16 +708,20 @@ class Admin_ProfilControllerPageAccueilClearBannerFromChildTest extends Admin_Ab
   public function setUp() {
     parent::setUp();
 
-  $this->fixture('Class_Profil', ['id' => 712, 'libelle' => 'Parent profile',
-                                                'cfg_accueil' => 'a:4:{s:7:"modules";a:8:{i:2;a:3:{s:8:"division";s:1:"4";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:3;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:1;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:4;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:8;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:5;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:10;a:3:{s:8:"division";s:1:"3";s:11:"type_module";s:6:"PANIER";s:11:"preferences";a:3:{s:5:"titre";s:6:"Panier";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:11;a:3:{s:8:"division";s:1:"4";s:11:"type_module";s:5:"LOGIN";s:11:"preferences";a:17:{s:5:"titre";s:18:"Mon compte lecteur";s:14:"titre_connecte";s:0:"";s:11:"identifiant";s:12:"N° de carte";s:19:"identifiant_exemple";s:0:"";s:12:"mot_de_passe";s:19:"Année de naissance";s:20:"mot_de_passe_exemple";s:0:"";s:14:"lien_connexion";s:12:"Se connecter";s:24:"lien_mot_de_passe_oublie";s:25:"» Mot de passe oublié ?";s:17:"lien_creer_compte";s:16:"» S\'enregistrer";s:16:"message_connecte";s:9:"Bienvenue";s:11:"lien_compte";s:10:"Mon compte";s:17:"lien_deconnection";s:15:"Se déconnecter";s:16:"autocomplete_off";s:1:"1";s:15:"profil_redirect";s:0:"";s:22:"profil_logout_redirect";s:0:"";s:5:"boite";s:21:"boite_banniere_droite";s:0:"";s:0:"";}}}s:14:"use_parent_css";s:1:"1";s:7:"sitemap";s:1:"1";s:8:"page_css";s:0:"";}']);
+    $this->fixture(Class_Profil::class,
+                   ['id' => 712,
+                    'libelle' => 'Parent profile',
+                    'cfg_accueil' => 'a:4:{s:7:"modules";a:8:{i:2;a:3:{s:8:"division";s:1:"4";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:3;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:1;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:4;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:8;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:5;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:10;a:3:{s:8:"division";s:1:"3";s:11:"type_module";s:6:"PANIER";s:11:"preferences";a:3:{s:5:"titre";s:6:"Panier";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:11;a:3:{s:8:"division";s:1:"4";s:11:"type_module";s:5:"LOGIN";s:11:"preferences";a:17:{s:5:"titre";s:18:"Mon compte lecteur";s:14:"titre_connecte";s:0:"";s:11:"identifiant";s:12:"N° de carte";s:19:"identifiant_exemple";s:0:"";s:12:"mot_de_passe";s:19:"Année de naissance";s:20:"mot_de_passe_exemple";s:0:"";s:14:"lien_connexion";s:12:"Se connecter";s:24:"lien_mot_de_passe_oublie";s:25:"» Mot de passe oublié ?";s:17:"lien_creer_compte";s:16:"» S\'enregistrer";s:16:"message_connecte";s:9:"Bienvenue";s:11:"lien_compte";s:10:"Mon compte";s:17:"lien_deconnection";s:15:"Se déconnecter";s:16:"autocomplete_off";s:1:"1";s:15:"profil_redirect";s:0:"";s:22:"profil_logout_redirect";s:0:"";s:5:"boite";s:21:"boite_banniere_droite";s:0:"";s:0:"";}}}s:14:"use_parent_css";s:1:"1";s:7:"sitemap";s:1:"1";s:8:"page_css";s:0:"";}']);
 
-    $this->fixture('Class_Profil', ['id' => 713,
-                                    'parent_id' => 712,
-                                    'id_site' => 0,
-                                    'libelle' => 'My page',
-                                    'cfg_accueil' => 'a:4:{s:7:"modules";a:8:{i:2;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:3;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:1;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:4;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:8;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:5;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:10;a:3:{s:8:"division";s:1:"3";s:11:"type_module";s:6:"PANIER";s:11:"preferences";a:3:{s:5:"titre";s:6:"Panier";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:11;a:3:{s:8:"division";s:1:"4";s:11:"type_module";s:5:"LOGIN";s:11:"preferences";a:17:{s:5:"titre";s:18:"Mon compte lecteur";s:14:"titre_connecte";s:0:"";s:11:"identifiant";s:12:"N° de carte";s:19:"identifiant_exemple";s:0:"";s:12:"mot_de_passe";s:19:"Année de naissance";s:20:"mot_de_passe_exemple";s:0:"";s:14:"lien_connexion";s:12:"Se connecter";s:24:"lien_mot_de_passe_oublie";s:25:"» Mot de passe oublié ?";s:17:"lien_creer_compte";s:16:"» S\'enregistrer";s:16:"message_connecte";s:9:"Bienvenue";s:11:"lien_compte";s:10:"Mon compte";s:17:"lien_deconnection";s:15:"Se déconnecter";s:16:"autocomplete_off";s:1:"1";s:15:"profil_redirect";s:0:"";s:22:"profil_logout_redirect";s:0:"";s:5:"boite";s:21:"boite_banniere_droite";s:0:"";s:0:"";}}}s:14:"use_parent_css";s:1:"1";s:7:"sitemap";s:1:"1";s:8:"page_css";s:0:"";}']);
+    $this->fixture(Class_Profil::class,
+                   ['id' => 713,
+                    'parent_id' => 712,
+                    'id_site' => 0,
+                    'libelle' => 'My page',
+                    'cfg_accueil' => 'a:4:{s:7:"modules";a:8:{i:2;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:3;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:4:"NEWS";s:11:"preferences";a:13:{s:5:"titre";s:8:"Articles";s:8:"type_aff";s:1:"1";s:12:"id_categorie";s:0:"";s:8:"id_items";s:0:"";s:6:"nb_aff";s:1:"1";s:10:"nb_analyse";s:1:"5";s:13:"display_order";s:9:"Selection";s:19:"display_titles_only";s:0:"";s:8:"rss_avis";s:1:"1";s:14:"op_largeur_img";s:3:"200";s:16:"op_hauteur_boite";s:3:"400";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:1;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:4;a:3:{s:8:"division";s:1:"1";s:11:"type_module";s:7:"KIOSQUE";s:11:"preferences";a:23:{s:5:"titre";s:7:"Kiosque";s:11:"style_liste";s:10:"slide_show";s:10:"nb_notices";s:2:"20";s:8:"only_img";s:1:"1";s:9:"aleatoire";s:1:"1";s:3:"tri";s:1:"1";s:10:"nb_analyse";s:2:"50";s:14:"op_hauteur_img";s:1:"0";s:13:"op_transition";s:0:"";s:14:"op_largeur_img";s:1:"0";s:16:"op_hauteur_boite";s:1:"0";s:11:"op_captions";s:1:"0";s:11:"op_autoplay";s:1:"0";s:10:"op_visible";s:1:"0";s:8:"op_speed";s:1:"0";s:7:"op_auto";s:1:"0";s:9:"op_scroll";s:1:"1";s:8:"rss_avis";s:1:"1";s:12:"id_catalogue";s:1:"0";s:9:"id_panier";s:1:"0";s:15:"profil_redirect";s:0:"";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:8;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:5;a:3:{s:8:"division";s:1:"2";s:11:"type_module";s:13:"MENU_VERTICAL";s:11:"preferences";a:7:{s:4:"menu";s:1:"V";s:14:"afficher_titre";s:1:"1";s:11:"menu_deplie";s:1:"0";s:8:"new_html";s:1:"0";s:5:"boite";s:0:"";s:5:"titre";s:0:"";s:0:"";s:0:"";}}i:10;a:3:{s:8:"division";s:1:"3";s:11:"type_module";s:6:"PANIER";s:11:"preferences";a:3:{s:5:"titre";s:6:"Panier";s:5:"boite";s:0:"";s:0:"";s:0:"";}}i:11;a:3:{s:8:"division";s:1:"4";s:11:"type_module";s:5:"LOGIN";s:11:"preferences";a:17:{s:5:"titre";s:18:"Mon compte lecteur";s:14:"titre_connecte";s:0:"";s:11:"identifiant";s:12:"N° de carte";s:19:"identifiant_exemple";s:0:"";s:12:"mot_de_passe";s:19:"Année de naissance";s:20:"mot_de_passe_exemple";s:0:"";s:14:"lien_connexion";s:12:"Se connecter";s:24:"lien_mot_de_passe_oublie";s:25:"» Mot de passe oublié ?";s:17:"lien_creer_compte";s:16:"» S\'enregistrer";s:16:"message_connecte";s:9:"Bienvenue";s:11:"lien_compte";s:10:"Mon compte";s:17:"lien_deconnection";s:15:"Se déconnecter";s:16:"autocomplete_off";s:1:"1";s:15:"profil_redirect";s:0:"";s:22:"profil_logout_redirect";s:0:"";s:5:"boite";s:21:"boite_banniere_droite";s:0:"";s:0:"";}}}s:14:"use_parent_css";s:1:"1";s:7:"sitemap";s:1:"1";s:8:"page_css";s:0:"";}']);
 
-    $this->fixture('Class_AdminVar',['id'=>'MENU_BOITE', 'valeur' => 1]);
+    $this->fixture(Class_AdminVar::class,
+                   ['id'=>'MENU_BOITE', 'valeur' => 1]);
   }
 
 
@@ -737,4 +746,4 @@ class Admin_ProfilControllerPageAccueilClearBannerFromChildTest extends Admin_Ab
                                                                 'division4' => 'LOGIN-11;NEWS-2;']);
     $this->assertEquals([11, 2], array_keys(Class_Profil::find(712)->getBannerBoxes()));
   }
-}
\ No newline at end of file
+}
diff --git a/tests/application/modules/admin/controllers/ProfilControllerTest.php b/tests/application/modules/admin/controllers/ProfilControllerTest.php
index 78a794e661efde02bfcf5ac60ac71023f59305ef..9b8194b76e7f0a18a95d77cd42fe72351b8df891 100644
--- a/tests/application/modules/admin/controllers/ProfilControllerTest.php
+++ b/tests/application/modules/admin/controllers/ProfilControllerTest.php
@@ -55,20 +55,21 @@ abstract class Admin_ProfilControllerProfilJeunesseTestCase extends Admin_Abstra
                                      'resa' => 2]];
 
 
-    $this->profil_jeunesse = $this->fixture('Class_Profil',
-                                            ['id' => 5,
-                                             'browser' => 'opac',
-                                             'titre_site' => 'Médiathèque de Melun',
-                                             'libelle' => 'Profil Jeunesse',
-                                             'commentaire' => 'Pour les jeunes',
-                                             'skin' => 'modele',
-                                             'cfg_site' => $cfg_site,
-                                             'cfg_notice' => $cfg_notice,
-                                             'mail_site' => 'tintin@herge.be',
-                                             'mail_suggestion_achat' => 'suggestion@herge.be',
-                                             'hauteur_banniere' => 150,
-                                             'boite_login_in_banniere' => true,
-                                             'rewrite_url' => 'jeunesse']);
+    $this->profil_jeunesse = $this
+      ->fixture(Class_Profil::class,
+                ['id' => 5,
+                 'browser' => 'opac',
+                 'titre_site' => 'Médiathèque de Melun',
+                 'libelle' => 'Profil Jeunesse',
+                 'commentaire' => 'Pour les jeunes',
+                 'skin' => 'modele',
+                 'cfg_site' => $cfg_site,
+                 'cfg_notice' => $cfg_notice,
+                 'mail_site' => 'tintin@herge.be',
+                 'mail_suggestion_achat' => 'suggestion@herge.be',
+                 'hauteur_banniere' => 150,
+                 'boite_login_in_banniere' => true,
+                 'rewrite_url' => 'jeunesse']);
 
     Class_Profil::setCurrentProfil($this->profil_jeunesse);
 
@@ -173,7 +174,7 @@ class Admin_ProfilControllerEditProfilJeunesseTest extends Admin_ProfilControlle
 
   /** @test */
   public function shouldDisplayBibSelection() {
-    $this->assertXPath('//select[@name="id_site"]');
+    $this->assertXPath('//input[@name="library_ids"]');
   }
 
 
@@ -903,21 +904,23 @@ abstract class Admin_ProfilControllerProfilJeunesseWithPagesTestCase extends Adm
   public function setUp() {
     parent::setUp();
 
+    $this->page_jeux = $this
+      ->fixture(Class_Profil::class,
+                ['id' => 12,
+                 'parent_id' => $this->profil_jeunesse->getId(),
+                 'libelle' => 'Jeux'
+                ]);
 
-    $this->page_jeux = Class_Profil::getLoader()
-      ->newInstanceWithId(12)
-      ->setParentId($this->profil_jeunesse->getId())
-      ->setLibelle('Jeux');
-
-
-    $this->page_musique = Class_Profil::getLoader()
-      ->newInstanceWithId(23)
-      ->setParentId($this->profil_jeunesse->getId())
-      ->setLibelle('Musique');
+    $this->page_musique = $this
+      ->fixture(Class_Profil::class,
+                ['id' => 23,
+                 'parent_id' => $this->profil_jeunesse->getId(),
+                 'libelle' => 'Musique'
+                ]);
 
     $this->profil_jeunesse->setSubProfils([$this->page_jeux, $this->page_musique]);
 
-    Class_Profil::getLoader()
+    $this->profil_wrapper
       ->whenCalled('findAllByZoneAndBib')
       ->answers([$this->profil_jeunesse, $this->page_jeux, $this->page_musique]);
   }
@@ -928,7 +931,7 @@ abstract class Admin_ProfilControllerProfilJeunesseWithPagesTestCase extends Adm
 class Admin_ProfilControllerProfilPanelTest extends Admin_ProfilControllerProfilJeunesseWithPagesTestCase {
   public function setUp() {
     parent::setUp();
-    $this->dispatch('admin/profil', true);
+    $this->dispatch('admin/profil');
   }
 
 
@@ -1574,13 +1577,15 @@ class Admin_ProfilControllerEditLibraryFilterTest extends Admin_AbstractControll
                                              ['id' => 12,
                                               'libelle' => 'Haute-Savoie'])]);
 
+    Class_Profil::find(1)->setIdSite('9')->assertSave();
+
     $this->dispatch('/admin/profil/edit/id_profil/1', true);
   }
 
 
   /** @test */
   public function annecyFilterShouldBePresent() {
-    $this->assertXPathContentContains('//select[@name="id_site"]//option[@value="9"]',
+    $this->assertXPathContentContains('//div[@id="library_ids_aff"]/span[@class="selected"]',
                                       'Annecy');
   }
 }
diff --git a/tests/application/modules/admin/controllers/RssControllerTest.php b/tests/application/modules/admin/controllers/RssControllerTest.php
index 00ffc13d8ab3b8e944e51748d22247664f58ec3c..67013f18ac366b3aaff0dbb7122956682c94f878 100644
--- a/tests/application/modules/admin/controllers/RssControllerTest.php
+++ b/tests/application/modules/admin/controllers/RssControllerTest.php
@@ -138,7 +138,7 @@ class Admin_RssControllerPostCatEditActionTest extends Admin_RssControllerTestCa
 
   /** @test */
   public function responseShouldRedirectToIndexWithZoneAllBibOne() {
-    $this->assertRedirectTo('/admin/rss/index/z/ALL/b/1');
+    $this->assertRedirectTo('/admin/rss/index/z/PORTAIL/b/PORTAIL');
   }
 }
 
@@ -221,7 +221,7 @@ class Admin_RssControllerPostCatAddActionTest extends Admin_RssControllerTestCas
 
   /** @test */
   public function responseShouldRedirectToIndexWithZoneAllBibOne() {
-    $this->assertRedirectTo('/admin/rss/index/z/ALL/b/1');
+    $this->assertRedirectTo('/admin/rss/index/z/PORTAIL/b/PORTAIL');
   }
 }
 
diff --git a/tests/application/modules/admin/controllers/UserGroupControllerTest.php b/tests/application/modules/admin/controllers/UserGroupControllerTest.php
index 0c38555547a0d67a32d11dcc6b258d76930b1a6d..2573205d318f5555d550d1643ab1ea2672b99c3c 100644
--- a/tests/application/modules/admin/controllers/UserGroupControllerTest.php
+++ b/tests/application/modules/admin/controllers/UserGroupControllerTest.php
@@ -258,7 +258,7 @@ class Admin_UserGroupControllerIndexTest extends Admin_UserGroupControllerTestCa
   public function requestShouldExists() {
     $this->assertSqlEquals(["SELECT `int_bib`.`sigb`, `int_bib`.`comm_params` FROM `int_bib` WHERE (`int_bib`.`sigb` != 0) GROUP BY `int_bib`.`sigb`, `int_bib`.`comm_params`",
                             "SELECT COUNT(*) AS `numberof` FROM `bib_admin_users`",
-                            "SELECT COUNT(*) AS `numberof` FROM `bib_admin_users` WHERE (`bib_admin_users`.`id_site` = '9' AND `bib_admin_users`.`role_level` = '3')"]);
+                            "SELECT COUNT(*) AS `numberof` FROM `bib_admin_users` WHERE (`bib_admin_users`.`id_site` IN ('9') AND `bib_admin_users`.`role_level` = '3')"]);
   }
 
 
@@ -448,6 +448,13 @@ class Admin_UserGroupControllerAddTest extends Admin_UserGroupControllerTestCase
   }
 
 
+  /** @test */
+  public function aCheckBoxShouldContainsRightAdministrationGestionDesProfils() {
+    $this->assertRightInputFor(46,
+                               'Administration: Gestion des profils');
+  }
+
+
   protected function assertRightInputFor($value, $label) {
     $this->assertXPathContentContains('//input[@name="rights_permissions[]"][@value="right-' . $value. '"]/parent::label',
                                       $label);
@@ -746,13 +753,13 @@ class Admin_UserGroupControllerEditGroupModerateursBibTest
 
   /** @test */
   public function librarySelectShouldBePresent() {
-    $this->assertXPath('//select[@name="search_id_site"]');
+    $this->assertXPath('//input[@name="search_id_site"]');
   }
 
 
   /** @test */
   public function librarySelectShouldHaveAnnecySelected() {
-    $this->assertXPath('//select[@name="search_id_site"]//option[@value="9"][@selected="selected"]');
+    $this->assertXPathContentContains('//div[@id="search_id_site_aff"]/span', 'Annecy');
   }
 }
 
@@ -1638,6 +1645,102 @@ class Admin_UserGroupControllerEditMembersWithPaginationAsAutomaticUserGroupTest
 
 
 
+class Admin_UserGroupControllerEditMembersWithMultiLibrariesDynamicUserGroupTest
+  extends Admin_AbstractControllerTestCase {
+
+  public function setup() {
+    parent::setup();
+
+    $this->fixture(Class_Users::class,
+                   ['id' => 10001,
+                    'idabon' => 10001,
+                    'nom' => 'User 10001',
+                    'login' => 'user10001',
+                    'last_login' => '',
+                    'password' => 'secret',
+                    'id_site' => 20001,
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB]);
+
+    $this->fixture(Class_Users::class,
+                   ['id' => 10002,
+                    'idabon' => 10002,
+                    'nom' => 'User 10002',
+                    'login' => 'user10002',
+                    'last_login' => '',
+                    'password' => 'secret',
+                    'id_site' => 20002,
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB]);
+
+    $this->fixture(Class_Users::class,
+                   ['id' => 10003,
+                    'idabon' => 10003,
+                    'nom' => 'User 10003',
+                    'login' => 'user10003',
+                    'last_login' => '',
+                    'password' => 'secret',
+                    'id_site' => 20001,
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::MODO_BIB]);
+
+    $this->fixture(Class_Users::class,
+                   ['id' => 10004,
+                    'idabon' => 10004,
+                    'nom' => 'User 10004',
+                    'login' => 'user10004',
+                    'last_login' => '',
+                    'password' => 'secret',
+                    'id_site' => 20003,
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB]);
+
+    $this->fixture(Class_UserGroup::class,
+                   ['id' => 1,
+                    'protected' => false,
+                    'libelle' => "Group",
+                    'group_type' => Class_UserGroup::TYPE_DYNAMIC,
+                    'filters' => json_encode(['search_role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
+                                              'search_id_site' => '20001;20002'])]);
+
+    $this->dispatch('admin/usergroup/editmembers/id/1');
+  }
+
+
+  /** @test */
+  public function nb2UsersShouldBeDisplay() {
+    $this->assertXPathContentContains('//div','2 utilisateurs');
+  }
+
+
+  /** @test */
+  public function user10001ShouldBeDisplayed()
+  {
+    $this->assertXPathContentContains('//tbody/tr/td', 'User 10001');
+  }
+
+
+  /** @test */
+  public function user10002ShouldBeDisplayed()
+  {
+    $this->assertXPathContentContains('//tbody/tr/td', 'User 10002');
+  }
+
+
+  /** @test */
+  public function user10003ShouldNotBeDisplayed()
+  {
+    $this->assertNotXPathContentContains('//tbody/tr/td', 'User 10003');
+  }
+
+
+  /** @test */
+  public function user10004ShouldNotBeDisplayed()
+  {
+    $this->assertNotXPathContentContains('//tbody/tr/td', 'User 10004');
+  }
+}
+
+
+
+
+
 class Admin_UserGroupControllerEditMembersNewsletterDedicatedUserGroupTest
   extends Admin_AbstractControllerTestCase {
 
diff --git a/tests/application/modules/admin/controllers/UsersControllerDynamicGroupsTest.php b/tests/application/modules/admin/controllers/UsersControllerDynamicGroupsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..adb9d0a29503cf405e37ffb018f2bfc75036bc58
--- /dev/null
+++ b/tests/application/modules/admin/controllers/UsersControllerDynamicGroupsTest.php
@@ -0,0 +1,109 @@
+<?php
+/**
+ * Copyright (c) 2012-2024, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+abstract class UsersControllerDynamicGroupsTestCase extends Admin_AbstractControllerTestCase
+{
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->fixture(Class_UserGroupCategorie::class,
+                   ['id' => 1001,
+                    'libelle' => 'Etablissement',
+                    'parent_id' => 0]);
+
+    $this->fixture(Class_UserGroup::class,
+                   ['id' => 101,
+                    'id_cat' => 1001,
+                    'protected' => false,
+                    'libelle' => 'Admin portail',
+                    'group_type' => Class_UserGroup::TYPE_DYNAMIC,
+                    'users' => [],
+                    'rights' => [],
+                    'filters' => json_encode(['search_role_level' => '6',
+                                              'search_id_site' => '1;2'])]);
+
+    $this->fixture(Class_UserGroup::class,
+                   ['id' => 102,
+                    'id_cat' => 1001,
+                    'protected' => false,
+                    'libelle' => 'Admin bibliothèque',
+                    'group_type' => Class_UserGroup::TYPE_DYNAMIC,
+                    'users' => [],
+                    'rights' => [],
+                    'filters' => json_encode(['search_role_level' => '4',
+                                              'search_id_site' => '3'])]);
+
+    $this->fixture(Class_UserGroup::class,
+                   ['id' => 103,
+                    'id_cat' => 1001,
+                    'protected' => false,
+                    'libelle' => 'Contributeurs',
+                    'group_type' => Class_UserGroup::TYPE_DYNAMIC,
+                    'users' => [],
+                    'rights' => [],
+                    'filters' => json_encode(['search_id_site' => '1'])]);
+  }
+
+
+  protected function _jsonContainsGroup(string $group_name): bool
+  {
+    $response = json_decode($this->_response->getBody());
+    foreach ($response[0]->categories[0]->items as $group)
+      if ($group->label == $group_name)
+        return true;
+
+    return false;
+  }
+}
+
+
+
+
+class UsersControllerDynamicGroupsAdminPortailTest extends UsersControllerDynamicGroupsTestCase
+{
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->fixture(Class_Users::class,
+                   ['id' => 201,
+                    'nom' => 'User 201',
+                    'last_login' => '',
+                    'idabon' => 201,
+                    'login' => 'user201',
+                    'password' => 'secret',
+                    'id_site' => 1,
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL]);
+
+    $this->dispatch('/admin/users/edit/id/201');
+  }
+
+
+  /** @test */
+  public function user201ShouldBeMemberOfGroupAdminPortailAndContributeurs()
+  {
+    $this->assertXPath('//input[@id="user_group_ids"][@value="101-103"]');
+  }
+}
diff --git a/tests/application/modules/admin/controllers/UsersControllerManagedLibrariesTest.php b/tests/application/modules/admin/controllers/UsersControllerManagedLibrariesTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..80fe578c0f3213eea527f4f385116130c7f91ecb
--- /dev/null
+++ b/tests/application/modules/admin/controllers/UsersControllerManagedLibrariesTest.php
@@ -0,0 +1,1219 @@
+<?php
+/**
+ * Copyright (c) 2012-2024, 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 UsersControllerManagedLibrariesGuestTest extends AbstractControllerTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+    $this->fixture(Class_Users::class, ['id' => 458,
+                                        'prenom' => 'Mimi',
+                                        'nom' => 'Mathy',
+                                        'login' => 'mmathy',
+                                        'mail'=> 'mmathy@gmail.com',
+                                        'pseudo' => 'mimi',
+                                        'password' => 'secret',
+                                        'role_level' => ZendAfi_Acl_AdminControllerRoles::INVITE,
+                                        'idabon' => '',
+                                        'id_site' => '',
+                                        'ordreabon' => 1,
+                                        'date_debut' => '19-07-2009',
+                                        'date_fin' => '19-07-2050',
+                                        'telephone' => '',
+                                        'mobile' => '',
+                                        'adresse' => '',
+                                        'code_postal' => '',
+                                        'ville' => '',
+                                        'subscription_type' => '',
+                                        'last_login' => null,
+                                        'civilite' => '']);
+
+    $this->dispatch('/admin/users/edit/id/458');
+  }
+
+
+  /** @test */
+  public function multiInputManagedLibrariesShouldExist()
+  {
+    $this->assertXPath('//input[@name="managed_libraries"]');
+  }
+
+
+  /** @test */
+  public function onLoadScriptShouldContainExpectedJS()
+  {
+    $this->assertXPathContentContains('//script', '$(function(){if ($(\'#role_level\').val() != 3 && $(\'#role_level\').val() != 4) { $(\'#managed_libraries\').parent().parent().hide() } else { $(\'#managed_libraries\').parent().parent().show() }});');
+  }
+
+
+  /** @test */
+  public function onChangeRoleLevelShouldContainExpectedJS()
+  {
+    $this->assertXPath('//select[@name="role_level"][@onchange="if (event.target.value != 3 && event.target.value != 4) { $(\'#managed_libraries\').parent().parent().hide() } else { $(\'#managed_libraries\').parent().parent().show() }"]');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesPostAdminTest extends AbstractControllerTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->fixture(Class_Bib::class,
+                   ['id' => 100,
+                    'libelle' => 'Poiter']);
+
+    $this->postDispatch('/admin/users/add',
+                        ['login' => 'mdavis',
+                         'password' => 'tutu',
+                         'nom' => 'Davis',
+                         'prenom' => 'Miles',
+                         'pseudo' => '',
+                         'mail' => 'mdavis@free.fr',
+                         'role_level' => ZendAfi_Acl_AdminControllerRoles::MODO_BIB,
+                         'id_site' => '100',
+                         'managed_libraries' => '3;5;31',
+                         'idabon' => '3444',
+                         'ordreabon' => '',
+                         'telephone' => '',
+                         'adresse' => '',
+                         'code_postal' => '',
+                         'ville' => '',
+                         'naissance' => '',
+                         'mobile' => '',
+                         'date_debut' => '',
+                         'date_fin' => '',
+                         'civilite' => 1,
+                         'user_group_ids' => '']);
+  }
+
+
+  /** @test */
+  public function mimiMathyManagedLibrariesShouldBeEmpty()
+  {
+    $this->assertEquals('3;5;31', Class_Users::findFirstBy(['idabon' => '3444'])->getManagedLibraries());
+  }
+}
+
+
+
+
+abstract class UsersControllerManagedLibrariesAbstractTest
+  extends Admin_AbstractControllerTestCase {
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->fixture(Class_Bib::class,
+                   ['id' => 1,
+                    'libelle' => 'Guéret']);
+
+    $this->fixture(Class_Bib::class,
+                   ['id' => 2,
+                    'libelle' => 'Aubusson']);
+
+    $this->fixture(Class_Bib::class,
+                   ['id' => 3,
+                    'libelle' => 'Felletin']);
+
+    $this->fixture(Class_Bib::class,
+                   ['id' => 4,
+                    'libelle' => 'Gouzon']);
+
+    $this->fixture(Class_Users::class,
+                   ['id' => 10,
+                    'idabon' => '65656',
+                    'login' => 'user_from_gueret',
+                    'password' => 'secret',
+                    'id_site' => 1,
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
+                    'last_login' => 0]);
+
+    $this->fixture(Class_Users::class,
+                   ['id' => 11,
+                    'idabon' => '65657',
+                    'login' => 'user_from_aubusson',
+                    'password' => 'secret',
+                    'id_site' => 2,
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
+                    'last_login' => 0]);
+
+    $this->fixture(Class_Users::class,
+                   ['id' => 12,
+                    'idabon' => '65658',
+                    'login' => 'user_from_felletin',
+                    'password' => 'secret',
+                    'id_site' => 3,
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
+                    'last_login' => 0]);
+
+    $this->fixture(Class_Users::class,
+                   ['id' => 13,
+                    'idabon' => '65659',
+                    'login' => 'user_from_gouzon',
+                    'password' => 'secret',
+                    'id_site' => 4,
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
+                    'last_login' => 0]);
+
+
+    ZendAfi_Auth::getInstance()->logUser($this->_getLoggedUser());
+  }
+
+
+  protected function _createLoggedUser(): Class_Users
+  {
+    return $this->fixture(Class_Users::class,
+                          ['id' => 1,
+                           'login' => 'logged_in',
+                           'password' => 'secret',
+                           'id_site' => 1,
+                           'managed_libraries' => '',
+                           'role_level' => '',
+                           'last_login' => 0]);
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this->_createLoggedUser();
+  }
+}
+
+
+
+abstract class UsersControllerManagedLibrariesIndexTest
+  extends UsersControllerManagedLibrariesAbstractTest {
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->dispatch('/admin/users');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesIndexModoBibManageGueretTest
+  extends UsersControllerManagedLibrariesIndexTest {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Rédacteur Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setIdSite('4')
+                ->setManagedLibraries('1')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromGueret() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_gueret"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldNotContainIdentifiantUserFromAubusson() {
+    $this->assertNotXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_aubusson"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldNotContainIdentifiantUserFromFelletin() {
+    $this->assertNotXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_felletin"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldNotContainIdentifiantUserFromGouzon() {
+    $this->assertNotXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_gouzon"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldNotContainGueret()
+  {
+    $this->assertNotXPath('//select[@name="search_id_site"]/option[@value="1"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldNotContainAubusson()
+  {
+    $this->assertNotXPath('//select[@name="search_id_site"]/option[@value="2"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldNotContainFelletin()
+  {
+    $this->assertNotXPath('//select[@name="search_id_site"]/option[@value="3"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldNotContainGouzon()
+  {
+    $this->assertNotXPath('//select[@name="search_id_site"]/option[@value="4"]');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesIndexModoBibManageNothingTest
+  extends UsersControllerManagedLibrariesIndexTest {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Rédacteur Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setIdSite('')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function usersTableShouldNotContainIdentifiantUserFromGueret() {
+    $this->assertNotXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_gueret"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldNotContainIdentifiantUserFromAubusson() {
+    $this->assertNotXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_aubusson"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldNotContainIdentifiantUserFromFelletin() {
+    $this->assertNotXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_felletin"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldNotBeDisplayed()
+  {
+    $this->assertNotXPath('//select[@name="search_id_site"]');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesIndexAdminBibManageAubussonFelletinTest
+  extends UsersControllerManagedLibrariesIndexTest {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Admin Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setIdSite('2')
+                ->setManagedLibraries('2;3')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB);
+  }
+
+
+  /** @test */
+  public function usersTableShouldNotContainIdentifiantUserFromGueret() {
+    $this->assertNotXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_gueret"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromAubusson() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_aubusson"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromFelletin() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_felletin"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldNotContainIdentifiantUserFromGouzon() {
+    $this->assertNotXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_gouzon"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldNotContainGueret()
+  {
+    $this->assertNotXPath('//select[@name="search_id_site"]/option[@value="1"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldContainAubusson()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="2"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldContainFelletin()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="3"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorNotShouldContainGouzon()
+  {
+    $this->assertNotXPath('//select[@name="search_id_site"]/option[@value="4"]');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesIndexModoPortailManageAubussonFelletinTest
+  extends UsersControllerManagedLibrariesIndexTest {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Admin Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('2;3')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromGueret() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_gueret"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromAubusson() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_aubusson"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromFelletin() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_felletin"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromGouzon() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_gouzon"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldNotContainGueret()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="1"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldContainAubusson()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="2"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldContainFelletin()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="3"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldContainGouzon()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="4"]');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesIndexAdminPortailManageGueretTest
+  extends UsersControllerManagedLibrariesIndexTest {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Admin Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('1')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL);
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromGueret() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_gueret"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromAubusson() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_aubusson"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromFelletin() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_felletin"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromGouzon() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_gouzon"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldNotContainGueret()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="1"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldContainAubusson()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="2"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldContainFelletin()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="3"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldContainGouzon()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="4"]');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesIndexSuperAdminTest
+  extends UsersControllerManagedLibrariesIndexTest {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Admin Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::SUPER_ADMIN);
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromGueret() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_gueret"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromAubusson() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_aubusson"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromFelletin() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_felletin"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromGouzon() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_gouzon"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldNotContainGueret()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="1"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldContainAubusson()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="2"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldContainFelletin()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="3"]');
+  }
+
+
+  /** @test */
+  public function librarySelectorShouldContainGouzon()
+  {
+    $this->assertXPath('//select[@name="search_id_site"]/option[@value="4"]');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesEditModoBibManageGueretTest
+  extends UsersControllerManagedLibrariesAbstractTest {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Admin Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('1')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function shouldRenderUserId10EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/10');
+    $this->assertXPath('//form[@action="/admin/users/edit/id/10"]');
+  }
+
+
+  /** @test */
+  public function shouldNotRenderUserId11EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/11');
+    $this->assertRedirect('opac/index');
+  }
+
+
+  /** @test */
+  public function shouldNotRenderUserId12EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/12');
+    $this->assertRedirect('opac/index');
+  }
+
+
+  /** @test */
+  public function shouldNotRenderUserId13EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/13');
+    $this->assertRedirect('opac/index');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesEditModoBibManageGueretFelletinTest
+  extends UsersControllerManagedLibrariesAbstractTest {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Admin Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setIdSite('4')
+                ->setManagedLibraries('1;3')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function shouldRenderUserId10EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/10');
+    $this->assertXPath('//form[@action="/admin/users/edit/id/10"]');
+  }
+
+
+  /** @test */
+  public function shouldNotRenderUserId11EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/11');
+    $this->assertRedirect('opac/index');
+  }
+
+
+  /** @test */
+  public function shouldRenderUserId12EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/12');
+    $this->assertXPath('//form[@action="/admin/users/edit/id/12"]');
+  }
+
+
+  /** @test */
+  public function shouldNotRenderUserId13EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/13');
+    $this->assertRedirect('opac/index');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesEditModoPortalManageGueretTest
+  extends UsersControllerManagedLibrariesAbstractTest {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Admin Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('1')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
+  }
+
+
+  /** @test */
+  public function shouldRenderUserId10EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/10');
+    $this->assertXPath('//form[@action="/admin/users/edit/id/10"]');
+  }
+
+
+  /** @test */
+  public function shouldNotRenderUserId11EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/11');
+    $this->assertXPath('//form[@action="/admin/users/edit/id/11"]');
+  }
+
+
+  /** @test */
+  public function shouldRenderUserId12EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/12');
+    $this->assertXPath('//form[@action="/admin/users/edit/id/12"]');
+  }
+
+
+  /** @test */
+  public function shouldRenderUserId13EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/13');
+    $this->assertXPath('//form[@action="/admin/users/edit/id/13"]');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesEditAdminBibManageAubussonFelletinTest
+  extends UsersControllerManagedLibrariesAbstractTest {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Admin Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('2;3')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB);
+  }
+
+
+  /** @test */
+  public function shouldNotRenderUserId10EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/10');
+    $this->assertRedirect('opac/index');
+  }
+
+
+  /** @test */
+  public function shouldNotRenderUserId11EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/11');
+    $this->assertXPath('//form[@action="/admin/users/edit/id/11"]');
+  }
+
+
+  /** @test */
+  public function shouldRenderUserId12EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/12');
+    $this->assertXPath('//form[@action="/admin/users/edit/id/12"]');
+  }
+
+
+  /** @test */
+  public function shouldRenderUserId13EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/13');
+    $this->assertRedirect('opac/index');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesEditAdminPortalManageFelletinTest
+  extends UsersControllerManagedLibrariesAbstractTest {
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Admin Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setManagedLibraries('3')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL);
+  }
+
+
+  /** @test */
+  public function shouldRenderUserId10EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/10');
+    $this->assertXPath('//form[@action="/admin/users/edit/id/10"]');
+  }
+
+
+  /** @test */
+  public function shouldNotRenderUserId11EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/11');
+    $this->assertXPath('//form[@action="/admin/users/edit/id/11"]');
+  }
+
+
+  /** @test */
+  public function shouldRenderUserId12EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/12');
+    $this->assertXPath('//form[@action="/admin/users/edit/id/12"]');
+  }
+
+
+  /** @test */
+  public function shouldRenderUserId13EditForm()
+  {
+    $this->dispatch('/admin/users/edit/id/13');
+    $this->assertXPath('//form[@action="/admin/users/edit/id/13"]');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesAdminBibEditOwnAccount
+    extends UsersControllerManagedLibrariesAbstractTest {
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->dispatch('/admin/users/edit/id/14');
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    return $this-> fixture(Class_Users::class,
+                           ['id' => 14,
+                            'idabon' => '65670',
+                            'login' => 'me',
+                            'password' => 'secret',
+                            'id_site' => 4,
+                            'role_level' => ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB,
+                            'last_login' => 0]);
+  }
+
+
+  /** @test */
+  public function loggedInShouldAccessHisOwnAccountForm()
+  {
+    $this->assertXPath('//form[@action="/admin/users/edit/id/14"]');
+  }
+
+
+  /** @test */
+  public function loggedInShouldSeeSitePortal()
+  {
+    $this->assertXPath('//select[@name="id_site"]/option[@value="0"]');
+  }
+
+
+  /** @test */
+  public function loggedInShouldNotSeeSiteGueret()
+  {
+    $this->assertNotXPath('//select[@name="id_site"]/option[@value="1"]');
+  }
+
+
+  /** @test */
+  public function loggedInShouldNotSeeSiteAubusson()
+  {
+    $this->assertNotXPath('//select[@name="id_site"]/option[@value="2"]');
+  }
+
+
+  /** @test */
+  public function loggedInShouldNotSeeSiteFelletin()
+  {
+    $this->assertNotXPath('//select[@name="id_site"]/option[@value="3"]');
+  }
+
+
+  /** @test */
+  public function loggedInShouldSeeSiteGouzon()
+  {
+    $this->assertXPath('//select[@name="id_site"]/option[@value="4"]');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesAddModoBibManageAubussonFelletinTest
+  extends UsersControllerManagedLibrariesAbstractTest {
+
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->dispatch('/admin/users/add');
+  }
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Admin Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setIdSite('2')
+                ->setManagedLibraries('2;3')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_BIB);
+  }
+
+
+  /** @test */
+  public function shouldRenderAddForm()
+  {
+    $this->assertXPath('//form[@action="/admin/users/add"]');
+  }
+
+
+  /** @test */
+  public function multiInputManagedLibrariesShouldBeHidden()
+  {
+    $this->assertNotXPath('//input[@name="managed_libraries"][@style="display: none;"]');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesAddAdminBibManageAubussonFelletinTest
+  extends UsersControllerManagedLibrariesAbstractTest {
+
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->dispatch('/admin/users/add');
+  }
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Admin Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setIdSite('2')
+                ->setManagedLibraries('2;3')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB);
+  }
+
+
+  /** @test */
+  public function shouldRenderAddForm()
+  {
+    $this->assertXPath('//form[@action="/admin/users/add"]');
+  }
+
+
+  /** @test */
+  public function libraryAubussonShouldBePresent()
+  {
+    $this->assertXPath('//select[@name="id_site"]/option[@value="2"]');
+  }
+
+
+  /** @test */
+  public function libraryFelletinShouldBePresent()
+  {
+    $this->assertXPath('//select[@name="id_site"]/option[@value="3"]');
+  }
+
+
+  /** @test */
+  public function libraryGueretShouldNotBePresent()
+  {
+    $this->assertNotXPath('//select[@name="id_site"]/option[@value="1"]');
+  }
+
+
+  /** @test */
+  public function libraryPortailShouldNotBePresent()
+  {
+    $this->assertNotXPath('//select[@name="id_site"]/option[@value="0"]');
+  }
+
+
+  /** @test */
+  public function multiInputManagedLibrariesShouldExist()
+  {
+    $this->assertXPath('//input[@name="managed_libraries"]');
+  }
+
+
+  /** @test */
+  public function multiInputManagedLibrariesShouldContainGueret()
+  {
+    $this->assertXPath('//input[@type="checkbox"][@data-clef="1"]');
+  }
+
+
+  /** @test */
+  public function multiInputManagedLibrariesShouldContainAubusson()
+  {
+    $this->assertXPath('//input[@type="checkbox"][@data-clef="2"]');
+  }
+
+
+  /** @test */
+  public function multiInputManagedLibrariesShouldContainFelletin()
+  {
+    $this->assertXPath('//input[@type="checkbox"][@data-clef="3"]');
+  }
+
+
+  /** @test */
+  public function multiInputManagedLibrariesShouldContainGouzon()
+  {
+    $this->assertXPath('//input[@type="checkbox"][@data-clef="4"]');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesAddModoPortalTest
+  extends UsersControllerManagedLibrariesAbstractTest {
+
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->dispatch('/admin/users/add');
+  }
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Admin Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setIdSite('2')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
+  }
+
+
+  /** @test */
+  public function shouldRenderAddForm()
+  {
+    $this->assertXPath('//form[@action="/admin/users/add"]');
+  }
+
+
+  /** @test */
+  public function multiInputManagedLibrariesShouldExist()
+  {
+    $this->assertXPath('//input[@name="managed_libraries"]');
+  }
+
+
+  /** @test */
+  public function multiInputManagedLibrariesShouldContainGueret()
+  {
+    $this->assertXPath('//input[@type="checkbox"][@data-clef="1"]');
+  }
+
+
+  /** @test */
+  public function multiInputManagedLibrariesShouldContainAubusson()
+  {
+    $this->assertXPath('//input[@type="checkbox"][@data-clef="2"]');
+  }
+
+
+  /** @test */
+  public function multiInputManagedLibrariesShouldContainFelletin()
+  {
+    $this->assertXPath('//input[@type="checkbox"][@data-clef="3"]');
+  }
+
+
+  /** @test */
+  public function multiInputManagedLibrariesShouldContainGouzon()
+  {
+    $this->assertXPath('//input[@type="checkbox"][@data-clef="4"]');
+  }
+}
+
+
+
+
+class UsersControllerManagedLibrariesSearchAdminBibManageAubussonFelletinTest
+  extends UsersControllerManagedLibrariesAbstractTest
+{
+
+  public function setUp()
+  {
+    parent::setUp();
+
+    $this->postDispatch('/admin/users', ['search_id_site' => '2']);
+  }
+
+
+  protected function _getLoggedUser(): Class_Users
+  {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 28,
+                             'libelle' => 'Admin Bib',
+                             'rights' => [Class_UserGroup::RIGHT_USER_SIGB_USER_READ]]);
+
+    return $this->_createLoggedUser()
+                ->setIdSite('2')
+                ->setManagedLibraries('2;3')
+                ->addUserGroup($group)
+                ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB);
+  }
+
+
+  /** @test */
+  public function usersTableShouldNotContainIdentifiantUserFromGueret() {
+    $this->assertNotXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_gueret"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldContainIdentifiantUserFromAubusson() {
+    $this->assertXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_aubusson"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldNotContainIdentifiantUserFromFelletin() {
+    $this->assertNotXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_felletin"]');
+  }
+
+
+  /** @test */
+  public function usersTableShouldNotContainIdentifiantUserFromGouzon() {
+    $this->assertNotXPath('//table[@id="users_table"]/tbody/tr/td[text()="user_from_gouzon"]');
+  }
+}
diff --git a/tests/application/modules/admin/controllers/UsersControllerRolesTest.php b/tests/application/modules/admin/controllers/UsersControllerRolesTest.php
index f5650b6087a01cb908e492b3a4b1719bed29dda3..a6fdb1d3f6010ef31238e60223dad7c3ab24b26a 100644
--- a/tests/application/modules/admin/controllers/UsersControllerRolesTest.php
+++ b/tests/application/modules/admin/controllers/UsersControllerRolesTest.php
@@ -76,6 +76,7 @@ class UsersControllerRolesAdminBibTest
                                  'password' => 'ro',
                                  'mail' => 'toto@ro.com',
                                  'id_site' => 1,
+                                 'managed_libraries' => '1',
                                  'role_level' => ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB,
                                  'last_login' => 0]);
 
diff --git a/tests/application/modules/admin/controllers/UsersControllerTest.php b/tests/application/modules/admin/controllers/UsersControllerTest.php
index 84b9fb4bdc4a259d9957e6b1161e89ffef6fd42b..d0d97e62b74e93201262cecbcd4facad1b96694b 100644
--- a/tests/application/modules/admin/controllers/UsersControllerTest.php
+++ b/tests/application/modules/admin/controllers/UsersControllerTest.php
@@ -254,7 +254,7 @@ class UsersControllerIndexSearchRoleLevelBorowersTest extends UsersControllerInd
   public function formMulticheckboxDropdownMembershipShouldNotContainsMembershipNonRenseigne() {
     $this->assertNotXPathContentContains('//div[@id="search_membership_saisie"]',
                                          'Non Renseigné<br/>');
-    $this->assertNotXPath('//input[@type="checkbox"][@clef="ignore"]');
+    $this->assertNotXPath('//input[@type="checkbox"][@data-clef="ignore"]');
   }
 
 
@@ -262,7 +262,7 @@ class UsersControllerIndexSearchRoleLevelBorowersTest extends UsersControllerInd
   public function formMulticheckboxDropdownMembershipShouldNotContainsMembershipAbonneInterne() {
     $this->assertNotXPathContentContains('//div[@id="search_membership_saisie"]',
                                          'Abonné Adulte Interne<br/>');
-    $this->assertNotXPath('//input[@type="checkbox"][@clef="1"]');
+    $this->assertNotXPath('//input[@type="checkbox"][@data-clef="1"]');
   }
 
 
@@ -381,7 +381,7 @@ class UsersControllerIndexSearchRoleLevelAbonneWithNanookUniqueTest
   public function formMulticheckboxDropdownMembershipShouldContainsMembershipNonRenseigne() {
     $this->assertXPathContentContains('//div[@id="search_membership_saisie"]',
                                       'Non Renseigné<br/>');
-    $this->assertXPath('//input[@type="checkbox"][@clef="ignore"]');
+    $this->assertXPath('//input[@type="checkbox"][@data-clef="ignore"]');
   }
 
 
@@ -389,7 +389,7 @@ class UsersControllerIndexSearchRoleLevelAbonneWithNanookUniqueTest
   public function formMulticheckboxDropdownMembershipShouldContainsMembershipAbonneInterne() {
     $this->assertXPathContentContains('//div[@id="search_membership_saisie"]',
                                       'Abonné Adulte Interne<br/>');
-    $this->assertXPath('//input[@type="checkbox"][@clef="1"]');
+    $this->assertXPath('//input[@type="checkbox"][@data-clef="1"]');
   }
 
 
@@ -1444,6 +1444,7 @@ class UsersControllerChangeRoleLevelOfUserInMyBibAsAdminBibTest
                                 'login' => 'adminbib',
                                 'password' => 'secret',
                                 'id_site' => '5',
+                                'managed_libraries' => '5',
                                 'role_level' => ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB,
                                 'last_login' => null]);
 
diff --git a/tests/application/modules/opac/controllers/AuthoritySuggestControllerTest.php b/tests/application/modules/opac/controllers/AuthoritySuggestControllerTest.php
index 710e774b13c2ed97ccc33937e5af1de10bd2b12f..ee2360b5b2d41bf7f375d8e5ef46eeaa4b129294 100644
--- a/tests/application/modules/opac/controllers/AuthoritySuggestControllerTest.php
+++ b/tests/application/modules/opac/controllers/AuthoritySuggestControllerTest.php
@@ -70,9 +70,8 @@ class AuthoritySuggestControllerSimpleTest extends AbstractControllerTestCase {
    */
   public function forAutoritysAsAdminPortailBodyShouldContainsTagListe($type, $id, $content) {
     $this->dispatch('/opac/authority-suggest/suggest/type_autorite/' . $type . '/mode/1/valeur/l/id_champ/suggest');
-    $this->assertXPathContentContains('//li[@class="tag_liste"]/a[@clef="'. $id .'"]',
-                                      $content,
-                                      $this->_response->getBody());
+    $this->assertXPathContentContains('//li[@class="tag_liste"]/a[@data-clef="'. $id .'"]',
+                                      $content);
   }
 }
 
@@ -128,9 +127,8 @@ class AuthoritySuggestControllerThesaurusPirateTest extends AbstractControllerTe
 
 
   protected function assertPirateIsSuggested() {
-    $this->assertXPathContentContains('//li[@class="tag_liste"]/a[@clef="1"]',
-                                      '1 : pirate',
-                                      $this->_response->getBody());
+    $this->assertXPathContentContains('//li[@class="tag_liste"]/a[@data-clef="1"]',
+                                      '1 : pirate');
   }
 
 
@@ -191,20 +189,20 @@ class AuthoritySuggestControllerSimpleWithIdRefResultsTest extends AbstractContr
                                       ($additional_class
                                        ? '[contains(@class, "'. $additional_class. '")]'
                                        : '')
-                                      .'/a[@clef="'.$id .'"]',
-                                      $content, $this->_response->getBody());
+                                      .'/a[@data-clef="'.$id .'"]',
+                                      $content);
   }
 
 
   /** @test */
   public function JsFunctionForEmotionalIntelligenceShouldBeCreateAndSelect() {
-    $this->assertXPath('//a[@clef="5110817"][contains(@onclick,"createAndSelectSuggest(\'Emotional intelligence\',this)")]');
+    $this->assertXPath('//a[@data-clef="5110817"][contains(@onclick,"createAndSelectSuggest(\'Emotional intelligence\',this)")]');
   }
 
 
   /** @test */
   public function JsFunctionForIntelligencePratiqueShouldBeSelectSuggest() {
-    $this->assertXPath('//a[@clef="999"][contains(@onclick,"selectSuggest(\'suggest\',this)")]');
+    $this->assertXPath('//a[@data-clef="999"][contains(@onclick,"selectSuggest(\'suggest\',this)")]');
   }
 }
 
diff --git a/tests/application/modules/opac/controllers/BibControllerBibViewTest.php b/tests/application/modules/opac/controllers/BibControllerBibViewTest.php
index b7110500ae005b356e8d1da91a5360d43dd1d959..865cf5738a2a265deac02ece8a83e3b202f04275 100644
--- a/tests/application/modules/opac/controllers/BibControllerBibViewTest.php
+++ b/tests/application/modules/opac/controllers/BibControllerBibViewTest.php
@@ -588,6 +588,7 @@ abstract class BibControllerLibraryWithOpeningsTestCase extends BibControllerBib
                                 ['id' => 54,
                                  'login' => 'admin bib',
                                  'password' => 'popup',
+                                 'managed_libraries' => '4',
                                  'id_site' => 4]);
     $admin_bib->beAdminBib();
     ZendAfi_Auth::getInstance()->logUser($admin_bib);
@@ -660,16 +661,14 @@ class BibControllerBibViewAnnecyRangeOpeningsTest extends BibControllerLibraryWi
   /** @test */
   public function shouldContainsDefault() {
     $this->assertXPathContentContains('//div[contains(@class, "library_schedule")]//h3',
-                                      'D\'habitude',
-                                      $this->_response->getBody());
+                                      'D\'habitude');
   }
 
 
   /** @test */
   public function shouldContainsHorairesDEte() {
     $this->assertXPathContentContains('//div[contains(@class, "library_schedule")]//h3',
-                                      'Horaires d\'été',
-                                      $this->_response->getBody());
+                                      'Horaires d\'été');
   }
 
 
diff --git a/tests/application/modules/opac/controllers/BibControllerTest.php b/tests/application/modules/opac/controllers/BibControllerTest.php
index 7a9bef9cbc19f4cfaa911292548fa33db47a97a1..11e5b35270b7dea18ffaa43bbb8202100f7a824a 100644
--- a/tests/application/modules/opac/controllers/BibControllerTest.php
+++ b/tests/application/modules/opac/controllers/BibControllerTest.php
@@ -1512,6 +1512,7 @@ class BibControllerWidgetPageAsAdminTest extends BibControllerWithThreeBibTestCa
                                 ['id' => 54,
                                  'login' => 'admin bib',
                                  'password' => 'popup',
+                                 'managed_libraries' => '1',
                                  'id_site' => 1]);
     $admin_bib->beAdminBib();
     ZendAfi_Auth::getInstance()->logUser($admin_bib);
diff --git a/tests/application/modules/opac/controllers/CmsControllerCalendarActionTest.php b/tests/application/modules/opac/controllers/CmsControllerCalendarActionTest.php
index 3d184848dace299a7aca0c9cde121c90bc5ad2be..ccc3aa881895d73c7d175db9675c7267447bac50 100644
--- a/tests/application/modules/opac/controllers/CmsControllerCalendarActionTest.php
+++ b/tests/application/modules/opac/controllers/CmsControllerCalendarActionTest.php
@@ -48,6 +48,7 @@ abstract class CmsControllerCalendarActionTestCase
                    ['id' => 3,
                     'browser' => 'opac',
                     'libelle' => 'Rendez-vous',
+                    'id_site' => '1 2',
                     'cfg_accueil' => $this->cfg_accueil]);
 
     Class_AdminVar::newInstanceWithId('CACHE_ACTIF',
@@ -236,7 +237,7 @@ class CmsControllerCalendarActionWithMultipleFiltersTest
     $common_preferences = ['display_order' => 'EventDebut',
                            'id_categorie' => '12-2',
                            'events_only' => true,
-                           'id_bib' => 0,
+                           'id_bib' => [1, 2],
                            'id_lieu' => '',
                            'published' =>true,
     ];
@@ -258,6 +259,7 @@ class CmsControllerCalendarActionWithMultipleFiltersTest
       ->answers([$this->_permaculture])
       ->whenCalled('getArticlesByPreferences')
       ->with(array_merge($common_preferences, ['event_date' => '',
+                                               'id_categorie' => '12-2',
                                                'custom_fields' => [2 => [0 => 'culture'],
                                                                    20 => [0 => 'jardinage']],
                                                'event_start_after' => '2014-07',
@@ -321,7 +323,7 @@ abstract class CmsControllerCalendarActionWithFiltersTestCase
     $this->_common_preferences = ['display_order' => 'EventDebut',
                                   'id_categorie' => '12-2',
                                   'events_only' => true,
-                                  'id_bib' => 0,
+                                  'id_bib' => [1, 2],
                                   'id_lieu' => '',
                                   'custom_fields' => [2 =>[0 => $this->getSetupValueIdForString('opac')]],
                                   'published' => true];
@@ -592,7 +594,7 @@ class CmsControllerCalendarActionWithDayTest extends AbstractControllerTestCase
                  'id_categorie' => '',
                  'events_only' => true,
                  'event_date' => '2014-09',
-                 'id_bib' => 0,
+                 'id_bib' => [1, 2],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true])
@@ -603,7 +605,7 @@ class CmsControllerCalendarActionWithDayTest extends AbstractControllerTestCase
                  'id_categorie' => '',
                  'events_only' => true,
                  'event_date' => '2014-09',
-                 'id_bib' => 0,
+                 'id_bib' => [1, 2],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true,
@@ -615,7 +617,7 @@ class CmsControllerCalendarActionWithDayTest extends AbstractControllerTestCase
                  'id_categorie' => '',
                  'events_only' => true,
                  'event_date' => '',
-                 'id_bib' => 0,
+                 'id_bib' => [1, 2],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true,
@@ -629,7 +631,7 @@ class CmsControllerCalendarActionWithDayTest extends AbstractControllerTestCase
                  'id_categorie' => '',
                  'events_only' => true,
                  'event_date' => '2014-09-30',
-                 'id_bib' => 0,
+                 'id_bib' => [1, 2],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true])
@@ -1471,7 +1473,7 @@ class CmsControllerCalendarActionWithOutDateTest extends AbstractControllerTestC
                  'id_categorie' => '',
                  'events_only' => true,
                  'event_date' => '2014-09',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true,
@@ -1483,7 +1485,7 @@ class CmsControllerCalendarActionWithOutDateTest extends AbstractControllerTestC
                  'id_categorie' => '',
                  'events_only' => true,
                  'event_date' => '',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true,
@@ -1496,7 +1498,7 @@ class CmsControllerCalendarActionWithOutDateTest extends AbstractControllerTestC
                  'id_categorie' => '',
                  'events_only' => true,
                  'event_date' => '2014-09',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true])
@@ -1613,7 +1615,7 @@ class CmsControllerCalenderWithAllCatSelectedAndIdCategorieSetTest
                  'id_categorie' => '12-2',
                  'events_only' => true,
                  'event_date' => '2018-09',
-                 'id_bib' => 0,
+                 'id_bib' => [1, 2],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true,
@@ -1673,7 +1675,7 @@ class CmsControllerCalenderWithAllCatSelectedAndIdCategorieEmptyTest
                  'id_categorie' => '',
                  'events_only' => true,
                  'event_date' => '2018-09',
-                 'id_bib' => 0,
+                 'id_bib' => [1, 2],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true,
@@ -1713,7 +1715,7 @@ class CmsControllerCalendarActionWithFiltersTagTest
               'id_categorie' => '12-2',
               'events_only' => true,
               'event_date' => '2011-02',
-              'id_bib' => 0,
+              'id_bib' => [1, 2],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => false])
@@ -1725,7 +1727,7 @@ class CmsControllerCalendarActionWithFiltersTagTest
               'id_categorie' => '12-2',
               'events_only' => true,
               'event_date' => '',
-              'id_bib' => 0,
+              'id_bib' => [1, 2],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => false,
diff --git a/tests/application/modules/opac/controllers/ProfilOptionsControllerTest.php b/tests/application/modules/opac/controllers/ProfilOptionsControllerTest.php
index ae741d95df5f2c459e7e062e275810b035c70736..1e8cd2fab290a61c6e38c92d7a8bf085c1532ad6 100644
--- a/tests/application/modules/opac/controllers/ProfilOptionsControllerTest.php
+++ b/tests/application/modules/opac/controllers/ProfilOptionsControllerTest.php
@@ -2569,7 +2569,7 @@ class ProfilOptionsControllerProfilBoiteCalendarWithFilterOnMonthsTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2050-03',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true])
@@ -2617,7 +2617,7 @@ class ProfilOptionsControllerProfilBoiteCalendarWithNoFilterTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2050-03',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -2629,7 +2629,7 @@ class ProfilOptionsControllerProfilBoiteCalendarWithNoFilterTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -2687,7 +2687,7 @@ class ProfilOptionsControllerWidgetCalendarWithDisplayFullPageDeactivateShouldUs
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2050-03',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -2699,7 +2699,7 @@ class ProfilOptionsControllerWidgetCalendarWithDisplayFullPageDeactivateShouldUs
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -2712,7 +2712,7 @@ class ProfilOptionsControllerWidgetCalendarWithDisplayFullPageDeactivateShouldUs
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2050-03',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true])
diff --git a/tests/library/Class/ArticleLoaderTest.php b/tests/library/Class/ArticleLoaderTest.php
index f9b2a94a6af3fd97929526b3204d4d27084c283f..72c10b746a6823d163d535f094976ee7c8b8390f 100644
--- a/tests/library/Class/ArticleLoaderTest.php
+++ b/tests/library/Class/ArticleLoaderTest.php
@@ -253,9 +253,9 @@ class ArticleLoaderGetArticlesByPreferencesTest
                         'id_items' => '',
                         'id_categorie' => '',
                         'event_date' => '2011-03',
-                        'id_bib' => 5]);
+                        'id_bib' => ['5']]);
 
-    $this->assertSelect(sprintf("INNER JOIN `cms_categorie` ON cms_categorie.ID_CAT = cms_article.ID_CAT WHERE %s AND (cms_categorie.ID_SITE=5) AND (left(EVENTS_DEBUT,7) <= '2011-03') AND (left(EVENTS_FIN,7) >= '2011-03') AND (PARENT_ID=0) ORDER BY `DATE_CREATION` DESC",
+    $this->assertSelect(sprintf("INNER JOIN `cms_categorie` ON cms_categorie.ID_CAT = cms_article.ID_CAT WHERE %s AND (cms_categorie.ID_SITE IN ('5')) AND (left(EVENTS_DEBUT,7) <= '2011-03') AND (left(EVENTS_FIN,7) >= '2011-03') AND (PARENT_ID=0) ORDER BY `DATE_CREATION` DESC",
                                 self::WHERE_VISIBLE_CLAUSE));
   }
 
@@ -314,6 +314,14 @@ class ArticleLoaderGetArticlesByPreferencesTest
 
     $this->assertSelect('WHERE (PARENT_ID=0) ORDER BY `DATE_CREATION` DESC');
   }
+
+
+  /** @test */
+  public function withIdSiteOneAndTwoShouldFilterWithIn()
+  {
+    $this->getArticles(['id_bib' => ['1', '2']]);
+    $this->assertSelect("INNER JOIN `cms_categorie` ON cms_categorie.ID_CAT = cms_article.ID_CAT WHERE ((DEBUT IS NULL) OR (DEBUT <= CURDATE())) AND ((FIN IS NULL) OR (FIN >= CURDATE())) AND (cms_categorie.ID_SITE IN ('1','2')) AND (PARENT_ID=0) ORDER BY `DATE_CREATION` DESC");
+  }
 }
 
 
diff --git a/tests/library/Class/ProfilTest.php b/tests/library/Class/ProfilTest.php
index 4c2e4b1cc79d0324bbf80d072f24f5e7b73a4159..88ea6f23d333778d5bad2d0eb12489cc62f00d09 100644
--- a/tests/library/Class/ProfilTest.php
+++ b/tests/library/Class/ProfilTest.php
@@ -1780,3 +1780,111 @@ class ProfilIsPortalTest extends ModelTestCase {
                                       ['id' => '7'])->isPortail());
   }
 }
+
+
+
+
+class ProfilfindByZoneAndBibsTest extends ModelTestCase {
+  public function setUp()
+  {
+    parent::setUp();
+    $this->fixture(Class_Profil::class,
+                   ['id' => 1,
+                    'libelle' => 'mon profil Portail',
+                   ]);
+
+    $this->fixture(Class_Profil::class,
+                   ['id' => 2,
+                    'libelle' => 'mon profil Site 1',
+                    'id_site' => 1
+                   ]);
+
+    $this->fixture(Class_Profil::class,
+                   ['id' => 5,
+                    'libelle' => 'ABBA',
+                    'id_site' => 2
+                   ]);
+
+    $this->fixture(Class_Profil::class,
+                   ['id' => 3,
+                    'libelle' => 'Zana',
+                    'id_site' => 3
+                   ]);
+
+    $this->fixture(Class_Profil::class,
+                   ['id' => 4,
+                    'libelle' => 'mon profil Site 4',
+                    'id_site' => 4
+                   ]);
+
+    $this->fixture(Class_Bib::class,
+                   ['id' => 4,
+                    'libelle' => 'JolieVille',
+                    'id_zone' => 1
+                   ]);
+
+    $this->fixture(Class_Bib::class,
+                   ['id' => 1,
+                    'libelle' => 'BaskerVille',
+                    'id_zone' => 1
+                   ]);
+
+    $abon = $this->fixture(Class_Users::class,
+                           ['id' => 1826,
+                            'login' => 'huguette',
+                            'password' => 'secret',
+                            'id_site' => 1,
+                            'managed_libraries' => '1;3;4',
+                            'role_level' => ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB]);
+
+    ZendAfi_Auth::getInstance()->logUser($abon);
+  }
+
+
+  /** @test */
+  public function withManagedLibrariesOneThreeAndFourShouldGetThreeProfiles() {
+    $profils = Class_Profil::findAllByZoneAndBib(0, 0);
+    $this->assertEquals(3, count($profils));
+    return $profils;
+  }
+
+
+  /** @test
+   *  @depends withManagedLibrariesOneThreeAndFourShouldGetThreeProfiles
+   */
+  public function firstProfilReturnedIdShouldBe5($profils) {
+    $this->assertEquals(3, $profils[0]->getId());
+  }
+
+
+  /** @test
+   *  @depends withManagedLibrariesOneThreeAndFourShouldGetThreeProfiles
+   */
+  public function secondProfilReturnedIdShouldBe3($profils) {
+    $this->assertEquals(2, $profils[1]->getId());
+  }
+
+
+  /** @test */
+  public function withIdZone1FindByZoneAndBibsCountshouldEquals2() {
+    $profils = Class_Profil::findAllByZoneAndBib(1, 0);
+    $this->assertEquals(2, count($profils));
+    return $profils;
+  }
+
+
+  /** @test
+   *  @depends withIdZone1FindByZoneAndBibsCountshouldEquals2
+   */
+  public function firstProfilReturnedIdShouldBe2($profils) {
+    $this->assertEquals(2, $profils[0]->getId());
+  }
+
+
+  /** @test
+   *  @depends withIdZone1FindByZoneAndBibsCountshouldEquals2
+   */
+  public function secondProfilReturnedIdShouldBe4($profils) {
+    $this->assertEquals(4, $profils[1]->getId());
+  }
+}
diff --git a/tests/library/ZendAfi/Controller/Action/Helper/ArticleListViewModeTest.php b/tests/library/ZendAfi/Controller/Action/Helper/ArticleListViewModeTest.php
index ad6d4492ce8243e69963d9ed5087390ab9d60e78..2a0a20d2d48534e20b00bd4925c3a3ca94a99b35 100644
--- a/tests/library/ZendAfi/Controller/Action/Helper/ArticleListViewModeTest.php
+++ b/tests/library/ZendAfi/Controller/Action/Helper/ArticleListViewModeTest.php
@@ -38,7 +38,8 @@ class ArticleListViewModeTest extends ModelTestCase {
                             'login' => 'redac',
                             'password' => 'redac',
                             'role_level' => ZendAfi_Acl_AdminControllerRoles::MODO_BIB,
-                            'id_site' => 1]);
+                            'id_site' => 1,
+                            'managed_libraries' => '1']);
 
     ZendAfi_Auth::getInstance()->logUser($user);
   }
diff --git a/tests/library/ZendAfi/View/Helper/Accueil/CalendarTest.php b/tests/library/ZendAfi/View/Helper/Accueil/CalendarTest.php
index d950d359270c312e0573425a681989e8ffb57eac..8d0ab772360f9a0cca457adf07cee7acf5f9b5c4 100644
--- a/tests/library/ZendAfi/View/Helper/Accueil/CalendarTest.php
+++ b/tests/library/ZendAfi/View/Helper/Accueil/CalendarTest.php
@@ -146,7 +146,7 @@ abstract class CalendarViewTodayTestCase extends CalendarWithEmptyPreferencesTes
                  'event_date' => '2013-08',
                  'event_end_after' => '2013-08-19',
                  'events_only' => true,
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true])
@@ -158,7 +158,7 @@ abstract class CalendarViewTodayTestCase extends CalendarWithEmptyPreferencesTes
                  'id_categorie' => '',
                  'event_date' => '2013-08',
                  'events_only' => true,
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true])
@@ -405,7 +405,7 @@ class CalendarWithPreferencesNbEventsOneTest extends CalendarWithEmptyPreference
                  'id_categorie' => '',
                  'event_end_after' => '2013-08-19',
                  'event_date' => '2013-08',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'events_only' => true,
@@ -416,7 +416,7 @@ class CalendarWithPreferencesNbEventsOneTest extends CalendarWithEmptyPreference
       ->with(['display_order' => 'EventDebut',
               'id_categorie' => '',
               'event_date' => '2013-08',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'events_only' => true,
@@ -470,7 +470,7 @@ class CalendarWithEmptyParamsLocaleEnAndOnlyTwoArticlesReturnedTest
                  'id_categorie' => '',
                  'event_date' => '2013-08',
                  'event_end_after' => '2013-08-19',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'events_only' => true,
@@ -481,7 +481,7 @@ class CalendarWithEmptyParamsLocaleEnAndOnlyTwoArticlesReturnedTest
          ->with(['display_order' => 'EventDebut',
                  'id_categorie' => '',
                  'event_start_after' => '2013-09',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'events_only' => true,
@@ -540,7 +540,7 @@ class CalendarWithCategoryLimitAndBibPreferencesTest extends CalendarViewHelperT
               'display_order' => 'DebutPublicationDesc',
               'id_categorie' => '12-3',
               'event_date' => '2011-03',
-              'id_bib' => 5,
+              'id_bib' => ['5'],
               'id_lieu' => '',
               'custom_fields' => [],
               'events_only' => true,
@@ -553,7 +553,7 @@ class CalendarWithCategoryLimitAndBibPreferencesTest extends CalendarViewHelperT
               'id_categorie' => '12-3',
               'events_only' => true,
               'event_date' => '2011-03-17',
-              'id_bib' => 5,
+              'id_bib' => ['5'],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => false
@@ -661,7 +661,7 @@ class CalendarWithWorkFlowStatusTest extends CalendarWithEmptyPreferencesTestCas
                  'id_categorie' => '',
                  'event_end_after' => '2013-08-19',
                  'event_date' => '2013-08',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'events_only' => true,
@@ -674,7 +674,7 @@ class CalendarWithWorkFlowStatusTest extends CalendarWithEmptyPreferencesTestCas
                  'display_order' => 'EventDebut',
                  'id_categorie' => '',
                  'event_date' => '2013-08',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'events_only' => true,
@@ -690,7 +690,7 @@ class CalendarWithWorkFlowStatusTest extends CalendarWithEmptyPreferencesTestCas
                  'event_date' => '',
                  'event_end_after' => '',
                  'events_only' => true,
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true
@@ -749,7 +749,7 @@ class CalendarWithCategorySelectorAndRssAndICalPreferencesTest extends CalendarV
          ->with(['display_order' => 'EventDebut',
                  'id_categorie' => '12',
                  'event_date' => '2011-12',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'events_only' => true,
@@ -762,7 +762,7 @@ class CalendarWithCategorySelectorAndRssAndICalPreferencesTest extends CalendarV
          ->with(['display_order' => 'EventDebut',
                  'id_categorie' => '12',
                  'event_date' => '2011-12-25',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'events_only' => true,
@@ -859,7 +859,7 @@ class CalendarWithCategorySelectorButNoSelectedCategoriesTest
       ->with(['display_order' => 'EventDebut',
               'id_categorie' => '',
               'event_date' => '2011-12',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'events_only' => true,
@@ -872,7 +872,7 @@ class CalendarWithCategorySelectorButNoSelectedCategoriesTest
               'display_order' => 'EventDebut',
               'id_categorie' => '',
               'event_date' => '2011-12-25',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'events_only' => true,
@@ -960,7 +960,7 @@ class CalendarOnJanuaryWithDisplayNextEventTrueTest extends CalendarViewHelperTe
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2012-01',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => false
@@ -1029,7 +1029,7 @@ class CalendarOnJanuaryWithDisplayNextEventFalseTest extends CalendarViewHelperT
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2012-01',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => false
diff --git a/tests/scenarios/AdminMenuComposition/AdminMenuCompositionTest.php b/tests/scenarios/AdminMenuComposition/AdminMenuCompositionTest.php
index 9c1c1dc309407d80f265d83fce02b1f7e4f5ef59..8dc5c6eb444ab44540db14604ec4d3bdb2fd42ec 100644
--- a/tests/scenarios/AdminMenuComposition/AdminMenuCompositionTest.php
+++ b/tests/scenarios/AdminMenuComposition/AdminMenuCompositionTest.php
@@ -461,12 +461,12 @@ class AdminMenuCompositionFormForModoPortailTest extends AdminMenuCompositionFor
        ['Import/Export EAD', '/admin/album/import_ead'],
        ['Notices liées', '/admin/frbr-link'],
 
-       ['Profils', '/admin/profil'],
        ['Magasin de thèmes', '/admin/template'],
        ['Modèles d\'impressions', '/admin/print'],
 
        ['Mise à jour de la charte graphique', '/admin/index/update-skin'],
 
+       ['Profils', '/admin/profil'],
        ['Territoires', '/admin/zone'],
        ['Bibliothèques', '/admin/bib'],
        ['Utilisateurs', '/admin/users'],
@@ -629,11 +629,12 @@ class AdminMenuCompositionFormForAdminBibTest extends AdminMenuCompositionFormTe
 
        ['Sélecteur de profil', 'admin_menu_change_profile'],
 
-       ['Configuration du profil', '/admin/profil/edit'],
        ['Configuration de la page', '/admin/profil/accueil'],
        ['Ajouter une boite', '/admin/widget/add-from-template'],
        ['Vider le cache', '/admin/index/clearcache'],
        ['Afficher les icones d\'administration', 'show_admin_icons'],
+       ['Configuration du profil', '/admin/profil/edit'],
+       ['Exporter le profil courant','/admin/profil/export'],
        ['Niveau expert', 'admin_level']
       ];
   }
@@ -648,8 +649,7 @@ class AdminMenuCompositionFormForAdminBibTest extends AdminMenuCompositionFormTe
                    ['Synchronisation du CSS avec GIT', '/admin/index/update-skin'],
 
                    ['Éditeur CSS', 'css_editor'],
-                   ['Amber IDE','amber_ide'],
-                   ['Exporter le profil courant','/admin/profil/export']]);
+                   ['Amber IDE','amber_ide']]);
   }
 }
 
@@ -680,7 +680,6 @@ class AdminMenuCompositionFormForModoBibTest extends AdminMenuCompositionFormTes
 
        ['Matomo', '/admin/stat/matomo'],
        ['Recherches infructueuses', '/admin/stat/rechercheinfructueuse'],
-
       ];
   }
 
@@ -701,12 +700,13 @@ class AdminMenuCompositionFormForModoBibTest extends AdminMenuCompositionFormTes
        ['Sitothèque', '/admin/album/add-website'],
        ['PNB Dilicom', '/admin/pnb'],
 
+       ['Profils', '/admin/profil'],
+
        ['Import/Export EAD', '/admin/album/import_ead'],
        ['Notices liées', '/admin/frbr-link'],
 
        ['Jamendo', '/admin/harvest/jamendo-browse'],
 
-       ['Profils', '/admin/profil'],
        ['Modèles d\'impressions', '/admin/print'],
 
        ['Bibliothèques', '/admin/bib'],
@@ -758,7 +758,9 @@ class AdminMenuCompositionFormForModoBibTest extends AdminMenuCompositionFormTes
        ['Ajouter une boite', '/admin/widget/add-from-template'],
        ['Vider le cache', '/admin/index/clearcache'],
        ['Afficher les icones d\'administration', 'show_admin_icons'],
-       ['Niveau expert', 'admin_level']
+       ['Niveau expert', 'admin_level'],
+
+       //       ['Configuration de la page', '/admin/profil/accueil'],
       ];
   }
 
@@ -771,7 +773,6 @@ class AdminMenuCompositionFormForModoBibTest extends AdminMenuCompositionFormTes
                    ['Utilisateurs', '/admin/users'],
 
                    ['Configuration du profil', '/admin/profil/edit'],
-                   ['Configuration de la page', '/admin/profil/accueil'],
 
                    ['Configuration du thème', '/admin/template/edit'],
                    ['Synchronisation du CSS avec GIT', '/admin/index/update-skin'],
@@ -1022,6 +1023,12 @@ class AdminMenuCompositionUsersEditDispatchTest extends Admin_AbstractController
   public function setUp() {
     parent::setUp();
 
+    $this->fixture(Class_Bib::class,
+                   ['id' => 2,
+                    'libelle' => 'Jolieville'
+                   ]);
+
+
     $this->fixture(Class_Users::class,
                    ['id' => 1,
                     'login' => 'invite',
@@ -1047,6 +1054,7 @@ class AdminMenuCompositionUsersEditDispatchTest extends Admin_AbstractController
                    ['id' => 11,
                     'login' => 'abonne',
                     'password' => 'guest',
+                    'id_site' => '2',
                     'last_login' => null,
                     'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE]);
 
@@ -1055,6 +1063,7 @@ class AdminMenuCompositionUsersEditDispatchTest extends Admin_AbstractController
                     'login' => 'abonne sigb',
                     'password' => 'guest',
                     'id_site' => '2',
+                    'managed_libraries' => '2',
                     'idabon' => '01234',
                     'last_login' => null,
                     'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB]);
@@ -1064,6 +1073,7 @@ class AdminMenuCompositionUsersEditDispatchTest extends Admin_AbstractController
                     'login' => 'abonne sigb',
                     'password' => 'guest',
                     'id_site' => '2',
+                    'managed_libraries' => '2',
                     'idabon' => '01234',
                     'last_login' => null,
                     'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB]);
@@ -1073,6 +1083,7 @@ class AdminMenuCompositionUsersEditDispatchTest extends Admin_AbstractController
                     'login' => 'modo bib',
                     'password' => 'modo',
                     'id_site' => '2',
+                    'managed_libraries' => '2',
                     'last_login' => null,
                     'role_level' => ZendAfi_Acl_AdminControllerRoles::MODO_BIB]);
 
@@ -1081,6 +1092,7 @@ class AdminMenuCompositionUsersEditDispatchTest extends Admin_AbstractController
                     'login' => 'modo bib',
                     'password' => 'modo',
                     'id_site' => '2',
+                    'managed_libraries' => '2',
                     'last_login' => null,
                     'role_level' => ZendAfi_Acl_AdminControllerRoles::MODO_BIB]);
 
@@ -1103,6 +1115,7 @@ class AdminMenuCompositionUsersEditDispatchTest extends Admin_AbstractController
                     'login' => 'admin bib',
                     'password' => 'admin',
                     'id_site' => '2',
+                    'managed_libraries' => '2',
                     'last_login' => null,
                     'role_level' => ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB]);
 
@@ -1111,6 +1124,7 @@ class AdminMenuCompositionUsersEditDispatchTest extends Admin_AbstractController
                     'login' => 'admin bib',
                     'password' => 'admin',
                     'id_site' => '2',
+                    'managed_libraries' => '2',
                     'last_login' => null,
                     'role_level' => ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB]);
 
@@ -1139,18 +1153,11 @@ class AdminMenuCompositionUsersEditDispatchTest extends Admin_AbstractController
 
   public function getNotAllowedRoleLevel() : array {
     return
-      [[3, 1],
-       [3, 2],
-       [3, 3],
+      [
        [3, 4],
 
        [4, 5],
 
-       [5, 1],
-       [5, 2],
-       [5, 3],
-       [5, 4],
-       [5, 5],
        [5, 6],
 
        [6, 7]];
@@ -1175,7 +1182,11 @@ class AdminMenuCompositionUsersEditDispatchTest extends Admin_AbstractController
 
   public function getAllowedRoleLevel() : array {
     return
-      [[4, 4],
+      [[3, 1],
+       [3, 2],
+       [3, 3],
+
+       [4, 4],
        [4, 3],
        [4, 2],
        [4, 1],
@@ -1187,13 +1198,20 @@ class AdminMenuCompositionUsersEditDispatchTest extends Admin_AbstractController
        [6, 2],
        [6, 1],
 
+       [5, 1],
+       [5, 2],
+       [5, 3],
+       [5, 4],
+       [5, 5],
+
        [7, 7],
        [7, 6],
        [7, 5],
        [7, 4],
        [7, 3],
        [7, 2],
-       [7, 1]];
+       [7, 1]
+      ];
   }
 
 
diff --git a/tests/scenarios/AdvancedSearch/AdvancedSearchTest.php b/tests/scenarios/AdvancedSearch/AdvancedSearchTest.php
index db34f99877031be492e4eb54c24e7117c4be6391..9490e6ed9379efc1c255eb53ebf885b66c9eb23b 100644
--- a/tests/scenarios/AdvancedSearch/AdvancedSearchTest.php
+++ b/tests/scenarios/AdvancedSearch/AdvancedSearchTest.php
@@ -1503,7 +1503,7 @@ class AdvancedSearchAuthoritySuggestTest extends AbstractControllerTestCase {
                     'libelle' => 'Herbert'
                    ]);
     $this->dispatch('/authority-suggest/suggest/type_autorite/auteur/valeur/herb/id_champ/author');
-    $this->assertXpathContentContains('//a[@clef="1"][contains(@onclick, "author")]', 'Herbert');
+    $this->assertXpathContentContains('//a[@data-clef="1"][contains(@onclick, "author")]', 'Herbert');
   }
 
 
@@ -1517,7 +1517,7 @@ class AdvancedSearchAuthoritySuggestTest extends AbstractControllerTestCase {
                     'libelle' => 'Le Saux Laetitia'
                    ]);
     $this->dispatch('/authority-suggest/suggest/type_autorite/auteur/valeur/le%20Saux/id_champ/author');
-    $this->assertXpathContentContains('//a[@clef="1"][contains(@onclick, "author")]', 'Le Saux');
+    $this->assertXpathContentContains('//a[@data-clef="1"][contains(@onclick, "author")]', 'Le Saux');
   }
 
 
@@ -1528,7 +1528,7 @@ class AdvancedSearchAuthoritySuggestTest extends AbstractControllerTestCase {
                     'libelle' => 'Herbert'
                    ]);
     $this->dispatch('/authority-suggest/suggest/type_autorite/auteur/valeur/herb/id_champ/author');
-    $this->assertXpathContentContains('//a[@clef="1"][contains(@onclick, "author")]', 'Herbert');
+    $this->assertXpathContentContains('//a[@data-clef="1"][contains(@onclick, "author")]', 'Herbert');
   }
 }
 
diff --git a/tests/scenarios/AdvancedSearch/SuggestSearchTest.php b/tests/scenarios/AdvancedSearch/SuggestSearchTest.php
index e2f3dfa10159f83317fe4ea67df280d9050cc3bb..e7dd41c00f06438cd1fd433139ff554f3e0b5d7a 100644
--- a/tests/scenarios/AdvancedSearch/SuggestSearchTest.php
+++ b/tests/scenarios/AdvancedSearch/SuggestSearchTest.php
@@ -66,7 +66,7 @@ class SuggestSearchDeweyTest extends AbstractControllerTestCase {
   public function searchOnIndice0011ShouldReturnVieIntellectuelle() {
     $this->dispatch('/opac/authority-suggest/suggest/type_autorite/dewey/id_champ/dewey/mode/10/valeur/0011');
 
-    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a clef="0011" href="#" onclick="selectSuggest(\'dewey\',this); return false">001.1 : Vie intellectuelle</a></li></ul>',
+    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a data-clef="0011" href="#" onclick="selectSuggest(\'dewey\',this); return false">001.1 : Vie intellectuelle</a></li></ul>',
                         $this->_response->getBody());
   }
 
@@ -74,7 +74,7 @@ class SuggestSearchDeweyTest extends AbstractControllerTestCase {
   /** @test */
   public function searchOnContainsVieShouldReturnAll() {
     $this->dispatch('/opac/authority-suggest/suggest/type_autorite/dewey/id_champ/dewey/mode/2/valeur/Vie');
-    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a clef="0011" href="#" onclick="selectSuggest(\'dewey\',this); return false">001.1 : Vie intellectuelle</a></li><li class="tag_liste"><a clef="0012" href="#" onclick="selectSuggest(\'dewey\',this); return false">001.2 : Ravie</a></li><li class="tag_liste"><a clef="0013" href="#" onclick="selectSuggest(\'dewey\',this); return false">001.3 : Reve et vie </a></li></ul>',
+    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a data-clef="0011" href="#" onclick="selectSuggest(\'dewey\',this); return false">001.1 : Vie intellectuelle</a></li><li class="tag_liste"><a data-clef="0012" href="#" onclick="selectSuggest(\'dewey\',this); return false">001.2 : Ravie</a></li><li class="tag_liste"><a data-clef="0013" href="#" onclick="selectSuggest(\'dewey\',this); return false">001.3 : Reve et vie </a></li></ul>',
                         $this->_response->getBody());
   }
 
@@ -82,9 +82,23 @@ class SuggestSearchDeweyTest extends AbstractControllerTestCase {
   /** @test */
   public function searchOnContainsExpressionVieShouldReturnWithExactWordVie() {
     $this->dispatch('/opac/authority-suggest/suggest/type_autorite/dewey/id_champ/dewey/mode/3/valeur/Vie');
-    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a clef="0011" href="#" onclick="selectSuggest(\'dewey\',this); return false">001.1 : Vie intellectuelle</a></li><li class="tag_liste"><a clef="0013" href="#" onclick="selectSuggest(\'dewey\',this); return false">001.3 : Reve et vie </a></li></ul>',
+    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a data-clef="0011" href="#" onclick="selectSuggest(\'dewey\',this); return false">001.1 : Vie intellectuelle</a></li><li class="tag_liste"><a data-clef="0013" href="#" onclick="selectSuggest(\'dewey\',this); return false">001.3 : Reve et vie </a></li></ul>',
                         $this->_response->getBody());
   }
+
+
+  /** @test */
+  public function pageShouldBeHtml5Valid()
+  {
+    $this->dispatch('/opac/authority-suggest/suggest/type_autorite/dewey/id_champ/dewey/mode/3/valeur/Vie');
+    $this->assertHTML5($this->_addHTMLLayout($this->_response->getBody()));
+  }
+
+
+  protected function _addHTMLLayout(string $html): string
+  {
+    return sprintf('<!DOCTYPE html><head><title>test</title></head><body>%s</body></html>', $html);
+  }
 }
 
 
@@ -141,7 +155,7 @@ class SuggestSearchMatiereSuggestTest extends AbstractControllerTestCase {
   public function startWithScienShouldContainsScienceOnly() {
     $this->dispatch('/opac/authority-suggest/suggest/type_autorite/matiere/id_champ/matiere/mode/1/valeur/scienc');
 
-    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a clef="10" href="#" onclick="selectSuggest(\'matiere\',this); return false">Science et ignorance</a></li></ul>',
+    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a data-clef="10" href="#" onclick="selectSuggest(\'matiere\',this); return false">Science et ignorance</a></li></ul>',
                         $this->_response->getBody());
   }
 
@@ -150,7 +164,7 @@ class SuggestSearchMatiereSuggestTest extends AbstractControllerTestCase {
   public function containsIgnoranceScienceShouldContainsTwoSuggest() {
     $this->dispatch('/opac/authority-suggest/suggest/type_autorite/matiere/id_champ/matiere/mode/2/valeur/ignorance science');
 
-    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a clef="10" href="#" onclick="selectSuggest(\'matiere\',this); return false">Science et ignorance</a></li><li class="tag_liste"><a clef="11" href="#" onclick="selectSuggest(\'matiere\',this); return false">Conscience et ignorance</a></li></ul>',
+    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a data-clef="10" href="#" onclick="selectSuggest(\'matiere\',this); return false">Science et ignorance</a></li><li class="tag_liste"><a data-clef="11" href="#" onclick="selectSuggest(\'matiere\',this); return false">Conscience et ignorance</a></li></ul>',
                         $this->_response->getBody());
   }
 
@@ -159,7 +173,7 @@ class SuggestSearchMatiereSuggestTest extends AbstractControllerTestCase {
   public function containsExactMatchScienceEtIgnoContainsOneSuggest() {
     $this->dispatch('/opac/authority-suggest/suggest/type_autorite/matiere/id_champ/matiere/mode/3/valeur/science et igno');
 
-    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a clef="10" href="#" onclick="selectSuggest(\'matiere\',this); return false">Science et ignorance</a></li></ul>',
+    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a data-clef="10" href="#" onclick="selectSuggest(\'matiere\',this); return false">Science et ignorance</a></li></ul>',
                         $this->_response->getBody());
   }
 
@@ -168,7 +182,7 @@ class SuggestSearchMatiereSuggestTest extends AbstractControllerTestCase {
   public function containsRougeNoirShouldContainsOneSuggestNoirEtRouge() {
     $this->dispatch('/opac/authority-suggest/suggest/type_autorite/matiere/id_champ/matiere/mode/2/valeur/rouge noir');
 
-    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a clef="12" href="#" onclick="selectSuggest(\'matiere\',this); return false">Noir et rouge</a></li></ul>',
+    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a data-clef="12" href="#" onclick="selectSuggest(\'matiere\',this); return false">Noir et rouge</a></li></ul>',
                         $this->_response->getBody());
   }
 }
diff --git a/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsCalendarTest.php b/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsCalendarTest.php
index 8b33f8208a6f2e31728c57879b6d688aa4d783db..ad04af098c3d3f912a59a1ddc7f84ed59afd3979 100644
--- a/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsCalendarTest.php
+++ b/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsCalendarTest.php
@@ -95,7 +95,7 @@ abstract class ArticlesMultipleTimingsCalendarTestCase extends AbstractControlle
                  'id_categorie' => '',
                  'events_only' => true,
                  'event_date' => '2021-06',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true,
@@ -108,7 +108,7 @@ abstract class ArticlesMultipleTimingsCalendarTestCase extends AbstractControlle
                  'id_categorie' => '',
                  'events_only' => true,
                  'event_date' => '',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true,
@@ -125,7 +125,7 @@ abstract class ArticlesMultipleTimingsCalendarTestCase extends AbstractControlle
                  'id_categorie' => '',
                  'events_only' => true,
                  'event_date' => '',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true,
@@ -143,7 +143,7 @@ abstract class ArticlesMultipleTimingsCalendarTestCase extends AbstractControlle
                  'id_categorie' => '',
                  'events_only' => true,
                  'event_date' => '2021-06',
-                 'id_bib' => 0,
+                 'id_bib' => [''],
                  'id_lieu' => '',
                  'custom_fields' => [],
                  'published' => true])
diff --git a/tests/scenarios/AuthorPage/AuthorWidgetTest.php b/tests/scenarios/AuthorPage/AuthorWidgetTest.php
index 43328b618bf4a5777babf5542c5123a5268a6bc0..e878abb4af67a691a443366abe00ea88e684f69a 100644
--- a/tests/scenarios/AuthorPage/AuthorWidgetTest.php
+++ b/tests/scenarios/AuthorPage/AuthorWidgetTest.php
@@ -521,7 +521,7 @@ class AuthorWidgetResponsibilitiesInputSuggestTest extends AuthorWidgetOnPageTes
 
     $this->dispatch('/opac/authority-suggest/suggest?type_autorite=responsibility&id_champ=responsibilities&mode=1&valeur=Pro');
 
-    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a clef="635" href="#" onclick="selectSuggest(\'responsibilities\',this); return false">Programmeur informatique</a></li></ul>',
+    $this->assertEquals('<ul class="tag_liste_results"><li class="tag_liste"><a data-clef="635" href="#" onclick="selectSuggest(\'responsibilities\',this); return false">Programmeur informatique</a></li></ul>',
                         $this->_response->getBody());
   }
 }
diff --git a/tests/scenarios/DomainsPerLibraries/DomainsPerLibrariesTest.php b/tests/scenarios/DomainsPerLibraries/DomainsPerLibrariesTest.php
index 0aaa1ae056d4b93bc84b65338773c0fd9d7db750..2cce3591c471b248d7d96e240db4e5541f89eec5 100644
--- a/tests/scenarios/DomainsPerLibraries/DomainsPerLibrariesTest.php
+++ b/tests/scenarios/DomainsPerLibraries/DomainsPerLibrariesTest.php
@@ -54,6 +54,7 @@ abstract class DomainsPerLibrariesTestCase extends Admin_AbstractControllerTestC
                     'login' => 'alderaan_admin',
                     'password' => 'secret',
                     'id_site' => 1,
+                    'managed_libraries' => '1',
                     'role_level' => ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB]);
 
     $this->fixture(Class_Catalogue::class,
@@ -142,9 +143,9 @@ class DomainsPerLibrariesCatalogueControllerAsAdminBibWithoutGroupIndexTest exte
 
 
   /** @test */
-  public function pageShouldContainsTableWithFolderLinkToPortal() {
-    $this->assertXPathContentContains('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/0")]',
-                                      'Portail');
+  public function pageShouldNotContainsTableWithFolderLinkToPortal() {
+    $this->assertNotXPathContentContains('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/0")]',
+                                         'Portail');
   }
 }
 
@@ -174,9 +175,9 @@ class DomainsPerLibrariesCatalogueControllerAsAdminAlderaanWithAccessIndexTest e
 
 
   /** @test */
-  public function pageShouldContainsTableWithFolderLinkToPortal() {
-    $this->assertXPathContentContains('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/0")]',
-                                      'Portail');
+  public function pageShouldContainsNotTableWithFolderLinkToPortal() {
+    $this->assertNotXPathContentContains('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/0")]',
+                                         'Portail');
   }
 
 
@@ -209,6 +210,7 @@ abstract class DomainsPerLibrariesCatalogueControllerAsAdminTatooineWithAccessSu
                              'login' => 'tatooine',
                              'password' => 'secret',
                              'bib' => Class_Bib::find(2),
+                             'managed_libraries' => Class_Bib::find(2)->getId(),
                              'user_groups' => [Class_UserGroup::find(4)]])
                   ->beAdminBib();
     ZendAfi_Auth::getInstance()->logUser($admin);
@@ -226,9 +228,9 @@ class DomainsPerLibrariesCatalogueControllerAsAdminTatooineWithAccessCreatorInde
 
 
   /** @test */
-  public function pageShouldContainsTableWithFolderLinkToPortal() {
-    $this->assertXPathContentContains('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/0")]',
-                                      'Portail');
+  public function pageShouldNotContainsTableWithFolderLinkToPortal() {
+    $this->assertNotXPathContentContains('//table//td/a[contains(@href, "/admin/catalogue/index/id_bib/0")]',
+                                         'Portail');
   }
 
 
@@ -271,8 +273,8 @@ class DomainsPerLibrariesCatalogueControllerAsAdminTatooineWithAccessCreatorAddT
 
 
   /** @test */
-  public function selectParentIdShouldHaveOptGroupPortail() {
-    $this->assertXPath('//select[@id="parent_id"]/optgroup[@label="Portail"]');
+  public function selectParentIdShouldNotHaveOptGroupPortail() {
+    $this->assertNotXPath('//select[@id="parent_id"]/optgroup[@label="Portail"]');
   }
 
 
diff --git a/tests/scenarios/Templates/TemplatesAdminProfileTest.php b/tests/scenarios/Templates/TemplatesAdminProfileTest.php
index ec13a30c0d7a78f6cedfe50c7a508923bd3bc829..79d023e5248a21af820f29844c0bf4881b6031d3 100644
--- a/tests/scenarios/Templates/TemplatesAdminProfileTest.php
+++ b/tests/scenarios/Templates/TemplatesAdminProfileTest.php
@@ -448,3 +448,68 @@ class TemplatesAdminProfileDispatchIndexWithIntentTest extends Admin_AbstractCon
     $this->assertXPathCount('//i[@class="fa fa-user-circle-o"]', 1);
   }
 }
+
+
+
+
+class TemplatesAdminProfileDispatchEditProfileWithManagedLibrariesTest extends Admin_AbstractControllerTestCase {
+
+  public function setUp() {
+    parent::setUp();
+
+    $this->fixture(Class_Bib::class,
+                   ['id' => 3,
+                    'libelle' => 'Jolieville',
+                    'visibilite' => 2,
+                   ]);
+
+    $this->fixture(Class_Bib::class,
+                   ['id' => 4,
+                    'libelle' => 'Antre-Jeux',
+                    'visibilite' => 2,
+                   ]);
+
+    $this->fixture(Class_Bib::class,
+                   ['id' => 5,
+                    'libelle' => 'AAAA',
+                    'visibilite' => 2,
+                   ]);
+
+
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 12,
+                             'libelle' => 'Profil Manager',
+                             'rights' => [Class_UserGroup::RIGHT_ADMIN_PROFILE]
+                            ]);
+
+    $jeanbon = $this->fixture(Class_Users::class,
+                              ['id' => 12,
+                               'nom' => 'Jean',
+                               'prenom' => 'Bon',
+                               'login' => 'jeanbon',
+                               'password' => 'herta',
+                               'id_site' => 3,
+                               'managed_libraries' => '4',
+                               'role_level' => ZendAfi_Acl_AdminControllerRoles::MODO_BIB
+                              ]);
+    $jeanbon->addUserGroup($group);
+
+
+    $this->_buildTemplateProfil(['id' => 122,
+                                 'libelle' => 'portail',
+                                 'id_site' => 4,
+                                 'header_css' => '/userfiles/css/main.css']);
+
+    ZendAfi_Auth::getInstance()->logUser($jeanbon);
+
+    $this->dispatch('/admin/profil/edit/id_profil/122');
+  }
+
+
+  /** @test */
+  public function pageShouldRedirectToOpac() {
+    $this->assertRedirect('/opac/index/index/id_profil/122');
+  }
+
+
+}
diff --git a/tests/scenarios/Templates/TemplatesAdvancedSearchTest.php b/tests/scenarios/Templates/TemplatesAdvancedSearchTest.php
index 1b9fc9e3259fd7d6dd14cd4eab7cedfd57c6a804..dc44611941980d2bbf46a18e3d1c9b8a42748069 100644
--- a/tests/scenarios/Templates/TemplatesAdvancedSearchTest.php
+++ b/tests/scenarios/Templates/TemplatesAdvancedSearchTest.php
@@ -177,4 +177,11 @@ class TemplatesDispatchIntonationAdvancedSearchTest extends TemplatesIntonationT
   public function searchAxeInputShouldBePresent() {
     $this->assertXPath('//span[@class="search_axe_input"]');
   }
+
+
+  /** @test */
+  public function pageShouldBeHTML5Valid()
+  {
+    $this->assertHTML5();
+  }
 }
diff --git a/tests/scenarios/Templates/TemplatesAgendaTest.php b/tests/scenarios/Templates/TemplatesAgendaTest.php
index 3f1c9fb33412b07670a1bfab4b0eb20a7bd6b6e4..ea1485c527f4e4554083971035f1561246776199 100644
--- a/tests/scenarios/Templates/TemplatesAgendaTest.php
+++ b/tests/scenarios/Templates/TemplatesAgendaTest.php
@@ -313,7 +313,7 @@ class TemplatesAgendaWallModeNoDateFilterTestCase
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2021-11',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -325,7 +325,7 @@ class TemplatesAgendaWallModeNoDateFilterTestCase
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -338,7 +338,7 @@ class TemplatesAgendaWallModeNoDateFilterTestCase
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2021-11',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true])
@@ -382,7 +382,7 @@ class TemplatesAgendaWallModeNoDateFilterAndNoEventTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2021-11',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -394,7 +394,7 @@ class TemplatesAgendaWallModeNoDateFilterAndNoEventTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -407,7 +407,7 @@ class TemplatesAgendaWallModeNoDateFilterAndNoEventTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2021-11',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true])
@@ -440,7 +440,7 @@ class TemplatesAgendaWallModeSelectedMonthIsCurrentMonthTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2021-11',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true])
@@ -487,7 +487,7 @@ class TemplatesAgendaWallModeSelectedMonthIsCurrentMonthNoEventsTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2021-11',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true])
@@ -498,7 +498,7 @@ class TemplatesAgendaWallModeSelectedMonthIsCurrentMonthNoEventsTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -534,7 +534,7 @@ class TemplatesAgendaWallModeSelectedMonthIsCurrentMonthEventsInNextMonthTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2021-11',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true])
@@ -545,7 +545,7 @@ class TemplatesAgendaWallModeSelectedMonthIsCurrentMonthEventsInNextMonthTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -580,7 +580,7 @@ class TemplatesAgendaWallModeSelectedMonthNextMonthTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2021-12',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true])
@@ -626,7 +626,7 @@ class TemplatesAgendaWallModeSelectedMonthNextMonthNoEventTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2021-12',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true])
@@ -637,7 +637,7 @@ class TemplatesAgendaWallModeSelectedMonthNextMonthNoEventTest
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -678,7 +678,7 @@ class TemplatesAgendaWallModeSelectedMonthIsCurrentMonthArticleWithoutEndDateTes
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2021-11',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true])
diff --git a/tests/scenarios/Templates/TemplatesSearchItemsTest.php b/tests/scenarios/Templates/TemplatesSearchItemsTest.php
index 969ed306da804fb9b7b763d8c9161ed84ef5d864..fb00108ae1663e445e431b086c6167ef2ebeb49e 100644
--- a/tests/scenarios/Templates/TemplatesSearchItemsTest.php
+++ b/tests/scenarios/Templates/TemplatesSearchItemsTest.php
@@ -156,7 +156,7 @@ class TemplatesSearchItemsViewNoticeInSectionDocumentItemsTest
     Class_Profil::find(1)->setIdSite(23)->assertSave();
 
     ZendAfi_Auth::getInstance()->logUser(Class_Users::newInstanceWithId(54)
-                                         ->setIdSite(23)
+                                         ->setManagedLibraries(23)
                                          ->beAdminBib());
     $this->dispatch('/opac/recherche/viewnotice/id/456/id_profil/1');
     $this->assertXPath('//div[contains(@class, "wrapper_document_items")]/a[@href="/admin/modulesnotice/exemplaires/id_profil/1"]');
diff --git a/tests/scenarios/Templates/TemplatesWidgetTest.php b/tests/scenarios/Templates/TemplatesWidgetTest.php
index c7bd71e46abc8b89a0678e7ec124c03272a83958..29f6383c2e202e67ecee1a71bd4c8456dd77dc6f 100644
--- a/tests/scenarios/Templates/TemplatesWidgetTest.php
+++ b/tests/scenarios/Templates/TemplatesWidgetTest.php
@@ -288,7 +288,7 @@ class TemplatesWidgetFilterTest extends TemplatesWidgetRenderAllTestCase {
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2020-11',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -300,7 +300,7 @@ class TemplatesWidgetFilterTest extends TemplatesWidgetRenderAllTestCase {
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'place_town' => 'Grand Annecy',
               'custom_fields' => [],
@@ -316,7 +316,7 @@ class TemplatesWidgetFilterTest extends TemplatesWidgetRenderAllTestCase {
               'id_categorie' => '',
               'events_only' => true,
               'event_date' => '2020-11',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true
@@ -1011,7 +1011,7 @@ class TemplatesWidgetCalendarTest extends TemplatesIntonationTestCase {
               'id_categorie' => '22',
               'events_only' => true,
               'event_date' => '2020-04',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -1023,7 +1023,7 @@ class TemplatesWidgetCalendarTest extends TemplatesIntonationTestCase {
               'id_categorie' => '22',
               'events_only' => true,
               'event_date' => '',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true,
@@ -1036,7 +1036,7 @@ class TemplatesWidgetCalendarTest extends TemplatesIntonationTestCase {
               'id_categorie' => '22',
               'events_only' => true,
               'event_date' => '2020-04',
-              'id_bib' => 0,
+              'id_bib' => [''],
               'id_lieu' => '',
               'custom_fields' => [],
               'published' => true])
diff --git a/tests_db/UpgradeDBTest.php b/tests_db/UpgradeDBTest.php
index 164f28b95018ca9e7e713a85845d817202beb18d..db2d9182e30806ba7bc2b1ae4f0bf6c5ae566e93 100644
--- a/tests_db/UpgradeDBTest.php
+++ b/tests_db/UpgradeDBTest.php
@@ -6315,3 +6315,151 @@ class UpgradeDB_470_Test extends UpgradeDBTestCase
     $this->assertEquals([$id], $filter_value );
   }
 }
+
+
+
+
+class UpgradeDB_471_Test extends UpgradeDBTestCase {
+
+  protected $_users = [['Test_Jean', 90, 0],
+                       ['Test_Joe', 90, 1],
+                       ['Test_Charles', 90, 2],
+                       ['Test_Stephane', 90, 3],
+                       ['Test_Regis', 91, 4],
+                       ['Test_Luc', 92, 5],
+                       ['Test_Michele', 92, 6],
+                       ['Test_Lucy', 0, 6]];
+
+  public function prepare(){
+    foreach ( $this->_users as $user)
+      $this->query("INSERT INTO bib_admin_users (login, password, id_site, role_level) values('{$user[0]}', 'secret', '{$user[1]}', '{$user[2]}')");
+
+  }
+
+  public function tearDown() {
+    foreach ($this->_users as $user)
+      $this->query("delete from bib_admin_users where login = '{$user[0]}';");
+    parent::tearDown();
+  }
+
+
+  /** @test */
+  public function guestShouldHaveEmptyManagedLibraries()
+  {
+    $this->assertEquals('',Class_Users::findFirstBy(['login' => 'Test_Jean'])
+                        ->getManagedLibraries());
+  }
+
+
+  /** @test */
+  public function suscriberShouldHaveEmptyManagedLibraries()
+  {
+    $this->assertEquals('',Class_Users::findFirstBy(['login' => 'Test_Joe'])
+                        ->getManagedLibraries());
+  }
+
+
+  /** @test */
+  public function ilsSuscriberShouldHaveEmptyManagedLibraries()
+  {
+    $this->assertEquals('',Class_Users::findFirstBy(['login' => 'Test_Charles'])
+                        ->getManagedLibraries());
+  }
+
+
+  /** @test */
+  public function modoLibraryShouldHaveManagedLibrary90()
+  {
+    $this->assertEquals(90 ,Class_Users::findFirstBy(['login' => 'Test_Stephane'])
+                        ->getManagedLibraries());
+  }
+
+
+  /** @test */
+  public function adminLibraryShouldHaveManagedLibrary90()
+  {
+    $this->assertEquals(91 ,Class_Users::findFirstBy(['login' => 'Test_Regis'])
+                        ->getManagedLibraries());
+  }
+
+
+  /** @test */
+  public function modoPortalShouldHaveManagedLibrary90()
+  {
+    $this->assertEquals(92 ,Class_Users::findFirstBy(['login' => 'Test_Luc'])
+                        ->getManagedLibraries());
+  }
+
+
+  /** @test */
+  public function adminPortalShouldHaveManagedLibrary90()
+  {
+    $this->assertEquals(92 ,Class_Users::findFirstBy(['login' => 'Test_Michele'])
+                        ->getManagedLibraries());
+  }
+
+
+  /** @test */
+  public function adminPortalWithIdSite0ShouldNotHaveManagedLibrary()
+  {
+    $this->assertEquals('' ,Class_Users::findFirstBy(['login' => 'Test_Lucy'])
+                        ->getManagedLibraries());
+  }
+}
+
+
+
+
+class UpgradeDB_472_Test extends UpgradeDBTestCase {
+  protected
+    $_system_cat_id,
+    $_prev_super_rights,
+    $_prev_admin_rights,
+    $_super_group,
+    $_admin_group;
+
+  public function prepare(){
+    $this->_system_cat_id = Class_UserGroupCategorie::findFirstBy(['libelle' => 'Système'])
+      ->getId();
+
+    $this->_super_group = Class_UserGroup::findFirstBy(['libelle' => 'Super administrateurs',
+                                                        'id_cat' => $this->_system_cat_id]);
+
+    $this->_prev_super_rights = $this->_super_group->getRightsToken();
+    $this->_super_group->setRightsToken(0)->save();
+
+    $this->_admin_group = Class_UserGroup::findFirstBy(['libelle' => 'Administrateurs portail',
+                                                        'id_cat' => $this->_system_cat_id]);
+
+    $this->_prev_admin_rights = $this->_admin_group->getRightsToken();
+    $this->_admin_group->setRightsToken(0)->save();
+  }
+
+  public function tearDown() {
+    Class_UserGroup::findFirstBy(['libelle' => 'Super administrateurs',
+                                  'id_cat' => $this->_system_cat_id])
+      ->setRightsToken($this->_prev_super_rights)
+      ->save();
+
+    Class_UserGroup::findFirstBy(['libelle' => 'Administrateurs portail',
+                                  'id_cat' => $this->_system_cat_id])
+      ->setRightsToken($this->_prev_admin_rights)
+      ->save();
+  }
+
+
+  /** @test */
+  public function superAdminGroupShouldHaveAdminProfileRight()
+  {
+    $this->assertTrue(in_array(Class_UserGroup::RIGHT_ADMIN_PROFILE,
+                               $this->_super_group->getRights()));
+  }
+
+
+  /** @test */
+  public function adminPortalGroupShouldHaveAdminProfileRight()
+  {
+    $this->assertTrue(in_array(Class_UserGroup::RIGHT_ADMIN_PROFILE,
+                               $this->_admin_group->getRights()));
+  }
+}