From 81a663dd633dc6f5dade55847c870337fe13327b Mon Sep 17 00:00:00 2001
From: gloas <gloas@afi-sa.fr>
Date: Mon, 19 Aug 2019 15:43:03 +0200
Subject: [PATCH] wip on bootstrap

---
 .../admin/controllers/ProfilController.php    |  21 +++-
 .../admin/controllers/TemplateController.php  |   4 +-
 .../views/scripts/profil/_profil_row.phtml    |  27 +++--
 .../admin/views/scripts/profil/accueil.phtml  |   1 -
 library/Class/Newsletter.php                  |   2 +-
 library/Class/Profil.php                      |  16 ++-
 library/Class/Profil/Promoter.php             |  54 +++++++++
 .../Systeme/ModulesAccueil/MenuVertical.php   |   2 +-
 library/Class/Template.php                    |  20 +---
 .../Controller/Action/Helper/ViewRenderer.php |   4 +-
 .../View/Helper/Admin/FrontNavEntries.php     |   6 +-
 .../View/Helper/ProfileComposition.php        |  27 +++--
 .../ZendAfi/View/Helper/Widget/Section.php    |   2 +-
 .../View/Helper/Widget/Section/Main.php       |   2 +-
 .../Lekiosk/tests/LekioskTest.php             |   2 +-
 .../Intonation/Assets/css/intonation.css      |   9 +-
 .../Library/FormCustomizer/Abstract.php       |  47 ++++----
 .../templates/Intonation/System/Abstract.php  |  71 ++++++++++-
 .../templates/Intonation/System/Section.php   |   3 +-
 .../Intonation/System/Section/Loader.php      |  44 +++++++
 library/templates/Intonation/Template.php     |  25 +---
 .../View/Admin/ProfileComposition.php         |  52 ++++++++
 .../Intonation/View}/Admin/TagEditSection.php |   4 +-
 .../Intonation/View/Admin/TagVisibility.php   | 111 ++++++++++++++++++
 public/admin/css/config_accueil.css           |  42 ++++++-
 public/admin/css/front_nav.css                |  21 ++++
 public/admin/js/cfg.accueil.js                |  14 ++-
 scripts/profil_to_portail.php                 |   2 +-
 .../ModulesnoticeControllerTest.php           |  10 +-
 .../controllers/ProfilControllerTest.php      |   8 +-
 .../opac/controllers/AuthControllerTest.php   |   2 +-
 .../opac/controllers/BibControllerTest.php    |   4 +-
 .../opac/controllers/CmsControllerTest.php    |   2 +-
 .../opac/controllers/IndexControllerTest.php  |  10 +-
 tests/library/Class/ProfilTest.php            |   2 +-
 .../View/Helper/Abonne/AbonnementTest.php     |   4 +-
 tests/scenarios/Templates/TemplatesTest.php   |  55 ++++++++-
 .../Versionning/VersionningWidgetTest.php     |   4 +-
 38 files changed, 603 insertions(+), 133 deletions(-)
 create mode 100644 library/Class/Profil/Promoter.php
 create mode 100644 library/templates/Intonation/System/Section/Loader.php
 create mode 100644 library/templates/Intonation/View/Admin/ProfileComposition.php
 rename library/{ZendAfi/View/Helper => templates/Intonation/View}/Admin/TagEditSection.php (93%)
 create mode 100644 library/templates/Intonation/View/Admin/TagVisibility.php

diff --git a/application/modules/admin/controllers/ProfilController.php b/application/modules/admin/controllers/ProfilController.php
index 7c5d3445372..ca0b78b5983 100644
--- a/application/modules/admin/controllers/ProfilController.php
+++ b/application/modules/admin/controllers/ProfilController.php
@@ -77,8 +77,8 @@ class Admin_ProfilController extends ZendAfi_Controller_Action {
 
   public function indexAction() {
     $user = ZendAfi_Auth::getInstance()->getIdentity();
-    $profils = Class_Profil::getLoader()->findAllByZoneAndBib($this->id_zone,
-                                                              $this->id_bib);
+    $profils = Class_Profil::findAllByZoneAndBib($this->id_zone,
+                                                 $this->id_bib);
 
     $profils_by_bib = array();
     foreach ($profils as $profil) {
@@ -266,6 +266,23 @@ class Admin_ProfilController extends ZendAfi_Controller_Action {
   }
 
 
+  public function promoteAction() {
+    if ( !$profile = Class_Profil::find($this->_getParam('id_profil'))) {
+      $this->_helper->notify($this->_('Une erreur c\'est produite.'));
+      return $this->_redirectToIndex();
+    }
+
+    if ($profile->isPortail()) {
+      $this->_helper->notify($this->_('Une erreur c\'est produite.'));
+      return $this->_redirectToIndex();
+    }
+
+    (new Class_Profil_Promoter())->promote($profile);
+
+    $this->_redirect('/opac/index/index/id_profil/' . Class_Profil::DEFAULT_PROFIL);
+  }
+
+
   protected function updateAccueil($profil) {
     $enreg = $this->_parseSaveContentString();
     $enreg['use_parent_css'] = $this->_getParam('use_parent_css', $profil->getUseParentCss());
diff --git a/application/modules/admin/controllers/TemplateController.php b/application/modules/admin/controllers/TemplateController.php
index eda524395f4..a3df6a80fb8 100644
--- a/application/modules/admin/controllers/TemplateController.php
+++ b/application/modules/admin/controllers/TemplateController.php
@@ -56,12 +56,12 @@ class Admin_TemplateController extends ZendAfi_Controller_Action {
       return $this->_redirectToIndex();
     }
 
-    if(!$this->view->id_profile = $template->tryOn($profile)) {
+    if(!$id_profile = $template->tryOn($profile)) {
       $this->_helper->notify($this->_('Une erreur c\'est produite. Vous ne pouvez pas tester le template'));
       return $this->_redirectToIndex();
     }
 
-    $this->_redirect('/opac/index/index/id_profil/' . $this->view->id_profile);
+    $this->_redirect('/opac/index/index/id_profil/' . $id_profile);
   }
 
 
diff --git a/application/modules/admin/views/scripts/profil/_profil_row.phtml b/application/modules/admin/views/scripts/profil/_profil_row.phtml
index 9191b3aa496..0f43b4ba536 100644
--- a/application/modules/admin/views/scripts/profil/_profil_row.phtml
+++ b/application/modules/admin/views/scripts/profil/_profil_row.phtml
@@ -1,12 +1,11 @@
 <?php
-
 include_once('_profil_drag_drop.phtml');
 
 $this->current_profil = Class_Profil::getCurrentProfil();
+
 if ($this->profil->hasParentProfil())
   $this->profil = $this->profil->getParentProfil();
 
-
 if ($this->profil->isTelephone()) {
   $icone = 'telephone';
   $bulle="Interface pour téléphone";
@@ -50,7 +49,7 @@ if ($this->profil->isTelephone()) {
                             $this->boutonIco('picto=' . $action['icon'], 'bulle=' . $action['help']));
     }
 
-      if ($this->profil->isPortail() == 1) {
+      if ($this->profil->isPortail()) {
         $actions[]= ['action' => 'duplicate-config-modules', 'icon' => 'copy_module', 'help' => 'Appliquer la configuration des pages aux autres profils'];
 
         echo $this->tagAnchor($this->url(['action' => 'duplicate-config-modules', 'id_profil' => $this->profil->getId()]),
@@ -58,11 +57,23 @@ if ($this->profil->isTelephone()) {
                                                                                        'alt' => 'Appliquer la configuration des pages aux autres profils',
                                                                                        'onclick' => 'javascript:if(!confirm(\'Cette action permet d\\\'appliquer le même affichage des notices, résultats de recherches, fil d\\\'arianne et style de page à l\\\'ensemble des profils du site. Attention, cela écrasera la configuration des autres profils. Continuer ?\')) return false;']));
       }
-      else
-        echo
-          '<a href="'.BASE_URL.'/admin/profil/delete/id_profil/'.$this->profil->getId(). '">'.
-            $this->boutonIco("type=del").
-          '</a>';
+    else {
+      echo $this->tagAnchor(['module' => 'admin',
+                             'controller' => 'profil',
+                             'action' => 'delete',
+                             'id_profil' => $this->profil->getId()],
+                            $this->boutonIco("type=del"));
+
+      echo $this->renderModelAction($this->profil,
+                                     ['url' => ['module' => 'admin',
+                                                'controller' => 'profil',
+                                                'action' => 'promote',
+                                                'id_profil' => $this->profil->getId()],
+                                      'icon' => 'main_profil',
+                                      'label' => $this->_('Devenir le profil principal'),
+                                      'anchorOptions' => ['target' => '_blank',
+                                                          'onclick' => $this->confirm($this->_('Etes-vous sur de vouloir rendre le profil %s comme profil principal du site ?', $this->profil->getLibelle()))]]);
+    }
     ?>
   </div>
 
diff --git a/application/modules/admin/views/scripts/profil/accueil.phtml b/application/modules/admin/views/scripts/profil/accueil.phtml
index 2b2c1f49622..261743f7ecd 100644
--- a/application/modules/admin/views/scripts/profil/accueil.phtml
+++ b/application/modules/admin/views/scripts/profil/accueil.phtml
@@ -3,4 +3,3 @@ if (!$this->isPopup())
   echo $this->partial('profil/_profil_panel.phtml',
                       ['profil' => $this->profil]);
 echo $this->renderForm($this->form);
-?>
diff --git a/library/Class/Newsletter.php b/library/Class/Newsletter.php
index ef4b22bbe15..21941cec28f 100644
--- a/library/Class/Newsletter.php
+++ b/library/Class/Newsletter.php
@@ -241,7 +241,7 @@ class Class_Newsletter extends Storm_Model_Abstract {
 
 
   protected function _getMailPortail() {
-    $portail = Class_Profil::find(1);
+    $portail = Class_Profil::getPortail();
     return $portail->getMailSite();
   }
 
diff --git a/library/Class/Profil.php b/library/Class/Profil.php
index 7b274ed7d39..d451ff59ff5 100644
--- a/library/Class/Profil.php
+++ b/library/Class/Profil.php
@@ -51,8 +51,8 @@ class ProfilLoader extends Storm_Model_Loader {
   }
 
 
-  public function findAllByZoneAndBib($id_zone=0,$id_bib=0) {
-    $conditions = array('order' => 'libelle');
+  public function findAllByZoneAndBib($id_zone = 0, $id_bib = 0) {
+    $conditions = ['order' => 'libelle'];
 
     $where = '';
     if($id_zone and $id_zone !="ALL") {
@@ -70,12 +70,12 @@ class ProfilLoader extends Storm_Model_Loader {
       $conditions["ID_SITE"] = $id_bib;
     }
 
-    return  $this->findAllBy($conditions);
+    return  Class_Profil::findAllBy($conditions);
   }
 
 
   public function getPortail() {
-    return $this->find(1);
+    return Class_Profil::find(Class_Profil::DEFAULT_PROFIL);
   }
 
 
@@ -1794,7 +1794,13 @@ class Class_Profil extends Storm_Model_Abstract {
    * @return bool
    */
   public function isPortail() {
-    return 1 === (int)$this->getId();
+    return static::DEFAULT_PROFIL === (int) $this->getId();
+  }
+
+
+  public function bePortail() {
+    $this->setId(static::DEFAULT_PROFIL);
+    return $this;
   }
 
 
diff --git a/library/Class/Profil/Promoter.php b/library/Class/Profil/Promoter.php
new file mode 100644
index 00000000000..9195799f518
--- /dev/null
+++ b/library/Class/Profil/Promoter.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Copyright (c) 2012-2019, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Class_Profil_Promoter {
+
+  use Trait_Translator;
+
+
+  public function promote($profile) {
+    if ($profile->isPortail())
+      return $this;
+
+    $portal = Class_Profil::getPortail();
+
+    $this
+      ->_backup($portal);
+
+    $profile
+      ->bePortail()
+      ->setCommentaire($portal->getCommentaire())
+      ->save();
+
+    return $this;
+  }
+
+
+  protected function _backup($portal) {
+    $portal
+      ->deepCopy()
+      ->setLibelle($this->_('Sauvegarde de : %s', $portal->getLibelle()))
+      ->save();
+
+    return $this;
+  }
+}
diff --git a/library/Class/Systeme/ModulesAccueil/MenuVertical.php b/library/Class/Systeme/ModulesAccueil/MenuVertical.php
index 4b1b0b8e7bf..564b71991fe 100644
--- a/library/Class/Systeme/ModulesAccueil/MenuVertical.php
+++ b/library/Class/Systeme/ModulesAccueil/MenuVertical.php
@@ -95,7 +95,7 @@ class Class_Systeme_ModulesAccueil_MenuVertical extends Class_Systeme_ModulesAcc
 
 
   public function getMenus() {
-    $profiles = array_merge([Class_Profil::find(1)],
+    $profiles = array_merge([Class_Profil::getPortail()],
                              Class_Profil::findTopProfils());
 
     $menus = ['', static::NEW_MENU => $this->_('Créer un nouveau menu')];
diff --git a/library/Class/Template.php b/library/Class/Template.php
index 24718cb38c0..b2cb13e26be 100644
--- a/library/Class/Template.php
+++ b/library/Class/Template.php
@@ -200,16 +200,6 @@ class Class_Template {
   }
 
 
-  public function handleFooter() {
-    return false;
-  }
-
-
-  public function handleSideColumn() {
-    return true;
-  }
-
-
   public function handleRecordView() {
     return false;
   }
@@ -268,11 +258,6 @@ class Class_Template {
   }
 
 
-  public function getTagEditSection($id_section, $view) {
-    return '';
-  }
-
-
   public function getSection($id) {
     if(Class_Profil::DIV_FIRST_SIDE == $id)
       return new Class_Systeme_Widget_Section_FirstSide;
@@ -340,6 +325,11 @@ class Class_Template {
   }
 
 
+  public function addAdminHelperPath($view) {
+    return $this;
+  }
+
+
   public function handleMappings($post) {
     return $post;
   }
diff --git a/library/ZendAfi/Controller/Action/Helper/ViewRenderer.php b/library/ZendAfi/Controller/Action/Helper/ViewRenderer.php
index 30e69d1e784..20260353a2a 100644
--- a/library/ZendAfi/Controller/Action/Helper/ViewRenderer.php
+++ b/library/ZendAfi/Controller/Action/Helper/ViewRenderer.php
@@ -45,7 +45,6 @@ class ZendAfi_Controller_Action_Helper_ViewRenderer extends Zend_Controller_Acti
 
   public function preDispatch() {
     $this->_initializeHelperPaths();
-
     $request = $this->getRequest();
     $this->view->setModuleControllerActionNames($request->getModuleName(),
                                                 $request->getControllerName(),
@@ -60,8 +59,10 @@ class ZendAfi_Controller_Action_Helper_ViewRenderer extends Zend_Controller_Acti
 
   protected function _initializeHelperPaths() {
     $module = $this->getmodule();
+
     if (in_array($module, ['admin', 'cosmo'])) {
       $this->view->addHelperPath('ZendAfi/View/Helper/Admin/', 'ZendAfi_View_Helper_Admin');
+      Class_Template::current()->addAdminHelperPath($this->view);
       return $this;
     }
 
@@ -74,6 +75,7 @@ class ZendAfi_Controller_Action_Helper_ViewRenderer extends Zend_Controller_Acti
       $this->view->addHelperPath('ZendAfi/View/Helper/Java', 'ZendAfi_View_Helper_Java');
       $this->view->addHelperPath('ZendAfi/View/Helper/Accueil', 'ZendAfi_View_Helper_Accueil');
       $this->view->addScriptPath('.' . $profil_path . 'html');
+      Class_Template::current()->addAdminHelperPath($this->view);
       Class_Template::current()->addHelperPath($this->view);
       return $this;
     }
diff --git a/library/ZendAfi/View/Helper/Admin/FrontNavEntries.php b/library/ZendAfi/View/Helper/Admin/FrontNavEntries.php
index 10cfc721152..a7a200869f8 100644
--- a/library/ZendAfi/View/Helper/Admin/FrontNavEntries.php
+++ b/library/ZendAfi/View/Helper/Admin/FrontNavEntries.php
@@ -273,8 +273,10 @@ class ZendAfi_View_Helper_Admin_FrontNavEntries extends ZendAfi_View_Helper_Base
 
     return $this->_toggleAnchor($this->_('Déplacement des boites'),
                                 'block_sorting',
-                                sprintf('opacBlocksSorting(\'%s\',%d); $("div.layout-division>div").sortable("enable");', Class_Url::absolute('/admin/profil/module-sort'), Class_Profil::getCurrentProfil()->getId()),
-                                '$("div.layout-division>div").sortable("disable");');
+                                sprintf('opacBlocksSorting(\'%s\',%d); $("div.layout-division>div, .section_content_wrapper").sortable(\'enable\');',
+                                        Class_Url::absolute('/admin/profil/module-sort'),
+                                        Class_Profil::getCurrentProfil()->getId()),
+                                '$("div.layout-division>div, .section_content_wrapper").sortable("disable");');
 
   }
 
diff --git a/library/ZendAfi/View/Helper/ProfileComposition.php b/library/ZendAfi/View/Helper/ProfileComposition.php
index 4deb63a05e7..3c252105ec7 100644
--- a/library/ZendAfi/View/Helper/ProfileComposition.php
+++ b/library/ZendAfi/View/Helper/ProfileComposition.php
@@ -108,16 +108,12 @@ class ZendAfi_View_Helper_ProfileComposition extends ZendAfi_View_Helper_BaseHel
 
 
   protected function _getSideColumn() {
-    return Class_Template::current()->handleSideColumn()
-      ? $this->_getDivisionColumn(5, $this->_('Division flottante'))
-      : '';
+    return $this->_getDivisionColumn(5, $this->_('Division flottante'));
   }
 
 
   protected function _getFooterColumn() {
-    return Class_Template::current()->handleFooter()
-      ? $this->_getDivisionColumn(Class_Profil::DIV_FOOTER, $this->_('Division pied de page'))
-      : '';
+    return '';
   }
 
 
@@ -135,8 +131,7 @@ class ZendAfi_View_Helper_ProfileComposition extends ZendAfi_View_Helper_BaseHel
     return
       $this->_tag('div',
                   $this->_tag('h5',
-                              $label
-                              . Class_Template::current()->getTagEditSection($column, $this->view))
+                              $label . $this->_getActions($column))
                   . $this->_tag('input', null, ['type' => 'hidden', 'name' => 'division' . $column])
                   . $this->_tag('ul',
                                 $this->_getHTMLForDivision($column),
@@ -146,6 +141,11 @@ class ZendAfi_View_Helper_ProfileComposition extends ZendAfi_View_Helper_BaseHel
   }
 
 
+  protected function _getActions($column) {
+    return '';
+  }
+
+
   protected function _getHTMLForDivision($division) {
     $profil = Class_Profil::getCurrentProfil();
     $html = '';
@@ -156,10 +156,15 @@ class ZendAfi_View_Helper_ProfileComposition extends ZendAfi_View_Helper_BaseHel
       $html .= $this->_getItemModule($module['type_module'],
                                      Class_Systeme_ModulesAccueil::moduleByCode($module['type_module'])->getLibelle(),
                                      $id_module,
-                                     $helper->getConfig($id_module,
-                                                        $module['type_module'],
-                                                        $division));
+                                     $this->_getWidgetActions($helper, $id_module, $module['type_module'], $division));
 
     return $html;
   }
+
+
+  protected function _getWidgetActions($helper, $id_module, $type_module, $division) {
+    return $helper->getConfig($id_module,
+                              $type_module,
+                              $division);
+  }
 }
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/Widget/Section.php b/library/ZendAfi/View/Helper/Widget/Section.php
index ba919a5b7c6..6c4e9d65a84 100644
--- a/library/ZendAfi/View/Helper/Widget/Section.php
+++ b/library/ZendAfi/View/Helper/Widget/Section.php
@@ -94,7 +94,7 @@ class ZendAfi_View_Helper_Widget_Section extends ZendAfi_View_Helper_BaseHelper
 
   public function getAdminTools() {
     return $this->_tag('div',
-                       $this->view->Admin_TagEditSection($this->_section),
+                       $this->view->tagEditSection($this->_section),
                        ['class' => 'section_configuration',
                         'style' => 'text-align:right']);
   }
diff --git a/library/ZendAfi/View/Helper/Widget/Section/Main.php b/library/ZendAfi/View/Helper/Widget/Section/Main.php
index fd7e3bb4aba..0e9e9b42892 100644
--- a/library/ZendAfi/View/Helper/Widget/Section/Main.php
+++ b/library/ZendAfi/View/Helper/Widget/Section/Main.php
@@ -28,7 +28,7 @@ class ZendAfi_View_Helper_Widget_Section_Main extends ZendAfi_View_Helper_Widget
                                        null,
                                        [function()
                                         {
-                                          return $this->view->Admin_TagEditSection($this->_section);
+                                          return $this->view->tagEditSection($this->_section);
                                         }]);
   }
 
diff --git a/library/digital_resources/Lekiosk/tests/LekioskTest.php b/library/digital_resources/Lekiosk/tests/LekioskTest.php
index 7c727e0607e..98eec122587 100644
--- a/library/digital_resources/Lekiosk/tests/LekioskTest.php
+++ b/library/digital_resources/Lekiosk/tests/LekioskTest.php
@@ -82,7 +82,7 @@ class LekioskLinkModeLinkTest extends LekioskLinkModeLinkTestCase {
 
   /** @test */
   public function withEmptyUserMailShouldGetSiteOrProfileMail() {
-    Class_Profil::find(1)->setMailSite('toto@example.com');
+    Class_Profil::getPortail()->setMailSite('toto@example.com');
     $expected = 'https://pros.lekiosk.com/login/accesshash?email=bd612092eb8f12afc609f161d641ba9a4ac6b6e45bfae616f4994f9205f50a7d&id=66&AccessHash=4c09021c872852de07b4e5e89a9fc1659a3c293c';
     $this->assertEquals($expected, (new Lekiosk_Link(''))->url());
   }
diff --git a/library/templates/Intonation/Assets/css/intonation.css b/library/templates/Intonation/Assets/css/intonation.css
index 867e08589e3..79c5237d2e8 100644
--- a/library/templates/Intonation/Assets/css/intonation.css
+++ b/library/templates/Intonation/Assets/css/intonation.css
@@ -550,10 +550,17 @@ dl.row {
     right: 0 !important;
 }
 
-
 .card-deck > .card,
 .card-columns > .card {
     overflow: hidden;
 }
 
+.ui-sortable-placeholder {
+    visibility: visible !important;
+    background-color: var(--front-background-modale);
+    heigth: 200px;
+}
 
+.section_content_wrapper.ui-sortable {
+    height: 100%;
+}
\ No newline at end of file
diff --git a/library/templates/Intonation/Library/FormCustomizer/Abstract.php b/library/templates/Intonation/Library/FormCustomizer/Abstract.php
index 1249beb81da..5ce8baf9faf 100644
--- a/library/templates/Intonation/Library/FormCustomizer/Abstract.php
+++ b/library/templates/Intonation/Library/FormCustomizer/Abstract.php
@@ -101,15 +101,6 @@ class Intonation_Library_FormCustomizer_Abstract {
 
   protected function _addResponsiveGroupTo() {
     $this->_form
-      ->addElement('select',
-                   $this->_template->withNameSpace('hidden_mode'),
-                   ['label' => $this->_('Visible à partir de la taille'),
-                    'value' => Intonation_Library_Constants::RESPONSIVE_MODE_XSMALL,
-                    'multiOptions' => [Intonation_Library_Constants::RESPONSIVE_MODE_XSMALL => $this->_('très petite ( inférieur à 575px )'),
-                                       Intonation_Library_Constants::RESPONSIVE_MODE_SMALL => $this->_('petite ( entre 575px et 767px )'),
-                                       Intonation_Library_Constants::RESPONSIVE_MODE_MEDIUM => $this->_('moyenne ( entre 768px et 991px )'),
-                                       Intonation_Library_Constants::RESPONSIVE_MODE_LARGE => $this->_('grande ( entre 991px et 1199px ) '),
-                                       Intonation_Library_Constants::RESPONSIVE_MODE_XLARGE => $this->_('très grande ( supérieur à 1200px )')]])
 
       ->addElement('select',
                    $this->_template->withNameSpace('width_xsmall'),
@@ -225,7 +216,7 @@ class Intonation_Library_FormCustomizer_Abstract {
                                                 'offset_large',
                                                 'offset_xlarge']),
                                   $this->_template->withNameSpace('responsive_group'),
-                                  ['legend' => $this->_('Thème %s : responsive', $this->_template->getId()),
+                                  ['legend' => $this->_('Adaptabilité'),
                                    'order' => static::FOURTH]);
     return $this;
   }
@@ -233,6 +224,17 @@ class Intonation_Library_FormCustomizer_Abstract {
 
   protected function _addControllerVisibilityGroupTo() {
     $this->_form
+
+      ->addElement('select',
+                   $this->_template->withNameSpace('hidden_mode'),
+                   ['label' => $this->_('Visible à partir de la taille'),
+                    'value' => Intonation_Library_Constants::RESPONSIVE_MODE_XSMALL,
+                    'multiOptions' => [Intonation_Library_Constants::RESPONSIVE_MODE_XSMALL => $this->_('très petite ( inférieur à 575px )'),
+                                       Intonation_Library_Constants::RESPONSIVE_MODE_SMALL => $this->_('petite ( entre 575px et 767px )'),
+                                       Intonation_Library_Constants::RESPONSIVE_MODE_MEDIUM => $this->_('moyenne ( entre 768px et 991px )'),
+                                       Intonation_Library_Constants::RESPONSIVE_MODE_LARGE => $this->_('grande ( entre 991px et 1199px ) '),
+                                       Intonation_Library_Constants::RESPONSIVE_MODE_XLARGE => $this->_('très grande ( supérieur à 1200px )')]])
+
       ->addElement('checkbox',
                    $this->_template->withNameSpace('visibility_index'),
                    ['label' => $this->_('Index'),
@@ -263,17 +265,20 @@ class Intonation_Library_FormCustomizer_Abstract {
                    ['label' => $this->_('Authentification'),
                     'value' => 1]);
 
-    $this->_form->addDisplayGroup(array_map(function($element)
-                                            {
-                                              return $this->_template->withNameSpace('visibility_' . $element);
-                                            }, ['index',
-                                                'recherche',
-                                                'abonne',
-                                                'cms',
-                                                'blog',
-                                                'auth']),
+    $elements_list = array_merge([$this->_template->withNameSpace('hidden_mode')],
+                                 array_map(function($element)
+                                           {
+                                             return $this->_template->withNameSpace('visibility_' . $element);
+                                           }, ['index',
+                                               'recherche',
+                                               'abonne',
+                                               'cms',
+                                               'blog',
+                                               'auth']));
+
+    $this->_form->addDisplayGroup($elements_list,
                                   $this->_template->withNameSpace('visibility_group'),
-                                  ['legend' => $this->_('Thème %s : visibilité', $this->_template->getId()),
+                                  ['legend' => $this->_('Visibilité'),
                                    'order' => static::FIFTH]);
 
     return $this;
@@ -331,7 +336,7 @@ class Intonation_Library_FormCustomizer_Abstract {
                                     return $this->_template->withNameSpace($element);
                                   },$elements),
                         $this->_template->withNameSpace('group'),
-                        ['legend' => $this->_('Thème %s', $this->_template->getId()),
+                        ['legend' => $this->_('Thème'),
                          'order' => static::FIRST]);
     return $this;
   }
diff --git a/library/templates/Intonation/System/Abstract.php b/library/templates/Intonation/System/Abstract.php
index b16f26c317d..759a3fea2df 100644
--- a/library/templates/Intonation/System/Abstract.php
+++ b/library/templates/Intonation/System/Abstract.php
@@ -158,11 +158,11 @@ abstract class Intonation_System_Abstract {
     $request = Zend_Controller_Front::getInstance()->getRequest();
     $controller = strtolower($request->getControllerName());
 
-    return in_array($controller, $this->getAuthorizedControllers());
+    return in_array($controller, $this->_getAuthorizedControllers());
   }
 
 
-  public function getAuthorizedControllers() {
+  protected function _getAuthorizedControllers() {
     $controllers = [];
 
     if($this->isVisibleForIndexController())
@@ -192,6 +192,53 @@ abstract class Intonation_System_Abstract {
   }
 
 
+  public function isVisibleInControllers() {
+    return
+      $this->isVisibleForIndexController()
+      && $this->isVisibleForSearchController()
+      && $this->isVisibleForUserController()
+      && $this->isVisibleForCmsController()
+      && $this->isVisibleForBlogController()
+      && $this->isVisibleForAuthController();
+  }
+
+
+  public function isInvisbleInControllers() {
+    return
+      !$this->isVisibleForIndexController()
+      && !$this->isVisibleForSearchController()
+      && !$this->isVisibleForUserController()
+      && !$this->isVisibleForCmsController()
+      && !$this->isVisibleForBlogController()
+      && !$this->isVisibleForAuthController();
+  }
+
+
+  public function getInvisibleControllers() {
+    $controllers = [];
+
+    if(!$this->isVisibleForIndexController())
+      $controllers [] = $this->_('Index');
+
+    if(!$this->isVisibleForSearchController())
+      $controllers [] = $this->_('Résultat de recherche');
+
+    if(!$this->isVisibleForUserController())
+      $controllers [] = $this->_('Espace abonné');
+
+    if(!$this->isVisibleForCmsController())
+      $controllers [] = $this->_('Articles, agenda, bibliothèque');
+
+    if(!$this->isVisibleForBlogController())
+      $controllers [] = $this->_('Avis');
+
+    if(!$this->isVisibleForAuthController())
+      $controllers [] = $this->_('Authentification');
+
+    return $controllers;
+  }
+
+
   public function isVisibleForIndexController() {
     $function_name = 'get' . Class_Template::current()->withNameSpace('visibility_index');
     return call_user_func([$this, $function_name]);
@@ -228,6 +275,26 @@ abstract class Intonation_System_Abstract {
   }
 
 
+  public function isVisibleFromXL() {
+    return $this->getIntonationHiddenMode() == Intonation_Library_Constants::RESPONSIVE_MODE_XLARGE;
+  }
+
+
+  public function isVisibleFromL() {
+    return $this->getIntonationHiddenMode() == Intonation_Library_Constants::RESPONSIVE_MODE_LARGE;
+  }
+
+
+  public function isVisibleFromM() {
+    return $this->getIntonationHiddenMode() == Intonation_Library_Constants::RESPONSIVE_MODE_MEDIUM;
+  }
+
+
+  public function isVisibleFromS() {
+    return $this->getIntonationHiddenMode() == Intonation_Library_Constants::RESPONSIVE_MODE_SMALL;
+  }
+
+
   protected function _defaultsSettings() {
     $map = ['expand_breakpoint' => Intonation_Library_Constants::RESPONSIVE_MODE_SMALL,
             'hidden_mode' => Intonation_Library_Constants::WIDTH_AUTO,
diff --git a/library/templates/Intonation/System/Section.php b/library/templates/Intonation/System/Section.php
index 632e5cfa4ba..c9ee281bdf4 100644
--- a/library/templates/Intonation/System/Section.php
+++ b/library/templates/Intonation/System/Section.php
@@ -55,7 +55,8 @@ class Intonation_System_Section extends Intonation_System_Abstract {
     if(is_array($classes))
       $classes = trim(implode(' ', $classes));
 
-    return ['class' => implode(' ',
+    return ['data-division' => $this->getId(),
+            'class' => implode(' ',
                                array_filter([$classes,
                                              $this->_getOrderClass(),
                                              $this->_getResponsiveWidths(),
diff --git a/library/templates/Intonation/System/Section/Loader.php b/library/templates/Intonation/System/Section/Loader.php
new file mode 100644
index 00000000000..74ff1a833e4
--- /dev/null
+++ b/library/templates/Intonation/System/Section/Loader.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Copyright (c) 2012-2019, 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 Intonation_System_Section_Loader {
+  public function load($section_id) {
+    if ($section_id == Class_Profil::DIV_BANNIERE)
+      return new Intonation_System_Section_Header;
+
+    if ($section_id == Class_Profil::DIV_FOOTER)
+      return new Intonation_System_Section_Footer;
+
+    if ($section_id == Class_Profil::DIV_FIRST_SIDE)
+      return new Intonation_System_Section_FirstSide;
+
+    if ($section_id == Class_Profil::DIV_MAIN)
+      return new Intonation_System_Section_Main;
+    if ($section_id == Class_Profil::DIV_SECOND_SIDE)
+      return new Intonation_System_Section_SecondSide;
+
+    if ($section_id == Class_Profil::DIV_FLOTANTTE)
+      return new Intonation_System_Section_FloatSide;
+
+    return new Intonation_System_Section;
+  }
+}
diff --git a/library/templates/Intonation/Template.php b/library/templates/Intonation/Template.php
index b1f74d2e468..42cd2d5e364 100644
--- a/library/templates/Intonation/Template.php
+++ b/library/templates/Intonation/Template.php
@@ -53,16 +53,6 @@ class Intonation_Template extends Class_Template {
   }
 
 
-  public function handleFooter() {
-    return true;
-  }
-
-
-  public function handleSideColumn() {
-    return false;
-  }
-
-
   public function handleRecordView() {
     return true;
   }
@@ -203,15 +193,6 @@ class Intonation_Template extends Class_Template {
   }
 
 
-  public function getTagEditSection($id_section, $view) {
-    $section = (new Class_Systeme_Widget_Section)
-      ->setId($id_section)
-      ->setProfileId($this->getProfile()->getId())
-      ->load();
-    return $view->Admin_TagEditSection($section);
-  }
-
-
   public function getSection($id) {
     if(Class_Profil::DIV_FIRST_SIDE == $id)
       return new Intonation_System_Section_FirstSide;
@@ -241,6 +222,12 @@ class Intonation_Template extends Class_Template {
   }
 
 
+  public function addAdminHelperPath($view) {
+    $view->addHelperPath('templates/Intonation/View/Admin', 'Intonation_View_Admin');
+    return $this;
+  }
+
+
   public function handleMappings($post) {
     $post = parent::handleMappings($post);
 
diff --git a/library/templates/Intonation/View/Admin/ProfileComposition.php b/library/templates/Intonation/View/Admin/ProfileComposition.php
new file mode 100644
index 00000000000..b3a79f91c92
--- /dev/null
+++ b/library/templates/Intonation/View/Admin/ProfileComposition.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Intonation_View_Admin_ProfileComposition extends ZendAfi_View_Helper_ProfileComposition {
+  protected function _getSideColumn() {
+    return '';
+  }
+
+
+  protected function _getFooterColumn() {
+    return $this->_getDivisionColumn(Class_Profil::DIV_FOOTER, $this->_('Division pied de page'));
+  }
+
+
+  protected function _getActions($column) {
+    $section = (new Intonation_System_Section_Loader)->load($column);
+    return $this->view->tagEditSection($section)
+      . $this->view->tagVisibility($section);
+  }
+
+
+  protected function _getWidgetActions($helper, $id_module, $type_module, $division) {
+    $widget = (new Intonation_System_Widget)
+      ->setSettings((new Class_Systeme_Widget_Widget())
+                    ->setId($id_module)
+                    ->setProfileId(Class_Profil::getCurrentProfil()->getId())
+                    ->setSection((new Intonation_System_Section_Loader)->load($division))
+                    ->load());
+
+    return parent::_getWidgetActions($helper, $id_module, $type_module, $division)
+      . $this->view->tagVisibility($widget);
+  }
+}
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/Admin/TagEditSection.php b/library/templates/Intonation/View/Admin/TagEditSection.php
similarity index 93%
rename from library/ZendAfi/View/Helper/Admin/TagEditSection.php
rename to library/templates/Intonation/View/Admin/TagEditSection.php
index 1d03fe77183..b7a7c6496a6 100644
--- a/library/ZendAfi/View/Helper/Admin/TagEditSection.php
+++ b/library/templates/Intonation/View/Admin/TagEditSection.php
@@ -20,9 +20,9 @@
  */
 
 
-class ZendAfi_View_Helper_Admin_TagEditSection extends ZendAfi_View_Helper_BaseHelper {
+class Intonation_View_Admin_TagEditSection extends ZendAfi_View_Helper_BaseHelper {
 
-  public function Admin_TagEditSection($section) {
+  public function tagEditSection($section) {
     if (!Class_Users::isCurrentUserAllowedToEditProfile($section->getProfile()))
       return '';
 
diff --git a/library/templates/Intonation/View/Admin/TagVisibility.php b/library/templates/Intonation/View/Admin/TagVisibility.php
new file mode 100644
index 00000000000..c79e4a4237c
--- /dev/null
+++ b/library/templates/Intonation/View/Admin/TagVisibility.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Copyright (c) 2012-2019, 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 Intonation_View_Admin_TagVisibility extends ZendAfi_View_Helper_BaseHelper {
+  public function tagVisibility($section_or_widget) {
+    Class_ScriptLoader::getInstance()
+      ->addFontAwesome();
+
+    $html = [$this->_getVisibility($section_or_widget),
+
+             $this->_getResponsive($section_or_widget)];
+
+    return implode($html);
+  }
+
+
+  protected function _getVisibility($section_or_widget) {
+    $visibility = $this->_getVisibilityStatus($section_or_widget);
+
+    return ($class = $visibility->getClass())
+      ? $this->_htmlTag($this->_tag('i', '', ['class' => 'fa fa-eye ' . $class]),
+                        $visibility->getText())
+      : '';
+  }
+
+
+  protected function _getVisibilityStatus($section_or_widget) {
+    $title = $section_or_widget->getTitle();
+
+    if ($section_or_widget->isVisibleInControllers())
+      return new Class_Entity(['Class' => '']);
+
+    if ($section_or_widget->isInvisbleInControllers())
+      return new Class_Entity(['Class' => 'error',
+                               'Text' => $this->_('Visible dans aucune action.')]);
+
+    return new Class_Entity(['Class' => 'warning',
+                             'Text' => $this->_('Visible que dans certaines actions.')]);
+  }
+
+
+  protected function _getResponsive($section_or_widget) {
+    $responsive = $this->_getResponsiveStatus($section_or_widget);
+
+    $icos = [];
+    foreach($responsive->getIco() as $ico)
+      $icos [] = $this->_tag('i',
+                             '',
+                             ['class' => 'fa ' . $ico]);
+
+    return $icos
+      ? $this->_htmlTag(implode($icos), $responsive->getText())
+      : '';
+  }
+
+
+  protected function _htmlTag($ico, $text) {
+    return
+      $this->_tag('span',
+                  $ico . $this->_tag('p', $text, ['class' => 'hidden']),
+                  ['class' => 'section_visibility']);
+  }
+
+
+  protected function _getResponsiveStatus($section_or_widget) {
+    if ($section_or_widget->isVisibleFromXL())
+      return new Class_Entity(['Ico' => ['fa-mobile error',
+                                         'fa-tablet error',
+                                         'fa-desktop warning'],
+                               'Text' => $this->_('Visible à partir de la taille très grande (1200px).')]);
+
+    if ($section_or_widget->isVisibleFromL())
+      return new Class_Entity(['Ico' => ['fa-mobile error',
+                                         'fa-tablet error',
+                                         'fa-desktop success'],
+                               'Text' => $this->_('Visible à partir de la taille grande (991px).')]);
+
+    if ($section_or_widget->isVisibleFromM())
+      return new Class_Entity(['Ico' => ['fa-mobile error',
+                                         'fa-tablet warning',
+                                         'fa-desktop success'],
+                               'Text' => $this->_('Visible à partir de la taille moyenne (768px).')]);
+
+    if ($section_or_widget->isVisibleFromS())
+      return new Class_Entity(['Ico' => ['fa-mobile warning',
+                                         'fa-tablet success',
+                                         'fa-desktop success'],
+                               'Text' => $this->_('Visible à partir de la taille petite (575px).')]);
+
+    return new Class_Entity(['Ico' => []]);
+  }
+}
diff --git a/public/admin/css/config_accueil.css b/public/admin/css/config_accueil.css
index 725fdaec57a..0ed085889f7 100644
--- a/public/admin/css/config_accueil.css
+++ b/public/admin/css/config_accueil.css
@@ -91,16 +91,16 @@
 }
 
 .profile_composition .placeholder {
-    background: var(--anchor);
+    background-color: var(--anchor);
     height: 1em;
 }
 
 .profile_composition .container_list li {
-    background: var(--line-highlight);
+    background-color: var(--line-highlight);
 }
 
 .profile_composition .container_list li * {
-    background: transparent;
+    background-color: transparent;
 }
 
 .profile_composition .drag_drop_container + h4,
@@ -109,7 +109,41 @@
 }
 
 .profile_composition .drag_drop_container + h4 {
-    background: var(--button-background);
+    background-color: var(--button-background);
     color: var(--button);
     border-bottom: 0;
 }
+
+.section_visibility {
+    position: relative;
+    margin-left: 5px;
+    cursor: help;
+}
+
+.profile_composition .section_visibility .hidden {
+    display: none;
+    width: 100px;
+    position: absolute;
+    background-color: var(--widget-background);
+    border-radius: 5px;
+    box-shadow: 1px 1px 5px var(--widget-shadow);
+    box-sizing: border-box;
+    overflow: hidden;
+    text-transform: none;
+    line-height: 1em;
+    left: -40px;
+    top: 1.5em;
+    padding: 5px;
+    z-index: 101;
+    font-weight: normal;
+}
+
+.section_visibility:hover .hidden {
+    display: inline-block;
+}
+
+.section_visibility i {
+    font-size: 16px !important;
+    padding: 1px;
+    margin: 1px;
+}
\ No newline at end of file
diff --git a/public/admin/css/front_nav.css b/public/admin/css/front_nav.css
index ae87697ea65..79bf5c00dae 100644
--- a/public/admin/css/front_nav.css
+++ b/public/admin/css/front_nav.css
@@ -274,4 +274,25 @@ article header .edit_article {
 
 .menu_admin_front a:hover {
     background-color: var(--line-highlight);
+}
+
+body .required:after,
+body .error,
+body .errors,
+body .errors *,
+body .error * {
+    color: var(--error-text);
+}
+
+body .notice {
+    color: var(--notice-text);
+}
+
+body .success {
+    font-weight: bold;
+    color: var(--success-text);
+}
+
+body .warning {
+    color: var(--warning-text);
 }
\ No newline at end of file
diff --git a/public/admin/js/cfg.accueil.js b/public/admin/js/cfg.accueil.js
index 7a504fd6e86..913fc066ddc 100644
--- a/public/admin/js/cfg.accueil.js
+++ b/public/admin/js/cfg.accueil.js
@@ -23,11 +23,11 @@
 function opacBlocksSorting(moduleSortUrl, currentProfilId) {
   opacBlocksSortingInitPositions();
   
-  $('div.layout-division>div').sortable({
+  $('div.layout-division>div, .section_content_wrapper').sortable({
     cursor: 'move',
-    connectWith: 'div.layout-division>div',
+    connectWith: 'div.layout-division>div, .section_content_wrapper',
     stop: function(event, ui){
-      var newDivision = $(ui.item).parents('div.layout-division').attr("data-division");
+      var newDivision = $(ui.item).parents('div.layout-division, [data-division]').attr("data-division");
       var newPosition = $(ui.item).prevAll('div[data-position]').length;
       if (newDivision == $(ui.item).attr('data-division')
           && newPosition == $(ui.item).attr('data-position')) 
@@ -47,11 +47,13 @@ function opacBlocksSorting(moduleSortUrl, currentProfilId) {
 
 
 function opacBlocksSortingInitPositions() {
-	var currentPositions = [0, 0, 0];
-  $("div.layout-division>div>div").each(function(k, item) {
+  var currentPositions = [0, 0, 0];
+  $("div.layout-division>div>div, .section_content_wrapper > .widget").each(function(k, item) {
+
     if ("barre_nav" == $(item).attr("class")) 
       return;
-    var division = $(item).parents("div.layout-division").attr("data-division");
+    
+    var division = $(item).parents("div.layout-division, [data-division]").attr("data-division");
     $(item).attr("data-position", currentPositions[division-1]);
     currentPositions[division-1]++;
     $(item).attr("data-division", division);
diff --git a/scripts/profil_to_portail.php b/scripts/profil_to_portail.php
index fcfbb9b749b..cbadc114cab 100644
--- a/scripts/profil_to_portail.php
+++ b/scripts/profil_to_portail.php
@@ -1,7 +1,7 @@
 <?php
 require(__DIR__.'/../console.php');
 
-$portal = Class_Profil::find(1);
+$portal = Class_Profil::getPortail();
 
 if (!$new_portal = Class_Profil::find($argv[1])) {
   echo 'Profil not found. Given id: ' . $argv[1] . "\n";
diff --git a/tests/application/modules/admin/controllers/ModulesnoticeControllerTest.php b/tests/application/modules/admin/controllers/ModulesnoticeControllerTest.php
index b01fa547b8d..7edd6331bb5 100644
--- a/tests/application/modules/admin/controllers/ModulesnoticeControllerTest.php
+++ b/tests/application/modules/admin/controllers/ModulesnoticeControllerTest.php
@@ -112,7 +112,7 @@ class ModulesnoticeControllerExemplairesPostWithErrorsTest extends Admin_Abstrac
                     'parent_id'  => 1,
                     'libelle' => 'Cran/Accueil'])
          ->setLibelle('');
-    Class_Profil::find(1)->setLargeurSite(1);
+    Class_Profil::getPortail()->setLargeurSite(1);
 
     $this->postDispatch('/admin/modulesnotice/exemplaires/id_profil/2', []);
   }
@@ -144,13 +144,13 @@ class ModulesnoticeControllerExemplairesPostTest extends Admin_AbstractControlle
                                    'libelle' => 'Cran/Accueil']);
 
 
-    $config = Class_Profil::find(1)->getCfgNoticeAsArray();
+    $config = Class_Profil::getPortail()->getCfgNoticeAsArray();
     $config['exemplaires']['annexe'] = '1';
     $config['exemplaires']['bib'] = '0';
     $config['exemplaires']['emplacement'] = '0';
     $config['exemplaires']['order_by'] = 'b';
     $config['exemplaires']['en_pret'] = 'en pret';
-    Class_Profil::find(1)
+    Class_Profil::getPortail()
       ->setCfgNotice($config)
       ->assertSave();
 
@@ -180,7 +180,7 @@ class ModulesnoticeControllerExemplairesPostTest extends Admin_AbstractControlle
 
   /** @test */
   public function parentProfilOneItemsSettingsShouldHaveOrderByA() {
-    $this->assertEquals('a', Class_Profil::find(1)->getItemsSettings()['order_by']);
+    $this->assertEquals('a', Class_Profil::getPortail()->getItemsSettings()['order_by']);
   }
 
 
@@ -199,6 +199,6 @@ class ModulesnoticeControllerExemplairesPostTest extends Admin_AbstractControlle
   /** @test */
   public function enPretShouldEqualEmprunte() {
     $this->assertEquals('emprunté',
-                        Class_Profil::find(1)->getItemsSettings()['en_pret']);
+                        Class_Profil::getPortail()->getItemsSettings()['en_pret']);
   }
 }
\ 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 6b201a6be24..9c091baf4c9 100644
--- a/tests/application/modules/admin/controllers/ProfilControllerTest.php
+++ b/tests/application/modules/admin/controllers/ProfilControllerTest.php
@@ -1521,7 +1521,7 @@ class Admin_ProfilControllerProfilPortalLoginPagePostTest extends Admin_Abstract
 
   /** @test */
   public function loginPageShouldBe2() {
-    $this->assertEquals(2, Class_Profil::find(1)->getLoginPage());
+    $this->assertEquals(2, Class_Profil::getPortail()->getLoginPage());
   }
 }
 
@@ -1630,7 +1630,7 @@ class ProfilControllerPostDispatchAccueilProfilTest extends Admin_AbstractContro
                          'division2' => 'CALENDAR-0;PRETS-0;NEWSLETTERS-0;MULTIMEDIA-0',
                         ]);
 
-    $this->_profil = Class_Profil::find(1);
+    $this->_profil = Class_Profil::getPortail();
   }
 
 
@@ -1681,7 +1681,7 @@ class ProfilControllerPostDispatchReferencementProfilTest extends Admin_Abstract
                          'ref_tags' => 'master,profile,web'
                         ]);
 
-    $this->_profil = Class_Profil::find(1);
+    $this->_profil = Class_Profil::getPortail();
   }
 
 
@@ -1718,7 +1718,7 @@ class ProfilControllerDispatchReferencementProfilTest extends Admin_AbstractCont
 
     $this->dispatch('admin/profil/edit/id_profil/1', true);
 
-    $this->_profil = Class_Profil::find(1);
+    $this->_profil = Class_Profil::getPortail();
   }
 
 
diff --git a/tests/application/modules/opac/controllers/AuthControllerTest.php b/tests/application/modules/opac/controllers/AuthControllerTest.php
index 3825c864950..2837f8c8c0b 100644
--- a/tests/application/modules/opac/controllers/AuthControllerTest.php
+++ b/tests/application/modules/opac/controllers/AuthControllerTest.php
@@ -1169,7 +1169,7 @@ class AuthControllerBoiteLoginPostTest extends AuthControllerPostSimpleSuccessfu
 
   /** @test */
   public function responseShouldRedirectToReferrer() {
-    $this->assertRedirectTo(Class_Profil::find(1)->getUrl());
+    $this->assertRedirectTo(Class_Profil::getPortail()->getUrl());
   }
 }
 
diff --git a/tests/application/modules/opac/controllers/BibControllerTest.php b/tests/application/modules/opac/controllers/BibControllerTest.php
index 04acf742f59..9c5b0a0b8c1 100644
--- a/tests/application/modules/opac/controllers/BibControllerTest.php
+++ b/tests/application/modules/opac/controllers/BibControllerTest.php
@@ -1377,7 +1377,7 @@ class BibControllerBibSelectionUnselectPostDispatch extends BibControllerSelecti
 class BibControllerBibSelectionWithProfilIdParamTest extends BibControllerSelectionTestCase {
   public function setUp() {
     parent::setUp();
-    Class_Profil::setCurrentProfil(Class_Profil::find(1));
+    Class_Profil::setCurrentProfil(Class_Profil::getPortail());
     (new Class_Session_Libraries)->setIds([1, 2]);
     $this->dispatch('opac/index/index/id_profil/1', true);
   }
@@ -1394,7 +1394,7 @@ class BibControllerBibSelectionWithProfilIdParamTest extends BibControllerSelect
 class BibControllerBibSelectionWithProfilHasChangedTest extends BibControllerSelectionTestCase {
   public function setUp() {
     parent::setUp();
-    Class_Profil::setCurrentProfil(Class_Profil::find(1));
+    Class_Profil::setCurrentProfil(Class_Profil::getPortail());
     (new Class_Session_Libraries)->setIds([1, 2]);
     $this->dispatch('opac/index/index/id_profil/2', true);
   }
diff --git a/tests/application/modules/opac/controllers/CmsControllerTest.php b/tests/application/modules/opac/controllers/CmsControllerTest.php
index 473843de0f7..479f4f3d55b 100644
--- a/tests/application/modules/opac/controllers/CmsControllerTest.php
+++ b/tests/application/modules/opac/controllers/CmsControllerTest.php
@@ -1748,7 +1748,7 @@ class CmsControllerDispatchViewSummaryTest extends AbstractControllerTestCase {
                                                             'toggle_menu' => 0,
                                                             'menu' => 'V']]]];
 
-    $profile = Class_Profil::find(1)
+        $profile = Class_Profil::getPortail()
       ->setCfgMenus($cfg_menus)
       ->setCfgAccueil($cfg_accueil)
       ->assertSave();
diff --git a/tests/application/modules/opac/controllers/IndexControllerTest.php b/tests/application/modules/opac/controllers/IndexControllerTest.php
index d3516064752..83bbd165f54 100644
--- a/tests/application/modules/opac/controllers/IndexControllerTest.php
+++ b/tests/application/modules/opac/controllers/IndexControllerTest.php
@@ -106,7 +106,7 @@ class IndexControllerAsAdminWithCssEditorAndNoHeaderCss extends IndexControllerA
   public function setUp() {
     parent::setUp();
 
-    Class_Profil::find(1)->setHeaderCss('');
+    Class_Profil::getPortail()->setHeaderCss('');
     $this->dispatch('/?id_profil=1');
   }
 
@@ -190,7 +190,7 @@ class IndexControllerAsAdminWithCSSEditorAndUseParentCssFalseTest extends IndexC
     parent::setUp();
 
     //@see http://forge.afi-sa.fr/issues/59813
-    Class_Profil::find(1)
+    Class_Profil::getPortail()
       ->setUseParentCss(false)
       ->assertSave();
 
@@ -352,13 +352,13 @@ class IndexControllerAccessLevelWithLoginPageTest extends AbstractControllerTest
   public function setUp() {
     parent::setUp();
     ZendAfi_Auth::getInstance()->clearIdentity();
-    Class_Profil::setCurrentProfil(Class_Profil::find(1));
+    Class_Profil::setCurrentProfil(Class_Profil::getPortail());
   }
 
 
     /** @test */
   public function sameLoginPageShouldNotRedirect() {
-    Class_Profil::find(1)
+    Class_Profil::getPortail()
       ->setAccessLevel(ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB)
       ->setLoginPage(1)
       ->assertSave();
@@ -393,7 +393,7 @@ class IndexControllerAccessLevelWithLoginPageTest extends AbstractControllerTest
 
     /** @test */
   public function noLoginPageShouldNotRedirectToAdmin() {
-    Class_Profil::find(1)
+    Class_Profil::getPortail()
       ->setAccessLevel(ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB)
       ->setLoginPage(null)
       ->assertSave();
diff --git a/tests/library/Class/ProfilTest.php b/tests/library/Class/ProfilTest.php
index 34e728a48e5..1c22f0197c3 100644
--- a/tests/library/Class/ProfilTest.php
+++ b/tests/library/Class/ProfilTest.php
@@ -1306,7 +1306,7 @@ class ProfilWithPagesCopyTest extends ModelTestCase {
     $profil->assertSave();
     Class_Profil::clearCache();
 
-    $profil = Class_Profil::find(1);
+    $profil = Class_Profil::getPortail();
     $this->_clone = $profil->deepCopy();
     $this->_clone->assertSave();
   }
diff --git a/tests/library/ZendAfi/View/Helper/Abonne/AbonnementTest.php b/tests/library/ZendAfi/View/Helper/Abonne/AbonnementTest.php
index f7950c99748..81b73374066 100644
--- a/tests/library/ZendAfi/View/Helper/Abonne/AbonnementTest.php
+++ b/tests/library/ZendAfi/View/Helper/Abonne/AbonnementTest.php
@@ -16,7 +16,7 @@
  *
  * 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 
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 require_once 'library/ZendAfi/View/Helper/ViewHelperTestCase.php';
 
@@ -44,7 +44,7 @@ class View_Helper_Abonne_AbonnementTest extends ViewHelperTestCase {
   public function userDateFinAbonnementShouldReturnAbonnementValid() {
     $this->assertXPathContentContains($this->_helper->abonne_abonnement(Class_Users::newInstanceWithId(3)
                                                                         ->beAbonneSIGB()
-                                                                        ->setDateFin('2019-08-19')),
+                                                                        ->setDateFin('2919-08-19')),
                                       '//div[@class="abonnement"]',
                                       'Votre abonnement est valide');
   }
diff --git a/tests/scenarios/Templates/TemplatesTest.php b/tests/scenarios/Templates/TemplatesTest.php
index b2592449879..4b78c170edd 100644
--- a/tests/scenarios/Templates/TemplatesTest.php
+++ b/tests/scenarios/Templates/TemplatesTest.php
@@ -3633,4 +3633,57 @@ class TemplatesDispatchProfilAccueilTest extends TemplatesIntonationTestCase {
   public function formShouldContainsDataDivisions3() {
     $this->assertXPath('//form//div[@data-divisions="3"]');
   }
-}
\ No newline at end of file
+
+
+  /** @test */
+  public function aDivisionShouldBeInvisible() {
+    $this->assertXPath('//h5//span[contains(@class, "section_visibility")]//i[contains(@class, "warning")]');
+  }
+}
+
+
+
+class TemplatesDispatchProfilIndexTest extends TemplatesIntonationTestCase {
+  /** @test */
+  public function linkToPromoteShouldBePresent() {
+    Class_Profil::getPortail()->setIdSite(1)->save();
+    Class_Profil::find(72)->setIdSite(1)->save();
+    $this->dispatch('/admin/profil/index');
+    $this->assertXPath('//a[contains(@href, "/admin/profil/promote/id_profil/72")]',
+                       $this->_response->getBody());
+  }
+}
+
+
+
+class TemplatesIntonationPromoteProfileTest extends TemplatesIntonationTestCase {
+
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('/admin/profil/promote/id_profil/72');
+  }
+
+
+  /** @test */
+  public function mainProfileShouldUseIntonationTemplate() {
+    $this->assertEquals('INTONATION', Class_Profil::getPortail()->getTemplate());
+  }
+
+
+  /** @test */
+  public function mainProfileShouldHaveNoComment() {
+    $this->assertEquals('', Class_Profil::getPortail()->getCommentaire());
+  }
+
+
+  /** @test */
+  public function intonationTestProfileShouldPersist() {
+    $this->assertNotNull(Class_Profil::find(72));
+  }
+
+
+  /** @test */
+  public function mainProfileShouldHaveBeenBackup() {
+    $this->assertEquals('Sauvegarde de : portail', Class_Profil::find(73)->getLibelle());
+  }
+}
diff --git a/tests/scenarios/Versionning/VersionningWidgetTest.php b/tests/scenarios/Versionning/VersionningWidgetTest.php
index ff120ff75f3..fe6151484b0 100644
--- a/tests/scenarios/Versionning/VersionningWidgetTest.php
+++ b/tests/scenarios/Versionning/VersionningWidgetTest.php
@@ -254,7 +254,7 @@ class VersionningWidgetNewsDeleteTest extends VersionningWidgetNewsTestCase {
 
   /** @test */
   public function widgetShouldBeDeleted() {
-    $this->assertEmpty(Class_Profil::find(1)
+    $this->assertEmpty(Class_Profil::getPortail()
                        ->getModuleAccueilConfigByType('NEWS', 1, 3));
   }
 
@@ -393,7 +393,7 @@ class VersionningWidgetActivitiesVersionTest extends VersionningWidgetTestCase {
                              "rss_avis" => "1"]));
       ;
 
-      Class_Profil::find(1)
+      Class_Profil::getPortail()
         ->updateModuleConfigAccueil(3,
                                     ['type_module' => $this->_type_module,
                                      'division' => 1,
-- 
GitLab