diff --git a/VERSIONS b/VERSIONS
index f75396750b4b525e754294ca8fc844f6b3a92003..cbb214c4939d6e8d79bcf97d9bf880abb4e43daa 100644
--- a/VERSIONS
+++ b/VERSIONS
@@ -1,3 +1,54 @@
+11/02/2016 - v7.5.8
+
+ - ticket #37341 : Correction de l'affichage des types docs en résultat de recherche
+
+ - ticket #37440 : SSO 1DTouch : Prise en charge de la nouvelle adresse de ce fournisseur
+
+ - ticket #37100 : Performances: suppression du rendu AJAX des liens réseaux sociaux, optimisation des requêtes SQL pour les boîtes critiques, paniers et articles lorsqu'on est connecté en mode admin
+
+ - ticket #38299 : Administration : Correction du bouton de suppression de boite pour toujours afficher la popup de confirmation
+
+ - ticket #38336 : Administration: Correction de la version d'Imagick sur les serveurs hébergés par AFI et correction du déclenchement de l'indexaton des articles à la validation du formulaire
+
+ - ticket #33533 : Administration: correction de la navigation dans la modération des avis
+
+ - ticket #37199 : Administration : correction de la redirection dans la modération de formulaires
+
+ - ticket #38320 : Cosmogramme : Ajout d'une gestion d'erreur sur l'execution des différentes phases
+
+ - ticket #37078 : Cosmogramme : Correction du chemin de fichier généné lors de la génération de site Nanook
+
+
+
+08/02/2016 - v7.5.7
+
+ - ticket #38223 : Intégration cosmogramme : correction d'une incompatibilité avec la version 5.4.45 de PHP
+
+
+05/02/2016 - v7.5.6
+
+ - ticket #36925 : Administration : correction du sélecteur de bibliothèque dans la fiche utilisateur
+
+
+04/02/2016 - v7.5.5
+
+ - ticket #37718 : Correction de l'affichage de la boite calendrier.
+
+ - ticket #36925 : Administration : amélioration de la page recherche des utilisateurs
+
+ - ticket #37405 : Administration : correction de l'affichage des liens dans l'assistance
+
+ - ticket #37877 : Administration : correction de l'affichage des listes d'articles
+
+ - ticket #37359 : Administration : correction du compteur d'avis à modérer
+
+ - ticket #37886 : Administration charte Bokeh74 et Retro: correction de l'affichage des compteurs de modérations et d'inscriptions dans le menu gauche
+
+ - ticket #37850 : Ressource numérique 1dtouch : correction du moissonnage lorsque le serveur oneDTouch retourne une erreur
+
+ - ticket #37078 : Cosmogramme : Le lien de génération de site Nanook ne créait pas les imports paniers
+
+
 02/02/2016 - v7.5.4
 
  - ticket #34246 : Administration : nouvelle charte graphique
diff --git a/application/modules/admin/controllers/CmsController.php b/application/modules/admin/controllers/CmsController.php
index 002f59d931626edfec68002807fac38de235732c..a02b4149ff623d54fbf6f05585d95d957fd15e8c 100644
--- a/application/modules/admin/controllers/CmsController.php
+++ b/application/modules/admin/controllers/CmsController.php
@@ -33,7 +33,8 @@ class Admin_CmsController extends ZendAfi_Controller_Action {
                            'successful_add' => $this->_('L\'article "%s" a été sauvegardé'),
                            'successful_delete' => $this->_('Article "%s" supprimé')],
 
-            'actions' => ['add' => ['title' => $this->_("Ajouter un article")]]];
+            'actions' => ['add' => ['title' => $this->_("Ajouter un article")]],
+            'after_edit' => function ($model) { $model->index(); }];
   }
 
 
@@ -47,11 +48,6 @@ class Admin_CmsController extends ZendAfi_Controller_Action {
   }
 
 
-  protected function _postEditAction($article) {
-    $article->index();
-  }
-
-
   protected function _getBibs() {
     if (0 != $this->_bib->getId())
       return [$this->_bib];
diff --git a/application/modules/admin/controllers/ModoController.php b/application/modules/admin/controllers/ModoController.php
index 4966ad2622308e9eb338b9fd21dbceec95baa966..965635873f71fd20b50a3f7a1a2baccdc6a66eea 100644
--- a/application/modules/admin/controllers/ModoController.php
+++ b/application/modules/admin/controllers/ModoController.php
@@ -27,7 +27,9 @@ class Admin_ModoController extends ZendAfi_Controller_Action {
 
 
   public function avisnoticeAction() {
-    $this->subviewForStatus(0);
+    $status = $this->_getParam('status', 0);
+    $this->subviewForStatus($status);
+
     $this->_request->setParam('back', 'avisnotice');
     $this->_forward('index');
   }
@@ -103,14 +105,8 @@ class Admin_ModoController extends ZendAfi_Controller_Action {
 
                                                  'active_tab' => $active_tab]);
 
-}
-  public function allreviewsAction() {
-    $this->_request->setParam('back', 'avisnotice');
-    $this->subviewForStatus(1);
-    $this->_forward('index');
   }
 
-
   public function delavisnoticeAction() {
     $id = $this->_request->getParam('id');
     Class_AvisNotice::find($id)->delete();
@@ -119,7 +115,7 @@ class Admin_ModoController extends ZendAfi_Controller_Action {
 
   public function editavisnoticeAction() {
     if (!$avis = Class_AvisNotice::find((int)$this->_request->getParam('id'))) {
-      $this->_redirect('admin/modo/avisnotice');
+      $this->_redirectToAvisNotice();
       return;
     }
 
@@ -128,7 +124,7 @@ class Admin_ModoController extends ZendAfi_Controller_Action {
       ->addPermalinkFor($avis);
 
     if ($this->_editavisnoticePost($form, $avis)) {
-      $this->_redirect('admin/modo/avisnotice');
+      $this->_redirectToAvisNotice();
       return;
     }
 
@@ -158,13 +154,26 @@ class Admin_ModoController extends ZendAfi_Controller_Action {
 
   public function validateavisnoticeAction() {
     $id = $this->_request->getParam('id');
+
     Class_AvisNotice::find($id)
       ->setModerationOK()
       ->save();
-    $this->_redirect('admin/modo/avisnotice');
+
+    $this->_redirectToAvisNotice();
   }
 
 
+  protected function _redirectToAvisNotice() {
+    $page = $this->_request->getParam('page', 0);
+    $active_tab = $this->_request->getParam('active_tab', 1);
+    $status = $this->_request->getParam('status', 0);
+
+    $this->_redirect('/admin/modo/avisnotice/status/' . $status .
+                     '/active_tab/' . $active_tab .
+                     '/page/' . $page);
+
+  }
+
   public function deleteCmsAvisAction() {
     $avis = Class_Avis::find($this->_getParam('id'));
     $avis->delete();
@@ -768,7 +777,7 @@ class Admin_ModoController extends ZendAfi_Controller_Action {
     $formulaire_to_delete = Class_Formulaire::find($this->_getParam('id'));
     $formulaire_to_delete->delete();
     $this->_helper->notify($this->_('Formulaire supprimé'));
-    $this->_redirect('admin/modo/formulaires/id_article/'.$formulaire_to_delete->getIdArticle());
+    $this->_redirect($this->_getReferer());
   }
 
 
diff --git a/application/modules/admin/controllers/UsersController.php b/application/modules/admin/controllers/UsersController.php
index 45b14bd961e8b35bde13efd05db40f886fe43fa2..d297fc16cbc6511664e9f372413c923e592e4d6d 100644
--- a/application/modules/admin/controllers/UsersController.php
+++ b/application/modules/admin/controllers/UsersController.php
@@ -38,43 +38,51 @@ class Admin_UsersController extends ZendAfi_Controller_Action {
   }
 
 
-  public function init() {
-    parent::init();
-    $this->view->user = ZendAfi_Auth::getInstance()->getIdentity();
-    $this->view->id_zone = $_SESSION["admin"]["filtre_localisation"]["id_zone"];
-    $this->view->id_bib = $_SESSION["admin"]["filtre_localisation"]["id_bib"];
-  }
-
-
-  public function pageAction() {$this->_forward('index');}
-
-
   public function indexAction()  {
-    $this->view->titre = 'Gestion des utilisateurs';
-
-    $cls_user = new Class_Users();
-    $page=$this->_getParam('page');
-
-    $rech_user = array();
-    if (($this->_getParam('recherche') == 1)  and $this->_request->isPost()){
-      $rech_user=ZendAfi_Filters_Post::filterStatic($this->_request->getPost());
-      $_SESSION["admin"]["rech_user"] = $rech_user;
-    }
-
-    $ret = $cls_user->getUsers($this->view->id_zone,
-                               $this->view->id_bib,
-                               $this->view->user->ROLE_LEVEL,
-                               isset($_SESSION["admin"]["rech_user"]) ? $_SESSION["admin"]["rech_user"] : $rech_user,
-                               $page);
-
-    $this->view->users = $ret["users"];
-    $this->view->nb_par_page = $ret["nb_par_page"];
-    $this->view->nombre = $ret["nombre"];
-    $this->view->rech_user = $rech_user;
-    $this->view->url = $this->view->url(['module' => 'admin',
-                                         'controller' => 'users',
-                                         'action' => 'page'], null, true);
-    $this->view->page=$page;
+    $this->view->titre = $this->_('Gestion des utilisateurs');
+    $this->view->page = $this->_getParam('page', 1);
+
+    $id_site = $this->_getParam('by_id_site', 'all');
+
+    $role_level = Class_Users::getIdentity()->isAdmin()
+      ? $this->_getParam('by_role_level', 'all')
+      : $this->_getParam('by_role_level', ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB);
+
+    $search_value = str_replace(["\000",
+                                 "\n",
+                                 "\r",
+                                 "\"",
+                                 "\'",
+                                 "'",
+                                 "\032"], '', $this->_getParam('search_for', null));
+
+    $valide_subscription = $this->_getParam('by_valide_subscription', null);
+
+    $params = ['id_site' => $id_site,
+               'role_level' => $role_level];
+
+    $where = array_fill_keys(['login',
+                              'nom',
+                              'prenom',
+                              'pseudo',
+                              'mail',
+                              'idabon'],
+                             $search_value);
+
+    $this->view->params = ['by_id_site' => $id_site,
+                           'by_role_level' => $role_level,
+                           'search_for' =>  $search_value,
+                           'by_valide_subscription' => $valide_subscription,
+                           'page' => $this->view->page];
+
+    $this->view->users = Class_Users::findSearched($params,
+                                                   $where,
+                                                   $valide_subscription,
+                                                   [$this->view->page, 20]);
+    $this->view->total = Class_Users::countSearched($params,
+                                                    $where,
+                                                    $valide_subscription);
+    $this->view->form = ZendAfi_Form_Admin_SearchUsers::newWith($this->view->params);
   }
 
 
@@ -111,14 +119,6 @@ class Admin_UsersController extends ZendAfi_Controller_Action {
   }
 
 
-  protected function _getParams() {
-    $params=parent::_getParams();
-    unset($params['id_categories']);
-    return $params;
-
-  }
-
-
   public function changeAdminSkinAction() {
     $admin_skin = $this->_request->getParam(Class_User_Settings::ADMIN_SKIN, '');
     $color = $this->_request->getParam(Class_User_Settings::ADMIN_SKIN_COLOR, '');
diff --git a/application/modules/admin/views/scripts/modo/_avis_partial.phtml b/application/modules/admin/views/scripts/modo/_avis_partial.phtml
deleted file mode 100644
index d62871b971ccfd30203be4720ce61bb401a814fb..0000000000000000000000000000000000000000
--- a/application/modules/admin/views/scripts/modo/_avis_partial.phtml
+++ /dev/null
@@ -1,9 +0,0 @@
-<div class="<?php echo $this->item_class ?>">
-  <?php
-  $actions = ['validate', 'edit', 'del'];
-  if ($this->avis->getFlags()>=0)
-    $actions[] = ($this->avis->getFlags()==0) ? 'invisible' :'visible';
-  $this->getHelper('avis')->setActions($actions); ?>
-   <?php echo $this->avis($this->avis) ?>
-   <div class='clear'></div>
-</div>
diff --git a/application/modules/admin/views/scripts/modo/avisnotice.phtml b/application/modules/admin/views/scripts/modo/avisnotice.phtml
index 5443bf7c18cc8271f90129bcc0edafa5818e8449..2723490bbf939b23a850fb09585ae5b1dfb325c7 100644
--- a/application/modules/admin/views/scripts/modo/avisnotice.phtml
+++ b/application/modules/admin/views/scripts/modo/avisnotice.phtml
@@ -1,11 +1,19 @@
 <?php
 if ($this->display_all)
   echo $this->tag('h1', $this->_('Tous les avis de notices modérés')) .
-       $this->tagAnchor(['action' => 'avisnotice'], $this->_('Afficher les avis non modérés'));
+       $this->tagAnchor(['action' => 'avisnotice',
+                         'status' => '0',
+                         'active_tab' => null,
+                         'page' => null],
+                        $this->_('Afficher les avis non modérés'));
 
 if (!$this->display_all)
   echo $this->tag('h1', $this->_('Modération des avis sur les notices')) .
-       $this->tagAnchor(['action' => 'allreviews'], $this->_('Afficher tous les avis modérés'));
+       $this->tagAnchor(['action' => 'avisnotice',
+                         'status' => '1',
+                         'active_tab' => null,
+                         'page' => null],
+                        $this->_('Afficher tous les avis modérés'));
 
 echo $this->tag('div',
 
diff --git a/application/modules/admin/views/scripts/modo/index.phtml b/application/modules/admin/views/scripts/modo/index.phtml
index 1b11f4971506875d1209084e440971d5a81d239d..99a651c0993e5239cc84c7a6adbd439e0c1cd045 100644
--- a/application/modules/admin/views/scripts/modo/index.phtml
+++ b/application/modules/admin/views/scripts/modo/index.phtml
@@ -4,33 +4,33 @@ $modstats = $moderer->getModerationStats();
 
 $menus = [["icon" => "articles",
            "label" => "Articles",
-           "url" => $this->url(['action' => 'aviscms']),
+           "url" => $this->url(['module' => 'admin', 'controller' => 'modo', 'action' => 'aviscms'], null, true),
            "count" => $modstats['avis_articles']['count']],
           ["icon" => "books",
            "label" => "Notices",
-           "url" =>$this->url(['action' => 'avisnotice']),
+           "url" =>$this->url(['module' => 'admin', 'controller' => 'modo', 'action' => 'avisnotice'], null, true),
            "count" => $modstats['avis_notices']['count']],
           ["icon" => "tag",
            "label" => "Tags notices",
-           "url" => $this->url(['action' => 'tagnotice']),
+           "url" => $this->url(['module' => 'admin', 'controller' => 'modo', 'action' => 'tagnotice'], null, true),
            "count" => $modstats['tags_notices']['count']],
           ["icon" => "suggestion",
            "label" => "Suggestions d'achat",
-           "url" => $this->url(['action' => 'suggestion-achat']),
+           "url" => $this->url(['module' => 'admin', 'controller' => 'modo', 'action' => 'suggestion-achat'], null, true),
            "count" => $modstats['suggestions_achat']['count']]
 
-];
+          ];
 
 if (isset($modstats['formulaires'])) {
   $menus[] =
   ["icon" => "formulaires_16.png",
    "label" => "Formulaires",
-   "url" => $this->url(['action' => 'formulaires', 'id_article' => null]),
+   "url" => $this->url(['action' => 'formulaires', 'id_article' => null, 'status' => null, 'active_tab' => null, 'page' => null]),
    "count" => $modstats['formulaires']['count']]
   ;}
 ?>
 <div class="menu"><?php echo $this->getHelper('MenuHorizontalAdmin')->generateMenu($menus);?></div>
 
 <?php if ($this->subview) { ?>
-    <div class="subview"><?php echo $this->subview;?><div class="clear"></div></div>
+  <div class="subview"><?php echo $this->subview;?><div class="clear"></div></div>
 <?php } ?>
diff --git a/application/modules/admin/views/scripts/users/index.phtml b/application/modules/admin/views/scripts/users/index.phtml
index 984e031301a57662674383b75814419e7eb0df49..151067991458d3ca64134409ccd7ed910d5bb93a 100644
--- a/application/modules/admin/views/scripts/users/index.phtml
+++ b/application/modules/admin/views/scripts/users/index.phtml
@@ -1,57 +1,3 @@
-<?php
-echo $this->profileSelect('users',$this->id_zone,$this->id_bib,'zb',0,true,true,true);
-
-
-echo (Class_Users::getIdentity()->isAdmin() ? '<center><div align="center"><br>'.$this->bouton('id=19','picto=add','texte='.$this->traduire('Ajouter un utilisateur').'','url='.BASE_URL.'/admin/users/add/','largeur=210px').'</div></center>': '')  ;
-if(!$this->users)
-{
-    echo ("<br><p align='center' class='error'>Aucun utilisateur trouvé pour les critères spécifiés</b></p>");
-}
-else
-{
-?>
-<br />
-<table cellspacing="0" cellpadding="0">
-  <tr class="soustitre">
-    <td width="18%"><?php echo $this->traduire('Identifiant'); ?></td>
-    <td width="23%"><?php echo $this->traduire('Nom'); ?></td>
-    <td width="16%"><?php echo $this->traduire('Prénom'); ?></td>
-    <td width="23%" style="white-space: nowrap"><?php echo $this->traduire('Rôle'); ?></td>
-    <td width="10%"><?php echo $this->traduire('Bibliothèque'); ?></td>
-    <td colspan="2" style="width:10%;"><?php echo $this->traduire('Action'); ?></td>
-  </tr>
-  <tr>
-    <td colspan="10"  class="separ"></td>
-  </tr>
-<?php
-
-$acl = new  ZendAfi_Acl_AdminControllerRoles();
-
-$ligne=0;
-foreach($this->users as $user)
-{
-    $ligne ++ ;
-    if ($ligne & 1) $class="first"; else $class="second";
-    if ($user["ID_SITE"] =="0") $nom_bib = $this->_('Portail');
-    else $nom_bib=fetchOne("select nom_court from int_bib where id_bib=".$user["ID_SITE"]);
-    if (strlen($user["LOGIN"])>=15) $login= substr($user["LOGIN"],0,15).'...'; else $login=$user["LOGIN"];
-    if (strlen($nom_bib)>=40) $nom_bib_r= substr($nom_bib,0,40).'...'; else $nom_bib_r=$nom_bib;
-    echo('<tr class="'.$class.'">');
-    echo('<td valign="top">'.$login.'</td>');
-    echo('<td valign="top">'.$user["NOM"].'</td>');
-    echo('<td valign="top">'.$user["PRENOM"].'</td>');
-    echo('<td valign="top">'.$acl->getLibelleRole($user["ROLE_LEVEL"]).'</td>');
-    echo('<td valign="top">'.$nom_bib_r.'</td><td valign="top">');
-    if (Class_Users::getIdentity()->isAdmin()) {
-      echo('<a href="'.BASE_URL.'/admin/users/edit/id/'.$user["ID_USER"].'">'.$this->boutonIco("type=edit").'</a>&nbsp;&nbsp; <a href="'.BASE_URL.'/admin/users/delete/id/'.$user["ID_USER"].'">');
-      if ($user["ID_USER"] != '1') echo $this->boutonIco("type=del");
-
-    echo('</a>');
-    }
-    echo('</td></tr>');
-
-}
-echo ('</table>');
-echo BR.'<div align="center" style="width:100%">'.$this->pager($this->nombre,$this->nb_par_page,$this->page,$this->url).'</div>';
-}
-?>
+<?php
+echo $this->Admin_SearchUsers($this->users, $this->total, $this->form, $this->page, $this->params);
+?>
diff --git a/application/modules/opac/controllers/RechercheController.php b/application/modules/opac/controllers/RechercheController.php
index 868321cd27f6b7befa9397325bb51eda02e17614..baae09033cb3616d89ff87ad554069958cea4e91 100644
--- a/application/modules/opac/controllers/RechercheController.php
+++ b/application/modules/opac/controllers/RechercheController.php
@@ -419,14 +419,6 @@ class RechercheController extends ZendAfi_Controller_Action {
   }
 
 
-  public function reseauAction() {
-    $viewRenderer = $this->getHelper('ViewRenderer');
-    $viewRenderer->setNoRender();
-
-    echo $this->view->reseauxSociaux(Class_Notice::find($this->_getParam('id_notice', 0)));
-  }
-
-
   public function vignetteAction()  {
     $viewRenderer = $this->getHelper('ViewRenderer');
     $viewRenderer->setNoRender();
diff --git a/application/modules/opac/views/scripts/head.phtml b/application/modules/opac/views/scripts/head.phtml
index f04ea1841710a1aa8873154b8cf993dd6f8f4de7..9005e147654e2462fb275344f76bdb9cf534fd8d 100644
--- a/application/modules/opac/views/scripts/head.phtml
+++ b/application/modules/opac/views/scripts/head.phtml
@@ -38,7 +38,6 @@
        initializeImgHover();
        initializePopups();
        initializeDivisionFive();
-       initializeReseauxSociaux();
        initializeReloadModule();')
     ->addJQueryBackEnd(sprintf('$("#select_clef_profil").parent().prepend(\'%s\')',
                                $this->tagImg(URL_ADMIN_IMG.'ico/lock.png',
diff --git a/application/modules/opac/views/scripts/recherche/viewnotice.phtml b/application/modules/opac/views/scripts/recherche/viewnotice.phtml
index 5b18296b9f92135faae7f3fae7efafb542bbd5c6..558fb0ab8d336a64c66b8769cf3ff58cacae71f1 100644
--- a/application/modules/opac/views/scripts/recherche/viewnotice.phtml
+++ b/application/modules/opac/views/scripts/recherche/viewnotice.phtml
@@ -12,13 +12,7 @@ $script_loader = Class_ScriptLoader::getInstance()
 	   ->addSkinstylesheet('recherche')
 	   ->addOpacScripts(['subModal',
 										   'recherche',
-										   'liste_notices_mur'])
-
-     ->addJQueryReady(sprintf('$("#reseaux-sociaux").load("%s")',
-													    $this->url(['controller' => 'recherche',
-																					'action' => 'reseau',
-																					'id_notice' => $this->notice->getId(),
-																					'type_doc' => $this->notice->getTypeDoc()])));
+										   'liste_notices_mur']);
 ?>
 
 <div class="navigation">
@@ -65,7 +59,7 @@ $script_loader = Class_ScriptLoader::getInstance()
 								 $this->_('Modifier la vignette'));
   ?>
 
-  <div id="reseaux-sociaux"></div>
+  <div id="reseaux-sociaux"><?php echo $this->reseauxSociaux($this->notice); ?></div>
 </div>
 
 
diff --git a/build.sh b/build.sh
index 0b5d611865ce06f89cf7a5ddba1836a66302c31e..754d033fbb705731352cef55e58fdf9366f65467 100755
--- a/build.sh
+++ b/build.sh
@@ -14,4 +14,4 @@ sed -i "s/integration_pwd=root/integration_pwd=opac/g" config.php
 sed -i "s/integration_base=opac3/integration_base=opac/g" config.php
 cd ..
 
-phpunit -c tests/phpunit.xml --exclude-group no-ci && cd cosmogramme/tests && phpunit --exclude-group no-ci
+phpunit -c tests/phpunit.xml --exclude-group no-ci && cd cosmogramme/tests && phpunit --exclude-group no-ci && cd ../cosmozend/tests && phpunit --exclude-group no-ci
diff --git a/cosmogramme/cosmozend/application/modules/cosmo/controllers/IntegrationController.php b/cosmogramme/cosmozend/application/modules/cosmo/controllers/IntegrationController.php
index 190f3613cfb53b4770d087decd0d442358a9daf2..2c2d8d92b0e744fe0f941d4512d34f60fa2cc0e3 100644
--- a/cosmogramme/cosmozend/application/modules/cosmo/controllers/IntegrationController.php
+++ b/cosmogramme/cosmozend/application/modules/cosmo/controllers/IntegrationController.php
@@ -21,6 +21,8 @@
 
 
 class Cosmo_IntegrationController extends Zend_Controller_Action{
+  use Trait_Translator;
+
 	public function preDispatch() {
 		$this->cosmoPath = $this->view->cosmoPath = new CosmoPaths();
 	}
@@ -54,5 +56,25 @@ class Cosmo_IntegrationController extends Zend_Controller_Action{
 		if (!$this->view->response)
 			$this->view->response = 'Impossible de contacter le service';
 	}
-}
-?>
\ No newline at end of file
+
+
+  public function generateAction() {
+    $this->view->titre = $this->_('Génération automatique des paramètres d\'intégration pour Pergame et Nanook');
+    $log = Class_Log::getInstance();
+    $dir = Class_Cosmogramme_LandingDirectory::getInstance();
+    if (!$dir->isValid()) {
+      $this->view->error = $log->getLastMessage();
+      return;
+    }
+
+    $this->view->directories = $dir->getSubdirectories();
+    if (!$this->_request->isPost())
+      return;
+
+    $var = (new Class_Cosmogramme_Generator())->generate($this->_request->getPost())
+      ? 'log' : 'error';
+    $this->view->__set($var, $log->getMessages());
+
+    $this->render('generate-log');
+  }
+}
\ No newline at end of file
diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/integration/generate-log.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/integration/generate-log.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..929126a626b78ed8b923d31765ef2d93c7a956ff
--- /dev/null
+++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/integration/generate-log.phtml
@@ -0,0 +1,13 @@
+<h1><?php echo $this->titre; ?></h1>
+
+<?php
+if ($this->error) {
+  echo $this->cosmoError($this->error[0]);
+  echo $this->cosmoButton($this->_('Retour'), $this->url(['module' => 'cosmo',
+                                                          'controller' => 'integration',
+                                                          'action' => 'generate'],
+                                                         null, true));
+  return;
+}
+
+echo implode($this->log);?>
diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/integration/generate.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/integration/generate.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..c6e0bda52a8528ceea757dd2743863eb02fe537b
--- /dev/null
+++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/integration/generate.phtml
@@ -0,0 +1,65 @@
+<h1><?php echo $this->titre;?></h1>
+
+<h3><?php echo $this->_('Mode d\'emploi :'); ?></h3>
+<ol>
+	<li>Faire un export total depuis Pergame ou Nanook dans le dossier ftp de réplication des fichiers<br>
+	  voir <a href="config_variables.php" target="droite">la variable ftp_path (Chemins et variables système)</a>:
+    <?php echo Class_CosmoVar::getValueOf('ftp_path');?></li>
+	<li>Sélectionner le dossier dans le formulaire ci-dessous.</li>
+	<li>Sélectionner le SIGB dans le formulaire ci-dessous.</li>
+	<li>Valider.</li>
+</ol>
+
+<?php
+if ($this->error) {
+  echo $this->cosmoError($this->error);
+  return;
+}
+
+if (!$this->directories) {
+  echo $this->cosmoError($this->_('Aucun dossier n\'a été trouvé dans le dossier des transferts ftp'));
+  return;
+}
+?>
+
+<div class="liste">
+	<form method="post" action="">
+    <table class="form" width="100%" cellspacing="0" cellpadding="5">
+	    <tr><th class="form" colspan="2" align="left">Sélection du dossier ftp</th></tr>
+	    <tr>
+        <td class="form_first" align="right" width="43%">Nom du dossier ftp</td>
+        <td class="form_first"><?php echo $this->formSelect('path_ftp', '', [], $this->directories); ?></td>
+      </tr>
+	    <tr>
+        <td class="form_first" align="right">SIGB</td>
+        <td class="form_first"><?php echo $this->formSelect('type_sigb', '', [],
+                                                            [1 => 'Pergame', 13 => 'Nanook']); ?></td>
+      </tr>
+	    <tr>
+        <td class="form_first" align="right">url du web-service (Nanook uniquement)</td>
+        <td class="form_first"><?php echo $this->formText('service_nanook', '', ['size' => 55]); ?></td>
+      </tr>
+      <tr>
+        <td class="form_first" align="right">Format(0.8.7) :</td>
+        <td class="form_first">ip:port/chemin_tomcat/ilsdi/nom_base</td>
+      </tr>
+      <tr>
+        <td class="form_first" align="right">Exemple :</td>
+        <td class="form_first">62.193.55.152:8080/afi_NanookWs/ilsdi/NANOOK</td>
+      </tr>
+	    <tr>
+        <td class="form_first" align="right">Créer les annexes comme les bibliothèques</td>
+        <td class="form_first"><?php echo $this->formSelect('creer_annexes', '', [],
+                                                            [1 => 'oui', 2 => 'non']);?></td>
+      </tr>
+      <tr>
+        <td class="form_first" align="right">Synchroniser l'étalon à chaque import</td>
+        <td class="form_first"><?php echo $this->formSelect('synchro', '', [],
+                                                            [1 => 'oui', 2 => 'non']);?></td>
+      </tr>
+	    <tr>
+        <th class="form" colspan="2" align="center"><input type="submit" class="bouton" value="Valider"></th>
+      </tr>
+    </table>
+  </form>
+</div>
diff --git a/cosmogramme/cosmozend/index.php b/cosmogramme/cosmozend/index.php
index 5a13c4cc9b171a4ca7bdf6a15debc6e31829a7f3..1d9144579ad4686b7547b3c45d0225cf693c5f6a 100644
--- a/cosmogramme/cosmozend/index.php
+++ b/cosmogramme/cosmozend/index.php
@@ -30,6 +30,13 @@ set_include_path( $cosmozendPath
 . PATH_SEPARATOR . $cosmozendPath . '/application'
 . PATH_SEPARATOR . get_include_path());
 
+// pretending I am under Bokeh's root
+chdir('../..');
+
+Zend_Controller_Action_HelperBroker::resetHelpers();
+Zend_Controller_Action_HelperBroker::addHelper(new ZendAfi_Controller_Action_Helper_Cosmo_ViewRenderer());
+Zend_Controller_Action_HelperBroker::addPrefix('ZendAfi_Controller_Action_Helper_Cosmo');
+
 Zend_Session::start();
 Zend_Layout::startMvc();
 Zend_Layout::getMvcInstance()
diff --git a/cosmogramme/cosmozend/tests/CosmoControllerTestCase.php b/cosmogramme/cosmozend/tests/CosmoControllerTestCase.php
index 68f23d360dd185e5867ccf8f0d45cef54ecb1f72..311bf53dae7c17e3478b45140da0d20084eabc21 100644
--- a/cosmogramme/cosmozend/tests/CosmoControllerTestCase.php
+++ b/cosmogramme/cosmozend/tests/CosmoControllerTestCase.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
  */
 
 
@@ -25,14 +25,20 @@ abstract class CosmoControllerTestCase extends Zend_Test_PHPUnit_ControllerTestC
 
 	public $bootstrap = 'bootstrap_frontcontroller.php';
 
+  protected $_storm_default_to_volatile = true;
+
 	public function setUp() {
 		parent::setUp();
 		Storm_Model_Abstract::unsetLoaders();
 		Storm_Cache::setDefaultZendCache(null);
+    if ($this->_storm_default_to_volatile)
+      Storm_Model_Loader::defaultToVolatile();
 	}
 
 
 	public function tearDown() {
+    if ($this->_storm_default_to_volatile)
+      Storm_Model_Loader::defaultToDb();
 		Storm_Model_Abstract::unsetLoaders();
 	}
 
diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/IntegrationControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/IntegrationControllerTest.php
index bfa86a10728f6bd5dfb31eb129735faaa898fd22..ddf0d1d9dcac6be17e10aeb3cd54a062fd888c16 100644
--- a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/IntegrationControllerTest.php
+++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/IntegrationControllerTest.php
@@ -34,9 +34,13 @@ class Cosmo_IntegrationControllerTestActionTest extends CosmoControllerTestCase
 abstract class Cosmo_IntegrationControllerControlActionTestCase extends CosmoControllerTestCase {
 	public function setUp() {
 		parent::setUp();
-		Class_IntBib::beVolatile();
-		Class_Cosmogramme_Integration::beVolatile();
-		Class_IntProfilDonnees::beVolatile();
+    $this->fixture('Class_CosmoVar',
+                   ['id' => 'import_type_operation',
+                    'liste' => "0:Import incrémentiel\r\n1:Suppression d'exemplaires\r\n2:Import total\r\n3:Suppression fichier d'entête Pergame\r\n"]);
+
+    $this->fixture('Class_CosmoVar',
+                   ['id' => 'type_fichier',
+                    'liste' => "0:notices\r\n1:abonnés\r\n2:prêts\r\n3:reservations\r\n4:paniers\r\n"]);
 
 		$this->file_system = $this->mock();
 		Class_Cosmogramme_Integration::setFileSystem($this->file_system);
@@ -152,4 +156,401 @@ class Cosmo_IntegrationControllerControlActionWithBibTest extends Cosmo_Integrat
 	public function vendrediShouldBePresent() {
 		$this->assertXPathContentContains('//td', 'vendredi');
 	}
+}
+
+
+
+abstract class Cosmo_IntegrationControllerGenerateActionTestCase extends CosmoControllerTestCase {
+  public function setUp() {
+    parent::setUp();
+    $this->fixture('Class_CosmoVar',
+                   ['id' => 'ftp_path',
+                    'valeur' => '../ftp/transfert/']);
+
+    $subdir_calls = 0;
+    $subdir_provider = function() use (&$subdir_calls) {
+      $subdir_calls++;
+      $mapping = [1 => '.', 2 => '..', 3 => 'library1', 4 => 'test'];
+      return array_key_exists($subdir_calls, $mapping) ? $mapping[$subdir_calls] : false;
+    };
+
+    $file_system = $this->mock()
+                        ->whenCalled('file_exists')->with('../ftp/transfert/')
+                        ->answers(true)
+
+                        ->whenCalled('opendir')->with('../ftp/transfert/')
+                        ->answers(true)
+
+                        ->whenCalled('readdir')->with(true)
+                        ->willDo($subdir_provider)
+
+                        ->whenCalled('is_dir')->with('../ftp/transfert/library1')
+                        ->answers(true)
+
+                        ->whenCalled('is_readable')
+                        ->with('../ftp/transfert/library1/etalon')
+                        ->answers(true)
+
+                        ->whenCalled('is_readable')
+                        ->with('../ftp/transfert/library1/etalon/annexes.txt')
+                        ->answers(true)
+
+                        ->whenCalled('is_readable')
+                        ->with('../ftp/transfert/library1/etalon/genres.txt')
+                        ->answers(true)
+
+                        ->whenCalled('is_readable')
+                        ->with('../ftp/transfert/library1/etalon/sections.txt')
+                        ->answers(true)
+
+                        ->whenCalled('is_readable')
+                        ->with('../ftp/transfert/library1/etalon/emplacements.txt')
+                        ->answers(true)
+
+                        ->whenCalled('file')
+                        ->with('../ftp/transfert/library1/etalon/annexes.txt')
+                        ->answers(['BIB_SPS_UTT|ID_SITE|LIBELLE',
+                                   '20|library1',
+                                   '12|library2'])
+
+                        ->whenCalled('file')
+                        ->with('../ftp/transfert/library1/etalon/sections.txt')
+                        ->answers(['BIB_C_SECTION|CODE|LIBELLE',
+                                   '1|Adulte',
+                                   '2|Jeunesse'])
+
+                        ->whenCalled('file')
+                        ->with('../ftp/transfert/library1/etalon/emplacements.txt')
+                        ->answers(['BIB_C_EMPLACEMENT|CODE|LIBELLE',
+                                   '4|Coin des tout-petits',
+                                   '5|Livres CD',
+                                   '6|Bacs imagiers',
+                                   '7|Albums'])
+
+                        ->whenCalled('file')
+                        ->with('../ftp/transfert/library1/etalon/genres.txt')
+                        ->answers(['BIB_GENRES|SUPPORT|CODE|LIBELLE|DOC',
+                                   '0|1|Album|f',
+                                   '0|2|Bande dessinée|f',
+                                   '0|3|Biographie|f'])
+
+                        ->beStrict();
+
+    Class_Cosmogramme_LandingDirectory::setFileSystem($file_system);
+  }
+
+
+  public function tearDown() {
+    Class_Log::getInstance()->reset();
+    parent::tearDown();
+  }
+}
+
+
+
+class Cosmo_IntegrationControllerGenerateActionTest extends Cosmo_IntegrationControllerGenerateActionTestCase {
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('cosmo/integration/generate', true);
+  }
+
+
+  public function tearDown() {
+    Class_Cosmogramme_LandingDirectory::setFileSystem(null);
+    parent::tearDown();
+  }
+
+
+  /** @test */
+  public function titleShouldBeGenerationAutomatique() {
+    $this->assertXPathContentContains('//h1', 'Génération automatique');
+  }
+
+
+  /** @test */
+  public function library1ShouldBeSelectable() {
+    $this->assertXPath('//select[@name="path_ftp"]//option[@value="library1"]');
+  }
+
+
+  /** @test */
+  public function testShouldNotBeSelectable() {
+    $this->assertNotXPath('//select[@name="path_ftp"]//option[@value="test"]');
+  }
+
+
+  /** @test */
+  public function parentShouldNotBeSelectable() {
+    $this->assertNotXPath('//select[@name="path_ftp"]//option[@value=".."]');
+  }
+
+
+  /** @test */
+  public function sigbNanookShouldBeSelectable() {
+    $this->assertXPath('//select[@name="type_sigb"]//option[@value="13"]');
+  }
+
+
+  /** @test */
+  public function shouldBeAbleToChooseBranchCreationMode() {
+    $this->assertXPath('//select[@name="creer_annexes"]');
+  }
+
+
+  /** @test */
+  public function shouldBeAbleToEtalonSynchMode() {
+    $this->assertXPath('//select[@name="synchro"]');
+  }
+}
+
+
+
+class Cosmo_IntegrationControllerGenerateActionNanookPostTest
+  extends Cosmo_IntegrationControllerGenerateActionTestCase {
+
+  public function setUp() {
+    parent::setUp();
+
+    $this->fixture('Class_IntProfilDonnees',
+                   ['id' => 104,
+                    'libelle' => 'Unimarc Nanook',
+                    'type_fichier' => 0]);
+
+    $this->fixture('Class_IntProfilDonnees',
+                   ['id' => 105,
+                    'libelle' => 'Abonné Nanook',
+                    'type_fichier' => 1]);
+
+    $time_source = $this->mock()->whenCalled('time')->answers(strtotime('2016-01-28'));
+    Class_Cosmogramme_Generator::setTimeSource($time_source);
+    Class_Cosmogramme_Generator_AbstractTask::setTimeSource($time_source);
+
+    $this->postDispatch('cosmo/integration/generate',
+                        ['path_ftp' => 'library1',
+                         'type_sigb' => 13,
+                         'service_nanook' => 'http://nanook-ws.net/ilsdi/',
+                         'creer_annexes' => 1,
+                         'synchro' => 1]);
+  }
+
+
+  public function tearDown() {
+    Class_Cosmogramme_Generator::setTimeSource(null);
+    Class_Cosmogramme_Generator_AbstractTask::setTimeSource(null);
+    parent::tearDown();
+  }
+
+
+  /** @test */
+  public function shouldNotContainsForm() {
+    $this->assertNotXPath('//form');
+  }
+
+
+  /** @test */
+  public function shouldNotHaveError() {
+    $this->assertNotXPath('//font[@color="red"]', $this->_response->getBody());
+  }
+
+
+  /** @test */
+  public function shouldLogLibraryCreation() {
+    $this->assertXPathContentContains('//h3', '1 - Création des bibliothèques', $this->_response->getBody());
+  }
+
+
+  /** @test */
+  public function shouldHaveCreated2Libraries() {
+    $this->assertEquals(2, Class_Bib::count());
+  }
+
+
+  /** @test */
+  public function library1ShouldBeCreated() {
+    $this->assertNotNull(Class_Bib::findFirstBy(['id_site' => 20,
+                                                 'libelle' => 'library1',
+                                                 'ville' => 'library1',
+                                                 'id_zone' => 1,
+                                                 'visibilite' => Class_Bib::V_DATA]),
+                         $this->_response->getBody());
+  }
+
+
+  /** @test */
+  public function library1IntegrationShouldBeCreated() {
+    $this->assertNotNull($bib = Class_IntBib::findFirstBy(['id_bib' => 20,
+                                                           'nom' => 'library1',
+                                                           'nom_court' => 'library1',
+                                                           'qualite' => 5,
+                                                           'sigb' => Class_IntBib::SIGB_NANOOK,
+                                                           'planif_mode' => 'r',
+                                                           'planif_jours' => '1111111',
+                                                           'comm_sigb' => Class_IntBib::COM_NANOOK]),
+                         $this->_response->getBody());
+    return $bib;
+  }
+
+
+  /**
+   * @test
+   * @depends library1IntegrationShouldBeCreated
+   */
+  public function library1IntegrationCommParamsShouldContainsNanookWebservice($bib) {
+    $this->assertContains('http://nanook-ws.net/ilsdi/', $bib->getCommParams());
+  }
+
+
+  /** @test */
+  public function library1BranchShouldBeCreated() {
+    $this->assertNotNull(Class_CodifAnnexe::findFirstBy(['id_bib' => 20,
+                                                         'code' => 20,
+                                                         'libelle' => 'library1',
+                                                         'invisible' => 0]),
+                         $this->_response->getBody());
+  }
+
+
+  /** @test */
+  public function barCodeProfileShouldBeCreated() {
+    $this->assertNotNull($profile = Class_IntProfilDonnees::findFirstBy(['libelle' => 'Liste de codes-barres']));
+    return $profile;
+  }
+
+
+  /**
+   * @test
+   * @depends barCodeProfileShouldBeCreated
+   */
+  public function library1ShouldHeveItemDeletionPlanned($profile) {
+    $this->assertNotNull(Class_IntMajAuto::findFirstBy(['id_bib' => 20,
+                                                        'rang' => 2001,
+                                                        'profil' => $profile->getId(),
+                                                        'type_operation' => Class_IntMajAuto::OP_ITEMS_DELETION,
+                                                        'nom_fichier' => 'library1/site20/suppressions.txt']));
+  }
+
+
+  /** @test */
+  public function library1ShouldHaveRecordsTotalPlanned() {
+    $this->assertNotNull(Class_IntMajAuto::findFirstBy(['id_bib' => 20,
+                                                        'profil' => 104,
+                                                        'type_operation' => Class_IntMajAuto::OP_FULL_IMPORT,
+                                                        'nom_fichier' => 'library1/site20/notices_total.txt']));
+  }
+
+
+  /** @test */
+  public function library1ShouldHaveRecordsPartialPlanned() {
+    $this->assertNotNull(Class_IntMajAuto::findFirstBy(['id_bib' => 20,
+                                                        'profil' => 104,
+                                                        'type_operation' => Class_IntMajAuto::OP_PARTIAL_IMPORT,
+                                                        'nom_fichier' => 'library1/site20/notices.txt']));
+  }
+
+
+  /** @test */
+  public function library1ShouldHaveUsersPlanned() {
+    $this->assertNotNull(Class_IntMajAuto::findFirstBy(['id_bib' => 20,
+                                                        'profil' => 105,
+                                                        'type_operation' => Class_IntMajAuto::OP_FULL_IMPORT,
+                                                        'nom_fichier' => 'library1/site20/abonnes.txt']));
+  }
+
+
+  /** @test */
+  public function library1ShouldHaveLoansPlanned() {
+    $this->assertNotNull(Class_IntMajAuto::findFirstBy(['id_bib' => 20,
+                                                        'profil' => 102,
+                                                        'type_operation' => Class_IntMajAuto::OP_FULL_IMPORT,
+                                                        'nom_fichier' => 'library1/site20/prets.txt']));
+  }
+
+
+  /** @test */
+  public function library1ShouldNotHaveHoldsPlanned() {
+    $this->assertNull(Class_IntMajAuto::findFirstBy(['id_bib' => 20,
+                                                     'profil' => 103,
+                                                     'type_operation' => Class_IntMajAuto::OP_FULL_IMPORT,
+                                                     'nom_fichier' => 'library1/site20/reservations.txt']));
+  }
+
+
+  /** @test */
+  public function basketsProfileShouldBeCreated() {
+    $profile = Class_IntProfilDonnees::findFirstBy(['accents' => Class_IntProfilDonnees::ENCODING_UTF8,
+                                                    'type_fichier' => Class_IntProfilDonnees::FT_BASKETS,
+                                                    'format' => Class_IntProfilDonnees::FORMAT_PIPED_ASCII]);
+    $this->assertNotNull($profile);
+    return $profile;
+  }
+
+
+
+  /**
+   * @test
+   * @depends basketsProfileShouldBeCreated
+   */
+  public function library1ShouldHaveBasketsFullPlanned($profile) {
+    $this->assertNotNull(Class_IntMajAuto::findFirstBy(['id_bib' => 20,
+                                                        'profil' => $profile->getId(),
+                                                        'type_operation' => Class_IntMajAuto::OP_FULL_IMPORT,
+                                                        'nom_fichier' => 'library1/site20/paniers_total.txt']));
+  }
+
+
+  /**
+   * @test
+   * @depends basketsProfileShouldBeCreated
+   */
+  public function library1ShouldHaveBasketsPartialPlanned($profile) {
+    $this->assertNotNull(Class_IntMajAuto::findFirstBy(['id_bib' => 20,
+                                                        'profil' => $profile->getId(),
+                                                        'type_operation' => Class_IntMajAuto::OP_PARTIAL_IMPORT,
+                                                        'nom_fichier' => 'library1/site20/paniers.txt']));
+  }
+
+
+  /** @test */
+  public function adulteSectionShouldBeCreated() {
+    $this->assertNotNull(Class_CodifSection::findFirstBy(['libelle' => 'Adulte',
+                                                          'regles' => '995$9=1']));
+  }
+
+
+  /** @test */
+  public function coinLocationShouldBeCreated() {
+    $this->assertNotNull(Class_CodifEmplacement::findFirstBy(['libelle' => 'Coin des tout-petits',
+                                                              'regles' => '995$6=4']));
+  }
+
+
+  /** @test */
+  public function bdKindShouldBeCReated() {
+    $this->assertNotNull(Class_CodifGenre::findFirstBy(['libelle' => 'Biographie',
+                                                        'regles' => '995$7=3']));
+  }
+
+
+  /** @test */
+  public function shouldHaveCreated10Deweys() {
+    $this->assertEquals(10, Class_CodifDewey::count());
+  }
+
+
+  /** @test */
+  public function generaliteDeweyShouldHaveId0() {
+    $this->assertNotNull(Class_CodifDewey::findFirstBy(['id_dewey' => 0, 'libelle' => 'Généralités']));
+  }
+
+
+  /** @test */
+  public function histoireDeweyShouldHaveId9() {
+    $this->assertNotNull(Class_CodifDewey::findFirstBy(['id_dewey' => 9, 'libelle' => 'Histoire, géographie']));
+  }
+
+
+  /** @test */
+  public function shouldSayFinished() {
+    $this->assertXPathContentContains('//h2', 'Traitement terminé');
+  }
 }
\ No newline at end of file
diff --git a/cosmogramme/cosmozend/tests/bootstrap.php b/cosmogramme/cosmozend/tests/bootstrap.php
index 6151b95fc7fbb1adabe552877752ace5983a74f6..42ef07542e9f48174da7e7f14b4d5a6684b3e006 100644
--- a/cosmogramme/cosmozend/tests/bootstrap.php
+++ b/cosmogramme/cosmozend/tests/bootstrap.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
  */
 
 $cosmozendPath = realpath(dirname(__FILE__)) . '/../';
@@ -44,5 +44,4 @@ $_SERVER['SERVER_NAME'] = 'localhost';
 $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
 
 require_once 'CosmoControllerTestCase.php';
-
 ?>
\ No newline at end of file
diff --git a/cosmogramme/cosmozend/tests/bootstrap_frontcontroller.php b/cosmogramme/cosmozend/tests/bootstrap_frontcontroller.php
index 9117b75da9b8f0840e22107215dae58bcb78c7cf..4284852ad259fc36218f264c7c705f53eb0b9991 100644
--- a/cosmogramme/cosmozend/tests/bootstrap_frontcontroller.php
+++ b/cosmogramme/cosmozend/tests/bootstrap_frontcontroller.php
@@ -16,9 +16,13 @@
  *
  * 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
  */
 
+Zend_Controller_Action_HelperBroker::resetHelpers();
+Zend_Controller_Action_HelperBroker::addHelper(new ZendAfi_Controller_Action_Helper_Cosmo_ViewRenderer());
+Zend_Controller_Action_HelperBroker::addPrefix('ZendAfi_Controller_Action_Helper_Cosmo');
+
 Zend_Layout::startMvc();
 Zend_Layout::getMvcInstance()->getView()
 ->addHelperPath('ZendAfi/View/Helper', 'ZendAfi_View_Helper');
diff --git a/cosmogramme/php/_menu.php b/cosmogramme/php/_menu.php
index 346fa582655c085848e3aefdf0d96c241221ee4d..0b27b1435522a3b4c563b5742ec8b847861d76a8 100644
--- a/cosmogramme/php/_menu.php
+++ b/cosmogramme/php/_menu.php
@@ -92,7 +92,7 @@ else
 	<div class="menu_section">Configurations</div>
 	<?php
 	ligneMenu("Variables","config_variables.php");
-	ligneMenu("Démarrer un nouvel OPAC","integre_generation_pergame.php");
+	ligneMenu("Démarrer un nouvel OPAC","../cosmozend/cosmo/integration/generate");
 	ligneMenu("Annexes","codif_annexe.php");
 	ligneMenu("Profils de données","config_profil_donnees.php");
 	ligneMenu("Intégrations programmées","config_integrations.php");
diff --git a/cosmogramme/php/integration/integration_phase.php b/cosmogramme/php/integration/integration_phase.php
index 3927cb0326103cdd5cab7b38eb43ce29f86ef810..db3877a85afa0eb20ff6f2eda89e83cbb5970fcc 100644
--- a/cosmogramme/php/integration/integration_phase.php
+++ b/cosmogramme/php/integration/integration_phase.php
@@ -46,9 +46,7 @@ function startIntegrationPhase($name) {
 	$current_chrono->backToLegacyState($chrono, $chrono_fichier, $chrono100notices);
 	$new_phase->backToLegacyState($phase, $phase_data, $mode_cron, $reprise, $compteur);
 
-
 	if (!$mode_cron && $requested_phase->isTimeOut())
 		sauveContexte();
 }
-
 ?>
\ No newline at end of file
diff --git a/library/Class/AdminVar.php b/library/Class/AdminVar.php
index 63e15b4a6070948e6e06cce39fa807f9098ed622..c836f90a21276d0867c2b84df2afd9e16ffff218 100644
--- a/library/Class/AdminVar.php
+++ b/library/Class/AdminVar.php
@@ -255,6 +255,10 @@ class Class_AdminVarLoader extends Storm_Model_Loader {
                    'MYCOW_EID' => Class_AdminVar_Meta::newDefault($this->_('Clé d\'identification MyCOW.EU pour le portail. Cette clé doit être fournie par MyCOW.EU. Elle active la ressource numérique dans le portail.'))->bePrivate(),
 
                    'ONEDTOUCH_URL' => Class_AdminVar_Meta::newDefault($this->_('Adresse du serveur OAI 1D touch'))->bePrivate(),
+                   'ONEDTOUCH_VERSION_URL' => Class_AdminVar_Meta::newCombo( $this->_('Type de SSO OneDTouch'),
+                                                                            ['options' => ['selectOptions' => ['label' => $this->_('Version'),
+                                                                                                               'multioptions' => (new Class_OneDTouchLink())->getVersionOptions()]]])->bePrivate(),
+
                    'ONEDTOUCH_ID' => Class_AdminVar_Meta::newDefault($this->_('Identifiant du portail chez 1D touch'))->bePrivate(),
 
                    'ORPHEA_URL' => Class_AdminVar_Meta::newDefault($this->_('Adresse du serveur Orphea'))->bePrivate(),
diff --git a/library/Class/AvisNotice.php b/library/Class/AvisNotice.php
index b4bb16054e3848be1c1908d86153d095362c0498..2c4de8af80267abd9d0f9d01d934965a18933300 100644
--- a/library/Class/AvisNotice.php
+++ b/library/Class/AvisNotice.php
@@ -47,8 +47,7 @@ class AvisNoticeLoader extends Storm_Model_Loader {
   public function findOrphanReviews($status, $limitPage) {
     return self::findReviews($status,
                              $limitPage,
-                             Class_AvisNotice::ORPHAN_FLAG,
-                             null);
+                             Class_AvisNotice::ORPHAN_FLAG);
   }
 
 
@@ -71,17 +70,20 @@ class AvisNoticeLoader extends Storm_Model_Loader {
   public function findArchivedReviews($status,$limitPage) {
     return self::findReviews($status,
                              $limitPage,
-                             Class_AvisNotice::ARCHIVED_FLAG,
-                             null);
+                             Class_AvisNotice::ARCHIVED_FLAG);
   }
 
 
-  protected function findReviews($status, $limit_page, $flag, $avis) {
-    return Class_AvisNotice::findAllBy(['flags' => $flag,
-                                        'abon_ou_bib' => $avis,
-                                        'order' => 'date_avis desc',
-                                        'statut' => $status,
-                                        'limitPage' => $limit_page]);
+  protected function findReviews($status, $limit_page, $flag, $avis = null) {
+    $params = ['flags' => $flag,
+                 'order' => 'date_avis desc',
+                 'statut' => $status,
+                 'limitPage' => $limit_page];
+
+    if ($avis !== null)
+      $params['abon_ou_bib'] = $avis;
+
+    return Class_AvisNotice::findAllBy($params);
   }
 
 
@@ -101,22 +103,24 @@ class AvisNoticeLoader extends Storm_Model_Loader {
 
   public function countOrphanReviews($status) {
     return self::countReviews($status,
-                              Class_AvisNotice::ORPHAN_FLAG,
-                              null);
+                              Class_AvisNotice::ORPHAN_FLAG);
   }
 
 
   public function countArchivedReviews($status) {
     return self::countReviews($status,
-                              Class_AvisNotice::ARCHIVED_FLAG,
-                              null);
+                              Class_AvisNotice::ARCHIVED_FLAG);
   }
 
 
-  protected function countReviews($status, $flag, $avis) {
-    return Class_AvisNotice::countBy(['statut' => $status,
-                                      'flags' => $flag,
-                                      'abon_ou_bib' => $avis]);
+  protected function countReviews($status, $flag, $avis = null) {
+    $params = ['flags' => $flag,
+                 'statut' => $status];
+
+    if ($avis !== null)
+      $params['abon_ou_bib'] = $avis;
+
+    return Class_AvisNotice::countBy($params);
   }
 
 
@@ -157,7 +161,7 @@ class AvisNoticeLoader extends Storm_Model_Loader {
       $params['flags'] = Class_AvisNotice::NO_FLAG;
     $preferences = array_merge(['id_panier' => 0,
                                 'id_catalogue' => 0,
-                                'abon_ou_bib' => 'all',
+                                'abon_ou_bib' => 'all'
                                 ],
                                $preferences);
 
@@ -171,8 +175,12 @@ class AvisNoticeLoader extends Storm_Model_Loader {
 
     $this->_addStatutAbonBibWhereClause($abon_ou_bib, $params);
 
-    if ($limit_page)
-      $params['limitPage'] = $limit_page;
+    if (!isset($preferences['nb_aff_avis']))
+      $preferences['nb_aff_avis'] = 10;
+
+    $params['limitPage'] = $limit_page
+      ? $limit_page
+      : [1, $preferences['nb_aff_avis'] * 3];
 
     return Class_AvisNotice::findAllBy($params);
   }
diff --git a/library/Class/Bib.php b/library/Class/Bib.php
index c35074e704efaede680ac6a5c65125569b9501bd..e65bc1dda40b7d5ad4a19e7b2af5686e7fc38c97 100644
--- a/library/Class/Bib.php
+++ b/library/Class/Bib.php
@@ -245,6 +245,7 @@ class Class_Bib extends Storm_Model_Abstract {
                                           'closed_on_holidays' => true];
 
   protected $_translate;
+  protected $_fixed_id = true;
 
   public function __construct() {
     parent::__construct();
diff --git a/library/Class/CodifDewey.php b/library/Class/CodifDewey.php
index 7c87cc69a31a7f47bac8bff19ff65b9ac9e7f922..c0e345541ff2d055ba8beba2442c398eda2fb14f 100644
--- a/library/Class/CodifDewey.php
+++ b/library/Class/CodifDewey.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
  */
 
 class Class_CodifDeweyLoader extends Storm_Model_Loader {
@@ -38,6 +38,7 @@ class Class_CodifDewey extends Storm_Model_Abstract {
   protected $_table_name = 'codif_dewey';
   protected $_table_primary = 'id_dewey';
   protected $_loader_class = 'Class_CodifDeweyLoader';
+  protected $_fixed_id = true;
 
 // ----------------------------------------------------------------
 // Rend une liste pour un champ suggestion
@@ -46,24 +47,24 @@ class Class_CodifDewey extends Storm_Model_Abstract {
     // Lancer la recherche
     $new = '';
     if($mode=="1") {
-      for($i=0; $i < strlen($recherche); $i++) 
+      for($i=0; $i < strlen($recherche); $i++)
         if($recherche[$i] >="0" and $recherche[$i] <= "9") $new.=$recherche[$i];
       $req="select id_dewey,libelle from codif_dewey where id_dewey like'".$new."%' order by id_dewey limit ".$limite_resultat;
     }
     if($mode=="2") $req="select id_dewey,libelle from codif_dewey where libelle like'".addslashes($recherche)."%' order by id_dewey limit ".$limite_resultat;
     if($mode=="3") $req="select id_dewey,libelle from codif_dewey where libelle like'%".addslashes($recherche)."%' order by id_dewey limit ".$limite_resultat;
-  
+
     $resultat=fetchAll($req);
-    
+
     // Mettre l'indice et le libelle
     if(!$resultat) return false;
     foreach($resultat as $enreg)
     {
       $liste[]=array($enreg["id_dewey"], $this->formatIndice($enreg["id_dewey"])." : ".$enreg["libelle"]);
     }
-    
+
     return $liste;
-  } 
+  }
 
 // ----------------------------------------------------------------
 // Rend une liste d'indices par niveau
@@ -71,7 +72,7 @@ class Class_CodifDewey extends Storm_Model_Abstract {
   static function getIndices($pere)
   {
     $sql = Zend_Registry::get('sql');
-    if($pere == "root") 
+    if($pere == "root")
       $liste=$sql->fetchAll("select * from codif_dewey where LENGTH(id_dewey)=1 order by id_dewey");
     else {
       $long=strlen($pere)+1;
@@ -80,7 +81,7 @@ class Class_CodifDewey extends Storm_Model_Abstract {
     }
     return $liste;
   }
-  
+
 // ----------------------------------------------------------------
 // Ponctue un indice dewey
 // ----------------------------------------------------------------
diff --git a/library/Class/Cosmogramme/Generator.php b/library/Class/Cosmogramme/Generator.php
new file mode 100644
index 0000000000000000000000000000000000000000..65444446c19cb7c9eb810e2287bcfdd554e20086
--- /dev/null
+++ b/library/Class/Cosmogramme/Generator.php
@@ -0,0 +1,506 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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_Cosmogramme_Generator {
+  use Trait_Translator, Trait_Loggable, Trait_TimeSource;
+
+  protected $_params = [], $_landing_directory;
+
+
+  public function generate($params) {
+    $this->_params = $params;
+    $this->_landing_directory = Class_Cosmogramme_LandingDirectory::getInstance();
+
+    if (!$this->isValid())
+      return false;
+
+    $result = $this->_generateLibraries()
+      && $this->_generateSections()
+      && $this->_generateLocations()
+      && $this->_generateKinds()
+      && $this->_generateDewey();
+
+    $this->log('<br><h2>'. $this->_('Traitement terminé.') .'</h2>');
+
+    return $result;
+  }
+
+
+  protected function isValid() {
+    return $this->validateDirectory() && $this->validateProfiles();
+  }
+
+
+  protected function validateDirectory() {
+    return $this->_landing_directory->couldGenerateFrom($this->_params['path_ftp']);
+  }
+
+
+  protected function validateProfiles() {
+    return ($validator = $this->getProfilesValidator())
+      ? $validator->isValid() : true;
+  }
+
+
+  protected function getProfilesValidator() {
+    if (Class_IntBib::SIGB_NANOOK == $this->_params['type_sigb'])
+      return new Class_Cosmogramme_GeneratorProfilesNanookValidator();
+
+    if (Class_IntBib::SIGB_PERGAME == $this->_params['type_sigb'])
+      return new Class_Cosmogramme_GeneratorProfilesPergameValidator();
+
+    return null;
+  }
+
+
+  protected function _generateLibraries() {
+    if (!$libraries = $this->_landing_directory->getLibrariesOf($this->_params['path_ftp'])) {
+      $this->log($this->_('Étalon des bibliothèques vide'));
+      return false;
+    }
+
+    $this->_generateLibrariesEntities($libraries);
+    $this->_generateLibrariesBranches($libraries);
+    $this->_generatePlannedIntegrations($libraries);
+
+    return true;
+  }
+
+
+  protected function _generateLibrariesEntities($libraries) {
+    $this->logTitle($this->_('1 - Création des bibliothèques'));
+
+    $html = '';
+    foreach ($libraries as $data)
+      $html .= $this->_generateLibrary($data);
+
+    $this->log('<div class="liste"><table class="blank">' . $html . '</table></div>');
+  }
+
+
+  protected function _generateLibrary($data) {
+    if (!$elem = $this->_extractLibraryData($data))
+      return '';
+
+    if (!$bib = Class_Bib::findFirstBy(['id_site' => $elem[0]]))
+      $bib = new Class_Bib();
+
+    $bib->updateAttributes(['id_site' => $elem[0],
+                            'libelle' => trim($elem[1]),
+                            'ville' => $this->_params['path_ftp'],
+                            'id_zone' => 1,
+                            'visibilite' => Class_Bib::V_DATA])
+        ->save();
+
+    Class_IntBib::deleteBy(['id_bib' => $bib->getIdSite()]);
+    $int_bib = Class_IntBib::newInstance(['id_bib' => $bib->getIdSite(),
+                                          'nom' => $bib->getLibelle(),
+                                          'nom_court' => $bib->getLibelle(),
+                                          'qualite' => 5,
+                                          'sigb' => $this->_params['type_sigb'],
+                                          'planif_mode' => 'r',
+                                          'planif_jours' => '1111111',
+                                          'comm_sigb' => Class_IntBib::COM_PERGAME,
+                                          'comm_params' => serialize(['Autoriser_docs_disponibles' => '0',
+                                                                      'Max_par_carte' => '3',
+                                                                      'Max_par_document' => '3'])]);
+
+    if (Class_IntBib::SIGB_NANOOK == $this->_params['type_sigb'])
+      $int_bib
+        ->setCommSigb(Class_IntBib::COM_NANOOK)
+        ->setCommParams(serialize(['url_serveur' => $this->_params['service_nanook']]));
+
+		$int_bib->save();
+
+    return '<tr><td class="blank">Site n° '. $bib->getIdSite() . '</td><td class="blank">'. $bib->getLibelle() . '</td></tr>';
+  }
+
+
+  protected function _generateLibrariesBranches($libraries) {
+    $this->logTitle($this->_('2 - Création des annexes'));
+    if ('1' != $this->_params['creer_annexes']) {
+      $this->log($this->_('Non demandée'));
+      return;
+    }
+
+    $deleted = Class_CodifAnnexe::deleteBy([]);
+    $html = '<tr><td class="blank" colspan="2">' . $this->_('%d annexe(s) supprimée(s)', $deleted) . '</td></tr>';
+    foreach ($libraries as $data)
+      $html .= $this->_generateBranch($data);
+    $this->log('<div class="liste"><table class="blank">' . $html . '</table></div>');
+  }
+
+
+  protected function _generateBranch($data) {
+    if (!$elem = $this->_extractLibraryData($data))
+      return '';
+
+    $branch = Class_CodifAnnexe::newInstance(['id_bib' => $elem[0],
+                                              'code' => $elem[0],
+                                              'libelle' => trim($elem[1]),
+                                              'invisible' => 0]);
+    $branch->save();
+
+    return '<tr><td class="blank">Site n° '. $branch->getIdBib() .'</td><td class="blank">'. $branch->getLibelle() . '</td></tr>';
+  }
+
+
+  protected function _generatePlannedIntegrations($libraries) {
+    $this->logTitle($this->_('3 - Programmation des intégrations'));
+
+    $html = '';
+    foreach ($libraries as $data)
+      $html .= $this->_generatePlannedIntegration($data);
+
+    $this->log('<div class="liste"><table class="blank">' . $html . '</table></div>');
+  }
+
+
+  protected function _generatePlannedIntegration($data) {
+    if (!$elem = $this->_extractLibraryData($data))
+      return '';
+
+    $id_bib = $elem[0];
+    Class_IntMajAuto::deleteBy(['id_bib' => $id_bib]);
+    $lib_label = trim($elem[1]);
+    return $this->getPlannedGenerator()->plan($id_bib, $lib_label);
+  }
+
+
+  protected function getPlannedGenerator() {
+    return (Class_IntBib::SIGB_NANOOK == $this->_params['type_sigb'])
+      ? new Class_Cosmogramme_GeneratorPlannedNanook()
+      : new Class_Cosmogramme_GeneratorPlannedPergame();
+  }
+
+
+  protected function _generateSections() {
+    $sections = $this->_landing_directory->getSectionsOf($this->_params['path_ftp']);
+    return (new Class_Cosmogramme_Generator_SectionsTask($this))->run($sections);
+  }
+
+
+  protected function _generateLocations() {
+    $locations = $this->_landing_directory->getLocationsOf($this->_params['path_ftp']);
+    return (new Class_Cosmogramme_Generator_LocationsTask($this))->run($locations);
+  }
+
+
+  protected function _generateKinds() {
+    $kinds = $this->_landing_directory->getKindsOf($this->_params['path_ftp']);
+    return (new Class_Cosmogramme_Generator_KindsTask($this))->run($kinds);
+  }
+
+
+  protected function _generateDewey() {
+    $this->logTitle($this->_('7 - Création des classes Dewey'));
+
+    Class_CodifDewey::deleteBy(['id_dewey' => range(0, 9)]);
+
+    $map = ['Généralités',
+            'Philosophie et disciplines connexes',
+            'Religion',
+            'Sciences sociales',
+            'Langues',
+            'Sciences de la nature et mathématiques',
+            'Technique (sciences appliquées)',
+            'Arts',
+            'Littérature (Belles-lettres)',
+            'Histoire, géographie'];
+
+    $html = '';
+    foreach($map as $k => $v) {
+      Class_CodifDewey::newInstance(['id_dewey' => $k, 'libelle' => $v])
+        ->save();
+      $html .= '<tr><td class="blank">'. $k .'</td><td class="blank">'. $v . '</td></tr>';
+    }
+
+    $this->log('<div class="liste"><table class="blank">' . $html . '</table></div>');
+
+    return true;
+  }
+
+
+  public function isPergame() {
+    return Class_IntBib::SIGB_PERGAME == $this->_params['type_sigb'];
+  }
+
+
+  public function isNanook() {
+    return Class_IntBib::SIGB_NANOOK == $this->_params['type_sigb'];
+  }
+
+
+  protected function logTitle($title) {
+    $this->log('<h3>' . $title . '</h3>');
+  }
+
+
+  protected function _extractLibraryData($data) {
+    $data = utf8_encode($data);
+		$elem = explode('|', $data);
+
+		return ($elem[0] == 'BIB_SPS_UTT') ? [] : $elem;
+  }
+}
+
+
+
+class Class_Cosmogramme_GeneratorProfilesAbstractValidator {
+  use Trait_Translator, Trait_Loggable;
+
+  public function isValid() {
+    if (!$definitions = $this->_getDefinitions())
+      return false;
+
+    foreach($this->_getDefinitions() as $parts)
+      if (!$this->_ensureProfile($parts[1], $parts[0], $parts[2]))
+        return false;
+
+    return true;
+  }
+
+
+  protected function _ensureProfile($label, $id, $type) {
+    if (!Class_IntProfilDonnees::findFirstBy(['id_profil' => $id, 'type_fichier' => $type])) {
+      $this->log($this->_('Profil de données %s (%d) non présent ou mal configuré', $label, $id));
+      return false;
+    }
+
+    return true;
+  }
+
+
+  protected function _getDefinitions() {
+    return [];
+  }
+}
+
+
+
+class Class_Cosmogramme_GeneratorProfilesNanookValidator
+  extends Class_Cosmogramme_GeneratorProfilesAbstractValidator {
+
+  protected function _getDefinitions() {
+    return[[104, 'Unimarc Nanook', Class_IntProfilDonnees::FT_RECORDS],
+           [105, 'Abonné Nanook', Class_IntProfilDonnees::FT_PATRONS]];
+  }
+}
+
+
+
+class Class_Cosmogramme_GeneratorProfilesPergameValidator
+  extends Class_Cosmogramme_GeneratorProfilesAbstractValidator {
+
+  protected function _getDefinitions() {
+    return[[100, 'Unimarc Pergame', Class_IntProfilDonnees::FT_RECORDS],
+           [101, 'Abonné Pergame', Class_IntProfilDonnees::FT_PATRONS],
+           [102, 'Prêts Pergame', Class_IntProfilDonnees::FT_LOANS],
+           [103, 'Réservations Pergame', Class_IntProfilDonnees::FT_HOLDS]];
+  }
+}
+
+
+
+class Class_Cosmogramme_GeneratorPlannedAbstract {
+  use Trait_Translator, Trait_Loggable;
+
+  protected
+    $_id_bib,
+    $_id_prog,
+    $_base_path,
+    $_html = '',
+    $_records_profile,
+    $_users_profile,
+    $_loans_profile = 102,
+    $_holds_profile = 103,
+    $_item_delete = false,
+    $_holds = false,
+    $_baskets = false;
+
+  public function plan($id_bib, $base_path) {
+    $this->_id_bib = $id_bib;
+    $this->_id_prog = $id_bib * 100;
+    $this->_base_path = $base_path . DIRECTORY_SEPARATOR . 'site' . $id_bib . DIRECTORY_SEPARATOR;
+
+    $this
+      ->itemDeletion()
+      ->recordsTotal()
+      ->recordsPartial()
+      ->users()
+      ->loans()
+      ->holds()
+      ->basketsTotal()
+      ->basketsPartial();
+
+    return $this->_html;
+  }
+
+
+  protected function itemDeletion() {
+    if (!$this->_item_delete)
+      return $this;
+
+    $profile = $this->_getBarCodeProfile();
+
+    return $this->planWith('Notices - suppression d\'exemplaires',
+                           $profile->getId(),
+                           Class_IntMajAuto::OP_ITEMS_DELETION,
+                           'suppressions.txt');
+  }
+
+
+  protected function recordsTotal() {
+    return $this->planWith('Notices - import total',
+                           $this->_records_profile,
+                           Class_IntMajAuto::OP_FULL_IMPORT,
+                           'notices_total.txt');
+  }
+
+
+  protected function recordsPartial() {
+    return $this->planWith('Notices - import incrémentiel',
+                           $this->_records_profile,
+                           Class_IntMajAuto::OP_PARTIAL_IMPORT,
+                           'notices.txt');
+  }
+
+
+  protected function users() {
+    return $this->planWith('Abonnés',
+                           $this->_users_profile,
+                           Class_IntMajAuto::OP_FULL_IMPORT,
+                           'abonnes.txt');
+  }
+
+
+  protected function loans() {
+    return $this->planWith('Prêts',
+                           $this->_loans_profile,
+                           Class_IntMajAuto::OP_FULL_IMPORT,
+                           'prets.txt');
+  }
+
+
+  protected function holds() {
+    return $this->_holds
+      ? $this->planWith('Réservations', $this->_holds_profile,
+                        Class_IntMajAuto::OP_FULL_IMPORT, 'reservations.txt')
+      : $this;
+  }
+
+
+  protected function basketsTotal() {
+    if (!$this->_baskets)
+      return $this;
+
+    $profile = $this->_getBasketProfile();
+
+    return $this->planWith('Paniers - import total',
+                           $profile->getId(),
+                           Class_IntMajAuto::OP_FULL_IMPORT,
+                           'paniers_total.txt');
+  }
+
+
+  protected function basketsPartial() {
+    if (!$this->_baskets)
+      return $this;
+
+    $profile = $this->_getBasketProfile();
+
+    return $this->planWith('Paniers - import incrémentiel',
+                           $profile->getId(),
+                           Class_IntMajAuto::OP_PARTIAL_IMPORT,
+                           'paniers.txt');
+  }
+
+
+  protected function planWith($name, $profile, $type, $file) {
+    $this->_html .= '<tr><td class="blank">Site n° '. $this->_id_bib . '</td><td class="blank">' . $name . '</td></tr>';
+    $this->_id_prog++;
+    Class_IntMajAuto::newInstance(['id_bib' => $this->_id_bib,
+                                   'libelle' => $name,
+                                   'profil' => $profile,
+                                   'type_operation' => $type,
+                                   'nom_fichier' => $this->_base_path . $file,
+                                   'rang' => $this->_id_prog])
+      ->save();
+
+    return $this;
+  }
+
+
+  protected function _getBarCodeProfile() {
+    $label = 'Liste de codes-barres';
+    if ($profile = Class_IntProfilDonnees::findFirstBy(['libelle' => $label]))
+      return $profile;
+
+
+    $attributs = 'a:6:{i:0;a:7:{s:8:"type_doc";a:11:{i:0;a:3:{s:4:"code";s:1:"0";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:1;a:3:{s:4:"code";s:1:"1";s:5:"label";s:5:"am;na";s:8:"zone_995";s:0:"";}i:2;a:3:{s:4:"code";s:1:"2";s:5:"label";s:2:"as";s:8:"zone_995";s:0:"";}i:3;a:3:{s:4:"code";s:1:"3";s:5:"label";s:3:"i;j";s:8:"zone_995";s:0:"";}i:4;a:3:{s:4:"code";s:1:"4";s:5:"label";s:1:"g";s:8:"zone_995";s:0:"";}i:5;a:3:{s:4:"code";s:1:"5";s:5:"label";s:3:"l;m";s:8:"zone_995";s:0:"";}i:6;a:3:{s:4:"code";s:1:"8";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:7;a:3:{s:4:"code";s:1:"9";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:8;a:3:{s:4:"code";s:2:"10";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:9;a:3:{s:4:"code";s:3:"100";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:10;a:3:{s:4:"code";s:2:"10";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}}s:17:"champ_code_barres";s:1:"f";s:10:"champ_cote";s:1:"k";s:11:"champ_genre";s:0:"";s:13:"champ_section";s:1:"q";s:17:"champ_emplacement";s:1:"u";s:12:"champ_annexe";s:1:"a";}i:1;a:1:{s:6:"champs";s:11:"code_barres";}i:2;a:1:{s:6:"champs";s:11:"code_barres";}i:3;a:1:{s:6:"champs";s:11:"code_barres";}i:5;a:3:{s:6:"champs";s:11:"code_barres";s:17:"xml_balise_abonne";s:0:"";s:17:"xml_champs_abonne";a:10:{s:6:"IDABON";s:0:"";s:9:"ORDREABON";s:0:"";s:3:"NOM";s:0:"";s:6:"PRENOM";s:0:"";s:9:"NAISSANCE";s:0:"";s:8:"PASSWORD";s:0:"";s:4:"MAIL";s:0:"";s:10:"DATE_DEBUT";s:0:"";s:8:"DATE_FIN";s:0:"";s:7:"ID_SIGB";s:0:"";}}i:4;a:5:{s:4:"zone";s:0:"";s:5:"champ";s:0:"";s:6:"format";s:0:"";s:5:"jours";s:0:"";s:7:"valeurs";s:0:"";}}';
+
+    $profile = Class_IntProfilDonnees::newInstance(['libelle' => $label,
+                                                    'accents' => Class_IntProfilDonnees::ENCODING_UTF8,
+                                                    'type_fichier' => Class_IntProfilDonnees::FT_RECORDS,
+                                                    'format' => Class_IntProfilDonnees::FORMAT_TABBED_ASCII,
+                                                    'attributs' => $attributs]);
+    $profile->save();
+    return $profile;
+  }
+
+
+  protected function _getBasketProfile() {
+    if ($profile = Class_IntProfilDonnees::findFirstBy(['accents' => Class_IntProfilDonnees::ENCODING_UTF8,
+                                                        'type_fichier' => Class_IntProfilDonnees::FT_BASKETS,
+                                                        'format' => Class_IntProfilDonnees::FORMAT_PIPED_ASCII]))
+      return $profile;
+
+    $profile = Class_IntProfilDonnees::newInstance(['libelle' => 'Paniers Nanook',
+                                                    'accents' => Class_IntProfilDonnees::ENCODING_UTF8,
+                                                    'rejet_periodiques' => 0,
+                                                    'id_article_periodique' => 4,
+                                                    'type_fichier' => Class_IntProfilDonnees::FT_BASKETS,
+                                                    'format' => Class_IntProfilDonnees::FORMAT_PIPED_ASCII,
+                                                    'attributs' => 'a:7:{i:0;a:9:{s:8:"type_doc";a:35:{i:0;a:3:{s:4:"code";s:1:"0";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:1;a:3:{s:4:"code";s:1:"1";s:5:"label";s:8:"am;na;mn";s:8:"zone_995";s:9:"LIV;MS;uu";}i:2;a:3:{s:4:"code";s:1:"2";s:5:"label";s:2:"as";s:8:"zone_995";s:3:"PER";}i:3;a:3:{s:4:"code";s:1:"3";s:5:"label";s:3:"i;j";s:8:"zone_995";s:17:"CD;LIVCD;LIVK7;K7";}i:4;a:3:{s:4:"code";s:1:"4";s:5:"label";s:1:"g";s:8:"zone_995";s:20:"DIAPO;DVD;VHS;VHD;VD";}i:5;a:3:{s:4:"code";s:1:"5";s:5:"label";s:6:"l;m;mm";s:8:"zone_995";s:3:"CDR";}i:6;a:3:{s:4:"code";s:1:"8";s:5:"label";s:0:"";s:8:"zone_995";s:1:"D";}i:7;a:3:{s:4:"code";s:1:"9";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:8;a:3:{s:4:"code";s:1:"8";s:5:"label";s:0:"";s:8:"zone_995";s:3:"DOS";}i:9;a:3:{s:4:"code";s:1:"9";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:10;a:3:{s:4:"code";s:2:"10";s:5:"label";s:0:"";s:8:"zone_995";s:6:"WEB;MF";}i:11;a:3:{s:4:"code";s:3:"102";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:12;a:3:{s:4:"code";s:3:"103";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:13;a:3:{s:4:"code";s:3:"104";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:14;a:3:{s:4:"code";s:3:"105";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:15;a:3:{s:4:"code";s:3:"106";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:16;a:3:{s:4:"code";s:3:"107";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:17;a:3:{s:4:"code";s:3:"108";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:18;a:3:{s:4:"code";s:3:"100";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:19;a:3:{s:4:"code";s:3:"101";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:20;a:3:{s:4:"code";s:3:"102";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:21;a:3:{s:4:"code";s:3:"103";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:22;a:3:{s:4:"code";s:3:"104";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:23;a:3:{s:4:"code";s:3:"105";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:24;a:3:{s:4:"code";s:3:"106";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:25;a:3:{s:4:"code";s:3:"107";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:26;a:3:{s:4:"code";s:3:"108";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:27;a:3:{s:4:"code";s:3:"109";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:28;a:3:{s:4:"code";s:3:"111";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:29;a:3:{s:4:"code";s:3:"110";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:30;a:3:{s:4:"code";s:3:"112";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:31;a:3:{s:4:"code";s:3:"114";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:32;a:3:{s:4:"code";s:3:"113";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:33;a:3:{s:4:"code";s:3:"115";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}i:34;a:3:{s:4:"code";s:3:"116";s:5:"label";s:0:"";s:8:"zone_995";s:0:"";}}s:17:"champ_code_barres";s:1:"a";s:10:"champ_cote";s:1:"f";s:14:"champ_type_doc";s:0:"";s:11:"champ_genre";s:1:"#";s:13:"champ_section";s:1:"w";s:17:"champ_emplacement";s:1:"x";s:12:"champ_annexe";s:1:"h";s:9:"champ_url";a:2:{s:4:"zone";s:0:"";s:5:"champ";s:0:"";}}i:1;a:1:{s:6:"champs";s:47:"ID_SIGB;LIBELLE;IDABON;MAIL;ROLE;ID_NOTICE_SIGB";}i:2;a:1:{s:6:"champs";s:47:"ID_SIGB;LIBELLE;IDABON;MAIL;ROLE;ID_NOTICE_SIGB";}i:3;a:1:{s:6:"champs";s:47:"ID_SIGB;LIBELLE;IDABON;MAIL;ROLE;ID_NOTICE_SIGB";}i:5;a:3:{s:6:"champs";s:47:"ID_SIGB;LIBELLE;IDABON;MAIL;ROLE;ID_NOTICE_SIGB";s:17:"xml_balise_abonne";s:0:"";s:17:"xml_champs_abonne";a:11:{s:6:"IDABON";s:0:"";s:9:"ORDREABON";s:0:"";s:3:"NOM";s:0:"";s:6:"PRENOM";s:0:"";s:9:"NAISSANCE";s:0:"";s:8:"PASSWORD";s:0:"";s:4:"MAIL";s:0:"";s:10:"DATE_DEBUT";s:0:"";s:8:"DATE_FIN";s:0:"";s:7:"ID_SIGB";s:0:"";s:9:"NUM_CARTE";s:0:"";}}i:4;a:5:{s:4:"zone";s:3:"995";s:5:"champ";s:1:"5";s:6:"format";s:1:"3";s:5:"jours";s:0:"";s:7:"valeurs";s:1:"1";}i:6;a:2:{s:4:"zone";s:0:"";s:5:"champ";s:0:"";}}']);
+    $profile->save();
+    return $profile;
+  }
+}
+
+
+
+class Class_Cosmogramme_GeneratorPlannedNanook extends Class_Cosmogramme_GeneratorPlannedAbstract{
+  protected
+    $_records_profile = 104,
+    $_users_profile = 105,
+    $_item_delete = true,
+    $_baskets = true;
+}
+
+
+
+class Class_Cosmogramme_GeneratorPlannedPergame extends Class_Cosmogramme_GeneratorPlannedAbstract{
+  protected
+    $_records_profile = 100,
+    $_users_profile = 101,
+    $_holds = true;
+}
\ No newline at end of file
diff --git a/library/Class/Cosmogramme/Generator/AbstractTask.php b/library/Class/Cosmogramme/Generator/AbstractTask.php
new file mode 100644
index 0000000000000000000000000000000000000000..f3b2730a43a0f586a927d88fbbf54c9057ed001d
--- /dev/null
+++ b/library/Class/Cosmogramme/Generator/AbstractTask.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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 Class_Cosmogramme_Generator_AbstractTask {
+  use Trait_Translator, Trait_Loggable, Trait_TimeSource;
+
+  protected $_generator;
+
+  public function __construct($generator) {
+    $this->_generator = $generator;
+  }
+
+
+  public function run($datas) {
+    if (!$datas) {
+      $this->log($this->_('Étalon des %s vide', $this->_name));
+      return false;
+    }
+
+    $this->logTitle($this->_('%d - Création des %s', $this->_id, $this->_name));
+    $date = $this->getCurrentDate();
+
+    $datas = $this->_prepare($datas);
+    $html = '';
+    foreach($datas as $data)
+      $html .= $this->_runOne($data, $date);
+
+    $this->log('<div class="liste"><table class="blank">' . $html . '</table></div>');
+
+    $this
+      ->_directQuery('delete from ' . $this->_table . ' where date_maj != "' . $date. '"')
+      ->_directQuery('update ' . $this->_table . ' set date_maj=""');
+
+    return true;
+  }
+
+
+  protected function _runOne($data, $date) {
+    $data = utf8_encode($data);
+    $elems = explode('|', $data);
+
+    if ($this->_isExcluded($elems))
+      return '';
+
+    $label = trim($elems[1]);
+    $code = strtolower($elems[0]);
+
+    $model_class = $this->_model_class;
+    if (!$model = $model_class::findFirstBy(['libelle' => $label]))
+      $model = $model_class::newInstance(['libelle' => $label]);
+
+    $model
+      ->setRegles($this->_createOrConcatRules($code, $model, $date))
+      ->setDateMaj($date)
+      ->save();
+
+    return $this->renderOne($code, $label);
+  }
+
+
+  protected function _isExcluded($elems) {
+    return false;
+  }
+
+
+  protected function _directQuery($sql) {
+    Zend_Db_Table::getDefaultAdapter()->query($sql);
+    return $this;
+  }
+
+
+  protected function logTitle($title) {
+    $this->log('<h3>' . $title . '</h3>');
+  }
+
+
+  protected function renderOne($code, $label) {
+    return '<tr><td class="blank">' . $code . '</td><td class="blank">' . $label . '</td></tr>';
+  }
+
+
+  protected function _createOrConcatRules($code, $model, $date) {
+    return !$model->isNew() && $model->getDateMaj() == $date
+      ? $model->getRegles() . ';' . $code
+      : $this->_getRuleFor($code);
+  }
+
+
+  protected function _getRuleFor($code) {
+    return '';
+  }
+
+
+  protected function _prepare($datas) {
+    return $datas;
+  }
+
+
+  public function isPergame() {
+    return $this->_generator->isPergame();
+  }
+
+
+  public function isNanook() {
+    return $this->_generator->isNanook();
+  }
+}
\ No newline at end of file
diff --git a/library/Class/Cosmogramme/Generator/KindsTask.php b/library/Class/Cosmogramme/Generator/KindsTask.php
new file mode 100644
index 0000000000000000000000000000000000000000..355a96b11f0ec808c608d938957bebd5cc55c254
--- /dev/null
+++ b/library/Class/Cosmogramme/Generator/KindsTask.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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_Cosmogramme_Generator_KindsTask extends Class_Cosmogramme_Generator_AbstractTask {
+  protected
+    $_index = 6,
+    $_name = 'genres',
+    $_table = 'codif_genre';
+
+
+  protected function _prepare($datas) {
+    $this->_kinds = [];
+    foreach($datas as $data)
+      $this->_prepareOne($data);
+
+    return $this->_kinds;
+  }
+
+
+  protected function _prepareOne($data) {
+    $data = utf8_encode($data);
+    $elems = explode('|', $data);
+    if ('BIB_' == substr($elems[0], 0, 4) || !trim($elems[1]))
+      return '';
+
+    $key = Class_Indexation::getInstance()->alphaMaj($elems[2]);
+    $code = trim($elems[1]);
+    $label = trim($elems[2]);
+
+    if (array_key_exists($key, $this->_kinds)) {
+      $this->_kinds[$key]['codes'][] = $code;
+      return;
+    }
+
+    $this->_kinds[$key] = ['codes' => [$code], 'label' => $label];
+  }
+
+
+  protected function _runOne($data, $date) {
+    $label = $data['label'];
+    $codes = implode(';', $data['codes']);
+
+    if (!$model = Class_CodifGenre::findFirstBy(['libelle' => $label]))
+      $model = Class_CodifGenre::newInstance(['libelle' => $label]);
+
+    $model
+      ->setRegles($this->_getRuleFor($codes))
+      ->setDateMaj($date)
+      ->save();
+
+    return $this->renderOne($codes, $label);
+  }
+
+
+  protected function _getRuleFor($codes) {
+    $field = null;
+    if ($this->isNanook())
+      $field = '995$7';
+    if ($this->isPergame())
+      $field = '930$4';
+
+    if ($field)
+      return $field . '=' . $codes;
+  }
+}
diff --git a/library/Class/Cosmogramme/Generator/LocationsTask.php b/library/Class/Cosmogramme/Generator/LocationsTask.php
new file mode 100644
index 0000000000000000000000000000000000000000..90512c8173dfdbc1298331405bf07a7ec7b4c1af
--- /dev/null
+++ b/library/Class/Cosmogramme/Generator/LocationsTask.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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_Cosmogramme_Generator_LocationsTask extends Class_Cosmogramme_Generator_AbstractTask {
+  protected
+    $_index = 5,
+    $_name = 'emplacements',
+    $_table = 'codif_emplacement',
+    $_model_class = 'Class_CodifEmplacement';
+
+
+  protected function _isExcluded($elems) {
+    return 'BIB_' == substr($elems[0], 0, 4) || !trim($elems[0]);
+  }
+
+
+  protected function _getRuleFor($code) {
+    return '995$6=' . $code;
+  }
+}
diff --git a/library/Class/Cosmogramme/Generator/SectionsTask.php b/library/Class/Cosmogramme/Generator/SectionsTask.php
new file mode 100644
index 0000000000000000000000000000000000000000..97b53c0ef2e8fbc356abd7b2189fec96f5f8beeb
--- /dev/null
+++ b/library/Class/Cosmogramme/Generator/SectionsTask.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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_Cosmogramme_Generator_SectionsTask extends Class_Cosmogramme_Generator_AbstractTask {
+  protected
+    $_index = 4,
+    $_name = 'sections',
+    $_table = 'codif_section',
+    $_model_class = 'Class_CodifSection';
+
+
+  protected function _isExcluded($elems) {
+    return 'BIB_C_SECTION' == $elems[0] || !trim($elems[0]);
+  }
+
+
+  protected function _getRuleFor($code) {
+    $field = null;
+    if ($this->isNanook())
+      $field = '9';
+    if ($this->isPergame())
+      $field = 'q';
+
+    if ($field)
+      return '995$' . $field . '=' . strtolower($code);
+  }
+}
\ No newline at end of file
diff --git a/library/Class/Cosmogramme/Integration/Chronometre.php b/library/Class/Cosmogramme/Integration/Chronometre.php
index 485131f7085fcaef99ca93bb963131314d7ecdb1..369a1b4c1a20ea0dbd779c8cb43b3325a0c86c04 100644
--- a/library/Class/Cosmogramme/Integration/Chronometre.php
+++ b/library/Class/Cosmogramme/Integration/Chronometre.php
@@ -39,10 +39,9 @@ class Class_Cosmogramme_Integration_Chronometre {
 
 
   public function backToLegacyState($main, $on_file, $on_records) {
-    foreach ([$main => $this->_main,
-              $on_file => $this->_on_file,
-              $on_records => $this->_on_records] as $legacy => $internal)
-      $legacy->timeStart = $internal->getStart();
+    $main->timeStart = $this->_main->getStart();
+    $on_file->timeStart = $this->_on_file->getStart();
+    $on_records->timeStart = $this->_on_records->getStart();
   }
 
 
diff --git a/library/Class/Cosmogramme/Integration/PhaseAbstract.php b/library/Class/Cosmogramme/Integration/PhaseAbstract.php
index e7d2935c27d167c01d5d8dbc5806c0694f732c6d..7f74223fd1fa11c3745231c90df20041ca061bea 100644
--- a/library/Class/Cosmogramme/Integration/PhaseAbstract.php
+++ b/library/Class/Cosmogramme/Integration/PhaseAbstract.php
@@ -23,8 +23,13 @@
 abstract class Class_Cosmogramme_Integration_PhaseAbstract {
   use Trait_TimeSource, Trait_StaticFileSystem, Trait_Translator, Trait_MemoryCleaner;
 
-  protected $_label = '';
-  protected $_phase, $_log, $_printer, $_chrono, $_is_time_out;
+  protected $_label = '',
+    $_phase,
+    $_log,
+    $_printer,
+    $_chrono,
+    $_is_time_out,
+    $_db_reset = true;
 
 
   public function __construct($phase, $log, $chrono) {
@@ -83,7 +88,14 @@ abstract class Class_Cosmogramme_Integration_PhaseAbstract {
 
     $this->_printLabel();
 
-    $this->_execute();
+    try {
+      $this->_execute();
+    } catch (Exception $e) {
+      $this->_log->ecrire('<p class="rouge">' . sprintf('Erreur lors de l\'execution de la phase %s : </br>%s',
+                                                        $this->_label,
+                                                        $e->getMessage()) . '</p>');
+      $this->_cleanMemory();
+    }
 
     return $this->_phase;
   }
@@ -160,4 +172,11 @@ abstract class Class_Cosmogramme_Integration_PhaseAbstract {
     gc_collect_cycles();
     return $this;
   }
+
+
+  /** @category testing */
+  public function noDbReset() {
+    $this->_db_reset = false;
+    return $this;
+  }
 }
\ No newline at end of file
diff --git a/library/Class/Cosmogramme/Integration/PhaseBatchs.php b/library/Class/Cosmogramme/Integration/PhaseBatchs.php
index 8bb8714e42e16a16365b50f96011055f5cc2e77e..56106347c28881d061e6e749f352ff6479761d9d 100644
--- a/library/Class/Cosmogramme/Integration/PhaseBatchs.php
+++ b/library/Class/Cosmogramme/Integration/PhaseBatchs.php
@@ -44,6 +44,8 @@ class Class_Cosmogramme_Integration_PhaseBatchs
 
       $this->_resetHttpClient()
            ->_runOne($batch);
+
+      $this->_cleanMemory();
     }
   }
 
diff --git a/library/Class/Cosmogramme/Integration/PhaseItemFacets.php b/library/Class/Cosmogramme/Integration/PhaseItemFacets.php
index 1c40d36af5d451131ee267fcb82902a57dd4932b..829bef1673fc8da0b04a03111bb78b29f8620408 100644
--- a/library/Class/Cosmogramme/Integration/PhaseItemFacets.php
+++ b/library/Class/Cosmogramme/Integration/PhaseItemFacets.php
@@ -39,6 +39,8 @@ class Class_Cosmogramme_Integration_PhaseItemFacets
   public function _execute() {
     while ($records = Class_Notice::findAllAfter($this->_getData('pointeur_notice'),
                                                  $this->_getData('pointeur'))) {
+      if ($this->isTimeOut())
+        return $this->_phase;
 
       if (0 == ($this->_getData('nombre') % 100))
         $this->_log->ecrire('<span class="vert"> ' . $this->_getData('nombre') . ' records updated </span>');
@@ -52,6 +54,7 @@ class Class_Cosmogramme_Integration_PhaseItemFacets
       $this->runUpdateForRecords($records);
 
       $this->_resetDbConnection();
+      $this->_cleanMemory();
     }
 
     Class_CosmoVar::setValueOf('date_maj_facettes', $this->_last_update_date);
@@ -121,12 +124,4 @@ class Class_Cosmogramme_Integration_PhaseItemFacets
   protected function _wasRunning() {
     return $this->_getData('pointeur_notice') > 0;
   }
-
-
-  /** @category testing */
-  public function noDbReset() {
-    $this->_db_reset = false;
-    return $this;
-  }
 }
-?>
\ No newline at end of file
diff --git a/library/Class/Cosmogramme/Integration/PhaseOnDataSource.php b/library/Class/Cosmogramme/Integration/PhaseOnDataSource.php
index c95a715ac56c486db59f119416e46093dde947ee..ff2634035af6ca41518af06480a51ec6b1d259d3 100644
--- a/library/Class/Cosmogramme/Integration/PhaseOnDataSource.php
+++ b/library/Class/Cosmogramme/Integration/PhaseOnDataSource.php
@@ -30,6 +30,7 @@ abstract class Class_Cosmogramme_Integration_PhaseOnDataSource extends Class_Cos
         return $this->_phase;
 
       $this->_runOne($integration);
+      $this->_cleanMemory();
     }
 
     $this->_setData('pointeur', 0);
diff --git a/library/Class/Cosmogramme/Integration/PhasePseudoRecord.php b/library/Class/Cosmogramme/Integration/PhasePseudoRecord.php
index 8e91dc3e70a4e7c4f3421f4b1e3e129804557e80..3ead13c40dc59b242cb8867285249f7a2300f00b 100644
--- a/library/Class/Cosmogramme/Integration/PhasePseudoRecord.php
+++ b/library/Class/Cosmogramme/Integration/PhasePseudoRecord.php
@@ -54,6 +54,7 @@ abstract class Class_Cosmogramme_Integration_PhasePseudoRecord
         return;
 
       $this->_runPage($models);
+      $this->_cleanMemory();
     }
 
     $this->_summarize();
diff --git a/library/Class/Cosmogramme/Integration/PhaseReviews.php b/library/Class/Cosmogramme/Integration/PhaseReviews.php
index 0492474e46662dceb6f5928e19f1eea3a112affd..6a465b155e7bd19f03de2c3f64cfda24c559431d 100644
--- a/library/Class/Cosmogramme/Integration/PhaseReviews.php
+++ b/library/Class/Cosmogramme/Integration/PhaseReviews.php
@@ -23,7 +23,6 @@ class Class_Cosmogramme_Integration_PhaseReviews extends Class_Cosmogramme_Integ
   const MY_ID=7.5;
 
   protected $_label = 'Reviews attachments';
-  protected $_db_reset=true;
 
   public function __construct($phase, $log, $chrono) {
     parent::__construct($phase, $log, $chrono);
@@ -52,7 +51,9 @@ class Class_Cosmogramme_Integration_PhaseReviews extends Class_Cosmogramme_Integ
   public function _execute() {
     $page = 1;
     while ($records = Class_AvisNotice::findAllBy(['order' => 'id',
-                                                   'limitPage' => [$page, 500]])) {
+                                                   'limitPage' => [$page, 100]])) {
+      if ($this->isTimeOut())
+        return $this->_phase;
 
       if ($this->_log && (0 == ($this->_getData('nombre') % 100)))
         $this->_log->ecrire('<span class="vert"> ' . $this->_getData('nombre') . ' avis mis à jour </span>');
@@ -60,7 +61,7 @@ class Class_Cosmogramme_Integration_PhaseReviews extends Class_Cosmogramme_Integ
       $this->runUpdateForRecords($records);
 
       $this->_resetDbConnection();
-
+      $this->_cleanMemory();
       $page++;
     }
 
@@ -76,7 +77,6 @@ class Class_Cosmogramme_Integration_PhaseReviews extends Class_Cosmogramme_Integ
 
       $this->_log->ecrire($msg);
     }
-
   }
 
 
@@ -97,23 +97,4 @@ class Class_Cosmogramme_Integration_PhaseReviews extends Class_Cosmogramme_Integ
     $this->_incrementData('nombre');
 
   }
-
-  /** @category testing */
-  public function noDbReset() {
-    $this->_db_reset = false;
-    return $this;
-  }
-
-  protected function _resetDbConnection() {
-    if (!$this->_db_reset)
-      return $this;
-
-    Storm_Model_Abstract::unsetLoaders();
-    Zend_Db_Table::getDefaultAdapter()->closeConnection();
-    setupDatabase(loadConfig());
-    gc_collect_cycles();
-    return $this;
-  }
-
-
 }
\ No newline at end of file
diff --git a/library/Class/Cosmogramme/LandingDirectory.php b/library/Class/Cosmogramme/LandingDirectory.php
new file mode 100644
index 0000000000000000000000000000000000000000..798c55efee2631ffe36012c8579f7a808ba8785d
--- /dev/null
+++ b/library/Class/Cosmogramme/LandingDirectory.php
@@ -0,0 +1,144 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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_Cosmogramme_LandingDirectory {
+  use Trait_StaticFileSystem, Trait_Translator, Trait_Loggable, Trait_Singleton;
+
+  const VAR_NAME = 'ftp_path';
+  const STANDARD_NAME = 'etalon';
+
+  protected
+    $_path,
+    $_required_files = ['libraries' => 'annexes.txt',
+                        'kinds' => 'genres.txt',
+                        'sections' => 'sections.txt',
+                        'locations' => 'emplacements.txt'];
+
+
+  public function __construct() {
+    $this->_path = Class_CosmoVar::getValueOf(static::VAR_NAME);
+  }
+
+
+  public function isValid() {
+    if ($this->_path && $this->getFileSystem()->file_exists($this->_path))
+      return true;
+
+    $this->log($this->_('La variable ftp_path est absente, incorrecte ou le dossier n\'a pas été créé.'));
+    return false;
+  }
+
+
+  public function couldGenerateFrom($subdir) {
+    if (!$this->isValid())
+      return false;
+
+    if (!$subdir) {
+      $this->log($this->_('Aucun répertoire fourni'));
+      return false;
+    }
+
+    $file_system = $this->getFileSystem();
+    $standard_dir = $this->_getStandardDirPath($subdir);
+
+    if (!$file_system->is_readable($standard_dir)) {
+      $this->log($this->_('Répertoire %s non présent ou non lisible', $standard_dir));
+      return false;
+    }
+
+    foreach($this->_required_files as $file) {
+      $file_path = $this->_getStandardFilePath($subdir, $file);
+      if (!$file_system->is_readable($file_path)) {
+        $this->log($this->_('Fichier %s non présent ou non lisible', $file_path));
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+
+  public function getSubdirPath($subdir) {
+    return $this->_path
+      . (DIRECTORY_SEPARATOR != substr($this->_path, -1) ? DIRECTORY_SEPARATOR : '')
+      . $subdir;
+  }
+
+
+  protected function _getStandardDirPath($subdir) {
+    return $this->getSubdirPath($subdir) . DIRECTORY_SEPARATOR . static::STANDARD_NAME;
+  }
+
+
+  protected function _getStandardFilePath($subdir, $file) {
+    return $this->_getStandardDirPath($subdir) . DIRECTORY_SEPARATOR . $file;
+  }
+
+
+  public function getLibrariesOf($subdir) {
+    return $this->getFileNamed('libraries', $subdir);
+  }
+
+
+  public function getSectionsOf($subdir) {
+    return $this->getFileNamed('sections', $subdir);
+  }
+
+
+  public function getLocationsOf($subdir) {
+    return $this->getFileNamed('locations', $subdir);
+  }
+
+
+  public function getKindsOf($subdir) {
+    return $this->getFileNamed('kinds', $subdir);
+  }
+
+
+  protected function getFileNamed($name, $subdir) {
+    $file = $this->_getStandardFilePath($subdir, $this->_required_files[$name]);
+    return $this->getFileSystem()->file($file);
+  }
+
+
+  public function getSubdirectories() {
+    if (!$this->isValid())
+      return [];
+
+    $file_system = $this->getFileSystem();
+
+    if (!$dir = $file_system->opendir($this->_path))
+      return [];
+
+    $subdirs = [];
+    while (false !== $file = $file_system->readdir($dir)) {
+      if ('.' == substr($file, 0, 1)
+          || 'test' == $file
+          || !$file_system->is_dir($this->_path . $file))
+        continue;
+
+      $subdirs[$file] = $file;
+    }
+
+    return $subdirs;
+  }
+}
\ No newline at end of file
diff --git a/library/Class/IntBib.php b/library/Class/IntBib.php
index f5b8138b07d5cc1779e4424ba37b262afe7aaf04..1163fb5c4b424313f6436399b73a64f2a91460bb 100644
--- a/library/Class/IntBib.php
+++ b/library/Class/IntBib.php
@@ -43,6 +43,8 @@ class Class_IntBib extends Storm_Model_Abstract {
   const COM_CDSCRIPT = 12;
 
   const SIGB_NONE = 0;
+  const SIGB_PERGAME = 1;
+  const SIGB_NANOOK = 13;
 
   protected static $COM_CLASSES = [self::COM_PERGAME => 'Class_WebService_SIGB_Pergame',
                                    self::COM_OPSYS => 'Class_WebService_SIGB_Opsys',
diff --git a/library/Class/Log.php b/library/Class/Log.php
new file mode 100644
index 0000000000000000000000000000000000000000..b47bc1cad0b634f4a7edefcebdb7cc817fa4dfcd
--- /dev/null
+++ b/library/Class/Log.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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_Log {
+  use Trait_Singleton;
+
+  protected $_messages = [];
+
+  public function log($message) {
+    $this->_messages[] = $message;
+    return $this;
+  }
+
+
+  public function getLastMessage() {
+    return end($this->_messages);
+  }
+
+
+  public function getMessages() {
+    return $this->_messages;
+  }
+
+
+  public function reset() {
+    $this->_messages = [];
+    return $this;
+  }
+}
\ No newline at end of file
diff --git a/library/Class/OneDTouchLink.php b/library/Class/OneDTouchLink.php
index 148ddf043a70aa5252c249162451a37127c776b0..589137d2e3aba89ae164f9ba30a4f7d76c16c208 100644
--- a/library/Class/OneDTouchLink.php
+++ b/library/Class/OneDTouchLink.php
@@ -21,28 +21,40 @@
 
 
 class Class_OneDTouchLink {
+  use Trait_Translator;
+
   const BASE_URL = 'http://music.1dtouch.com/';
 
-  public static function urlFor($album) {
-    if (Class_AdminVar::isOneDTouchSso())
-      return static::ssoUrlFor($album);
+  const NEW_VERSION = 'NEW';
+  const OLD_VERSION = 'OLD';
 
-    return sprintf(static::simpleUrlPattern(), $album->getIdOrigine());
+  public function urlFor($album) {
+    return static::BASE_URL
+      . (Class_AdminVar::isOneDTouchSso() ? $this->ssoUrlFor($album) : $this->simpleUrlFor($album));
   }
 
 
-  public static function ssoUrlFor($album) {
-    return sprintf(static::ssoUrlPattern(), Class_AdminVar::get('ONEDTOUCH_ID'), $album->getIdOrigine());
+  protected function simpleUrlFor($album) {
+    return 'albums/' . $album->getIdOrigine();
   }
 
 
-  public static function simpleUrlPattern() {
-    return static::BASE_URL . 'albums/%s';
+  protected function ssoUrlFor($album) {
+    return $this->ssoUrl() . $this->simpleUrlFor($album);
+  }
+
+
+  protected function ssoUrl() {
+    $id = Class_AdminVar::get('ONEDTOUCH_ID');
+
+    return (static::NEW_VERSION == Class_AdminVar::get('ONEDTOUCH_VERSION_URL'))
+      ? 'users/auth/afi?bibid=' . $id. '&dest='
+      : 'users/auth/' . $id . '?dest=';
   }
 
 
-  public static function ssoUrlPattern() {
-    return static::BASE_URL . 'users/auth/%s?dest=albums/%s';
+  public function getVersionOptions() {
+    return [static::NEW_VERSION => $this->_('Nouvelle version'),
+            static::OLD_VERSION => $this->_('Ancienne version')];
   }
-}
-?>
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/library/Class/PanierNotice.php b/library/Class/PanierNotice.php
index ad54242e17032534c9d879c9de294b096a55ab7e..8171d695f3ab6b9362d134919d630ef6cdbffbcf 100644
--- a/library/Class/PanierNotice.php
+++ b/library/Class/PanierNotice.php
@@ -47,20 +47,26 @@ class PanierNoticeLoader extends Storm_Model_Loader {
   }
 
 
+  public function findAllIdsWithCatalogue() {
+    $panier_notice_catalogue = Class_PanierNoticeCatalogue::getLoader()->findAll();
+    $ids_with_catalogue = array_map(function($association) {return $association->getIdPanier();}, $panier_notice_catalogue);
+    return array_filter(array_unique($ids_with_catalogue));
+  }
+
+
   public function findAllWithCatalogue() {
-    $this->user = Class_Users::getIdentity();
+    $ids = $this->findAllIdsWithCatalogue();
+
+    if(empty($ids))
+       return [];
 
-    return array_filter(
-                        array_unique(
-                                     array_map(
-                                               function($association) {return $association->getPanierNotice();},
-                                               Class_PanierNoticeCatalogue::findAll())));
+    return Class_PanierNotice::findAllBy(['id' => $ids]);
   }
 
 
   public function indexAll() {
     Class_NoticeDomain::deleteBy(['panier_id not' => 0]);
-    $cart_to_index = Class_PanierNotice::findAllWithCatalogue();
+    $cart_to_index = Class_PanierNotice::getLoader()->findAllWithCatalogue();
     foreach($cart_to_index as $cart) {
       $cart->index();
     }
diff --git a/library/Class/Profil.php b/library/Class/Profil.php
index 8495ddf1c0d53b7e2361ffa71fdcda4923b10e59..f3c1562cd048b1d12f0c6b73cbaef48c008fdda3 100644
--- a/library/Class/Profil.php
+++ b/library/Class/Profil.php
@@ -20,6 +20,8 @@
  */
 
 class ProfilLoader extends Storm_Model_Loader {
+  protected $_root;
+
   public function getProfilsByBib($id_zone, $id_bib) {
     $profils = Class_Profil::findAllByZoneAndBib($id_zone, $id_bib);
     $profils_by_bib = [];
@@ -76,7 +78,9 @@ class ProfilLoader extends Storm_Model_Loader {
   }
 
   public function getRoot() {
-    return Class_profil::newInstanceWithId(null,[]);
+    return isset($this->_root)
+      ? $this->_root
+      : ($this->_root = Class_profil::newInstanceWithId(null,[]));
   }
 
   public function isAPhoneProfilEnabled() {
diff --git a/library/Class/Testing/FileSystem.php b/library/Class/Testing/FileSystem.php
index 09bba9a1ac942d30300f97617b184ff768c720f6..5f7a756a1eda8492047a59eb388a8974e87af5d1 100644
--- a/library/Class/Testing/FileSystem.php
+++ b/library/Class/Testing/FileSystem.php
@@ -25,8 +25,9 @@ class Class_Testing_FileSystem {
      'rmdir', 'unlink', 'fopen', 'fseek', 'fgets',
      'filesize', 'fclose', 'ftell', 'fread', 'feof',
      'getcwd', 'file_exists', 'scandir', 'is_dir',
-     'opendir', 'readdir', 'closedir', 'mkdir','glob','file', 'fwrite','rename',
-     'getimagesize', 'file_get_contents', 'sha1_file', 'is_file', 'pathinfo'
+     'opendir', 'readdir', 'closedir', 'mkdir', 'glob', 'file', 'fwrite','rename',
+     'getimagesize', 'file_get_contents', 'sha1_file', 'is_file', 'pathinfo',
+     'is_readable'
     ];
 
 
diff --git a/library/Class/Users.php b/library/Class/Users.php
index 258c2df68a603713e27f38593678aefc55928c76..b954f9f4b962587cef4696a7c15eb634214254dd 100644
--- a/library/Class/Users.php
+++ b/library/Class/Users.php
@@ -239,6 +239,64 @@ class UsersLoader extends Storm_Model_Loader {
             Class_Users::CIVILITE_MONSIEUR => $this->_('Monsieur')];
   }
 
+
+  protected function _buildOrWhereParams($or, $sql_subscription) {
+    $table_or = [];
+    $sql = [];
+
+    foreach($or as $column => $value)
+      $table_or[] = sprintf('%s LIKE "%%%s%%"', $column, $value);
+
+    $sql_or = implode(' OR ', $table_or);
+
+    if(!$sql_subscription)
+      return ['where' => $sql_or];
+
+    if(!$sql_or)
+      return ['where' => $sql_subscription];
+
+    return ['where' => '(' . $sql_or  . ') AND ' . $sql_subscription];
+  }
+
+
+  protected function _buildSearchParams($default, $where, $valide_subscription, $limit = null) {
+    if(!isset($default['role_level']))
+      $default['role_level'] = 'all';
+
+    if(!isset($default['id_site']))
+      $default['id_site'] = 'all';
+
+    $sql_subscription = '';
+    if($valide_subscription && ($default['role_level'] == ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB))
+      $sql_subscription = 'STR_TO_DATE(date_fin, \'%Y-%m-%d\') >= CURDATE()';
+
+    $where = $this->_buildOrWhereParams($where, $sql_subscription);
+
+    if($limit)
+      $where['limitPage'] = $limit;
+
+    $params = array_merge($default, $where);
+
+    if($params['role_level'] == 'all')
+      unset($params['role_level']);
+
+    if($params['id_site'] == 'all')
+      unset($params['id_site']);
+
+    return $params;
+  }
+
+
+  public function findSearched($default, $where, $valide_subscription, $limit) {
+    $search_params = $this->_buildSearchParams($default, $where, $valide_subscription, $limit);
+    return Class_Users::findAllBy($search_params);
+  }
+
+
+  public function countSearched($defaults, $where, $valide_subscription) {
+    $count_params = $this->_buildSearchParams($defaults, $where, $valide_subscription);
+    return Class_Users::countBy($count_params);
+  }
 }
 
 
@@ -855,48 +913,6 @@ class Class_Users extends Storm_Model_Abstract {
   }
 
 
-  public function getUsers($id_zone,$id_site,$role_level,$recherche,$page)
-  {
-    if($id_site and $id_site !="ALL")
-      {
-        if($id_site=="PORTAIL") $id_site=0;
-        $cond[]="id_site=$id_site";
-      }
-    elseif($id_zone and $id_zone !="ALL")
-      {
-        if($id_zone=="PORTAIL") $cond[]="ID_SITE=0";
-        else
-          {
-            $bibs=fetchAll("select ID_SITE from bib_c_site where ID_ZONE=$id_zone");
-            if(!$bibs) return false;
-            foreach($bibs as $bib)
-              {
-                if($inSql) $inSql.=",";
-                $inSql.=$bib["ID_SITE"];
-              }
-            $cond[]="ID_SITE in($inSql)";
-          }
-      }
-
-    $recherche = array_merge(array('role' => '', 'login' => '', 'nom' => ''),
-                             $recherche);
-
-    if($recherche["role"]>"") $cond[]="ROLE_LEVEL=".$recherche["role"];
-    else $cond[]="ROLE_LEVEL<=$role_level";
-    if($recherche["login"]) $cond[]="LOGIN like '".addslashes($recherche["login"])."%'";
-    if($recherche["nom"]) $cond[]="NOM like '".addslashes($recherche["nom"])."%'";
-    $where=getWhereSql($cond);
-    $req_comptage="select count(*) from bib_admin_users ".$where;
-    $req_liste="select * from bib_admin_users ".$where." order by LOGIN ";
-
-    // Retour
-    $ret["nb_par_page"]=30;
-    $ret["nombre"]=fetchOne($req_comptage);
-    $ret["users"]=fetchAll($req_liste.getLimitSql($ret["nb_par_page"],$page));
-    return $ret;
-  }
-
-
   public function updatePseudo($data_user, $pseudo) {
     $user = $this->getLoader()->find($data_user->ID_USER);
     if ($user == null) return false;
@@ -1439,23 +1455,18 @@ class Class_Users extends Storm_Model_Abstract {
   }
 
 
-  public function getEditablePaniers() {
-    $user_paniers  = $this->getPaniers();
-    if ($this->canAccessBackend())
-      $user_paniers = array_filter(array_unique(array_merge($user_paniers,
-                                                            Class_PanierNotice::findAllWithCatalogue())));
-    Class_PanierNotice::sortPaniersByLibelle($user_paniers);
-    return $user_paniers;
-  }
-
-
   public function canModifyPanier($panier) {
     if (!$panier || $panier->isNew())
       return true;
 
-    $ids_paniers = array_map(function($panier) {return $panier->getId();},
-                             $this->getEditablePaniers());
-    return in_array($panier->getId(), $ids_paniers);
+    $user_paniers_ids = (new Storm_Model_Collection($this->getPaniers()))->collect('id');
+    if (in_array($panier->getId(), $user_paniers_ids->getArrayCopy()))
+      return true;
+
+    if (!$this->canAccessBackend())
+      return false;
+
+    return in_array($panier->getId(), Class_PanierNotice::findAllIdsWithCatalogue());
   }
 
 
diff --git a/library/Class/WebService/DublinCoreParser.php b/library/Class/WebService/DublinCoreParser.php
index 863f259719f9863320fa4a804a4f1dd4181f1864..a9896f0a9b7bb45e97294713e35ef22a50cbfdd2 100644
--- a/library/Class/WebService/DublinCoreParser.php
+++ b/library/Class/WebService/DublinCoreParser.php
@@ -65,7 +65,7 @@ class Class_WebService_DublinCoreParser extends Class_WebService_OAI_ParserAbstr
   public function newRecord($attributes) {
     $this->_record=[];
     $this->ressource_numerique = $this->visitor->getNewRessourceNumerique();
-    $this->_records_ressources[] = $this->ressource_numerique;
+    $this->_records_ressources[] = $this->getRessourceNumerique();
   }
 
 
@@ -75,49 +75,49 @@ class Class_WebService_DublinCoreParser extends Class_WebService_OAI_ParserAbstr
 
 
   public function enddc_identifier($data) {
-    $this->ressource_numerique->setOaiId($data);
+    $this->getRessourceNumerique()->setOaiId($data);
     $this->_record['id_oai']=$data;
   }
 
 
   public function enddc_title($data) {
-    $this->ressource_numerique->setTitle($data);
+    $this->getRessourceNumerique()->setTitle($data);
     $this->_record['titre']=$data;
   }
 
 
   public function enddc_creator($data) {
-    $this->ressource_numerique->addAuthor($data);
+    $this->getRessourceNumerique()->addAuthor($data);
     $this->_record['auteur']=$data;
   }
 
 
   public function enddc_publisher($data) {
-    $this->ressource_numerique->setEditeur($data);
+    $this->getRessourceNumerique()->setEditeur($data);
     $this->_record['editeur']=$data;
   }
 
   public function enddc_subject($data) {
-    $this->ressource_numerique->addMatiere($data);
+    $this->getRessourceNumerique()->addMatiere($data);
   }
 
   public function enddc_date($data) {
     $date = $data;
     if (strlen($date)>4)
-      $this->ressource_numerique->setYear(substr($date,0,4));
+      $this->getRessourceNumerique()->setYear(substr($date,0,4));
     $this->_record['date']=$date;
   }
 
 
   public function enddc_relation($data) {
     $this->_record['relation']=$data;
-    $this->ressource_numerique->setExternalUri($data);
+    $this->getRessourceNumerique()->setExternalUri($data);
   }
 
 
   public function enddc_description($data) {
     $this->_record['description']=$data;
-    $this->ressource_numerique->setDescription($data);
+    $this->getRessourceNumerique()->setDescription($data);
   }
 
 
@@ -129,5 +129,12 @@ class Class_WebService_DublinCoreParser extends Class_WebService_OAI_ParserAbstr
   public function getRecordsRessourceNumeriques() {
     return $this->_records_ressources;
   }
+
+
+  protected function getRessourceNumerique() {
+    if(!$this->ressource_numerique)
+      $this->ressource_numerique = new Class_WebService_BibNumerique_RessourceNumerique();
+    return $this->ressource_numerique;
+  }
 }
 ?>
diff --git a/library/Class/WebService/OneDTouchDCParser.php b/library/Class/WebService/OneDTouchDCParser.php
index 71dc88cad231814b072235e1863946df6ccb7c74..3166a6d075791da8a6e4944e9e84d4c109c462f9 100644
--- a/library/Class/WebService/OneDTouchDCParser.php
+++ b/library/Class/WebService/OneDTouchDCParser.php
@@ -46,7 +46,7 @@ class Class_WebService_OneDTouchDCParser extends Class_WebService_DublinCorePars
     if ($this->parser->getParent() == 'track') {
       return $this->current_track->setUrl($data);
     }
-    $this->ressource_numerique->setExternalUri($data);
+    $this->getRessourceNumerique()->setExternalUri($data);
   }
 
 
@@ -67,7 +67,7 @@ class Class_WebService_OneDTouchDCParser extends Class_WebService_DublinCorePars
 
 
   public function endTracks() {
-    $this->ressource_numerique->setRessources($this->tracks);
+    $this->getRessourceNumerique()->setRessources($this->tracks);
   }
 
 
@@ -82,7 +82,7 @@ class Class_WebService_OneDTouchDCParser extends Class_WebService_DublinCorePars
 
 
   public function endCover_url($data) {
-    $this->ressource_numerique->addPoster($data);
+    $this->getRessourceNumerique()->addPoster($data);
   }
 
 
diff --git a/library/Class/WebService/XMLParser.php b/library/Class/WebService/XMLParser.php
index 4b5bea8af96d308ac18e7007f733b5480b4223fb..f15109fcc53348b54ebb67df9966882f9a5f43f8 100644
--- a/library/Class/WebService/XMLParser.php
+++ b/library/Class/WebService/XMLParser.php
@@ -20,6 +20,7 @@
  */
 
 class Class_WebService_XMLParser {
+  use Trait_Logger;
 
   protected $_current_data ;
   protected $_parents ;
@@ -87,8 +88,9 @@ class Class_WebService_XMLParser {
       $column = xml_get_current_column_number($parser);
       $byte = xml_get_current_byte_index($parser);
       $error_msg = "XML parser error: $error_string"
-        . " at line $line column $column byte $byte (code: $error_code)";
-      error_log($error_msg);
+        . " at line $line column $column byte $byte (code: $error_code)"
+        . $xml;
+      $this->getLogger()->log($error_msg);
     }
     xml_parser_free($parser) ;
     return $this ;
diff --git a/library/Trait/Loggable.php b/library/Trait/Loggable.php
new file mode 100644
index 0000000000000000000000000000000000000000..6f29e8ce4099f93a9d57ff1fe3e4586cd3159d0a
--- /dev/null
+++ b/library/Trait/Loggable.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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
+ */
+
+
+trait Trait_Loggable {
+  public function getLog() {
+    return Class_Log::getInstance();
+  }
+
+
+  public function log($message) {
+    $this->getLog()->log($message);
+    return $this;
+  }
+}
\ No newline at end of file
diff --git a/library/Trait/TreeNode.php b/library/Trait/TreeNode.php
index 14dff96df30b738fa4513398426cf6ab8bb3b16f..ffffbb4566404c9a074b6f1fa1f928e6eff6bab7 100644
--- a/library/Trait/TreeNode.php
+++ b/library/Trait/TreeNode.php
@@ -22,6 +22,8 @@
 trait Trait_TreeNode {
   public static $PATH_SEPARATOR = '/';
 
+  protected $_path_cache = [];
+
   public function getPath() {
     return static::$PATH_SEPARATOR.implode(static::$PATH_SEPARATOR, $this->getPathParts());
   }
@@ -38,6 +40,14 @@ trait Trait_TreeNode {
    * @param $path string: le chemin pour retrouver un enfant dans la hiérarchie. Ex: /Histoire/Politique/XXe
    */
   public function findByPath($path) {
+    if (array_key_exists($path, $this->_path_cache))
+      return $this->_path_cache[$path];
+
+    return $this->_path_cache[$path] = $this->_computeFindByPath($path);
+  }
+
+
+  protected function _computeFindByPath($path) {
     if (!$parts = array_filter(explode(static::$PATH_SEPARATOR, $path)))
       return $this;
 
diff --git a/library/ZendAfi/Controller/Action/Helper/Cosmo/ViewRenderer.php b/library/ZendAfi/Controller/Action/Helper/Cosmo/ViewRenderer.php
new file mode 100644
index 0000000000000000000000000000000000000000..fdf40231cfe4876cee520fd25ec90110775fc5a6
--- /dev/null
+++ b/library/ZendAfi/Controller/Action/Helper/Cosmo/ViewRenderer.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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 ZendAfi_Controller_Action_Helper_Cosmo_ViewRenderer extends Zend_Controller_Action_Helper_ViewRenderer{
+  public function __construct(Zend_View_Interface $view = null, array $options = array()) {
+    parent::__construct(new ZendAfi_CosmoView(), $options);
+  }
+}
\ No newline at end of file
diff --git a/library/ZendAfi/CosmoView.php b/library/ZendAfi/CosmoView.php
new file mode 100644
index 0000000000000000000000000000000000000000..26da1e600cbed5bb0c3eb4164bbd1d9b5139117c
--- /dev/null
+++ b/library/ZendAfi/CosmoView.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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 ZendAfi_CosmoView extends Zend_View {
+  use Trait_Translator;
+}
diff --git a/library/ZendAfi/Form/Admin/EditAvis.php b/library/ZendAfi/Form/Admin/EditAvis.php
index c11db2b589e063d4756d7d717915f7d04a4527fd..c7556b835ac62190d5d6bcabf1db6133f5cce4e2 100644
--- a/library/ZendAfi/Form/Admin/EditAvis.php
+++ b/library/ZendAfi/Form/Admin/EditAvis.php
@@ -41,7 +41,8 @@ class ZendAfi_Form_Admin_EditAvis extends ZendAfi_Form {
     $this->setAttrib('data-backurl',
                      $this->getView()->url(['module' => 'admin',
                                             'controller' => 'modo',
-                                            'action' => $action], null, true));
+                                            'action' => $action,
+                                            'id' => null]));
     return $this;
   }
 
diff --git a/library/ZendAfi/Form/Admin/SearchUsers.php b/library/ZendAfi/Form/Admin/SearchUsers.php
new file mode 100644
index 0000000000000000000000000000000000000000..f45d3c5addc4254975854a7fa9fa1395ab847e8b
--- /dev/null
+++ b/library/ZendAfi/Form/Admin/SearchUsers.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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 ZendAfi_Form_Admin_SearchUsers extends ZendAfi_Form {
+
+  public static function newWith($datas = [], $custom_form = null) {
+    $form = (new static());
+
+    $form
+      ->setAttributes()
+      ->addElements()
+      ->populate($datas);
+
+    return $form;
+  }
+
+
+  public function setAttributes() {
+    return $this
+      ->setAction(Class_Url::absolute(['module' => 'admin',
+                                       'controller' => 'users',
+                                       'action' => 'index'], null, true))
+      ->setAttrib('style', 'position: relative')
+      ->setMethod('get');
+  }
+
+
+  public function addElements() {
+    return $this
+      ->addElement('select',
+                   'by_id_site',
+                   ['label' => $this->_('Bibliothèque'),
+                    'multiOptions' => ['all' => $this->_('Toutes')] + Class_Bib::findAllLabels()])
+
+      ->addElement('select',
+                   'by_role_level',
+                   ['label' => $this->_('Niveau d\'accès'),
+                    'multiOptions' => ['all' => $this->_('Tous')] + ZendAfi_Acl_AdminControllerRoles::getRolesLabelsWithOutSuperAdmin()])
+
+      ->addElement('checkbox',
+                   'by_valide_subscription',
+                   ['label' => $this->_('Abonnement valide')])
+
+      ->addElement('text',
+                   'search_for',
+                   ['label' => $this->_('Rechercher')])
+
+      ->addDisplayGroup(['by_id_site',
+                         'by_role_level',
+                         'by_valide_subscription',
+                         'search_for',
+                         'submit_form'],
+                        'search_group',
+                        ['legend' => $this->_('Recherche')]);
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/Form/Admin/User.php b/library/ZendAfi/Form/Admin/User.php
index 5d87321eea16eafc70c6ebf832e6040039a3ec58..f4479ee3ad0b8fbe8bb159ced329da72ee2497cb 100644
--- a/library/ZendAfi/Form/Admin/User.php
+++ b/library/ZendAfi/Form/Admin/User.php
@@ -128,7 +128,7 @@ class ZendAfi_Form_Admin_User extends ZendAfi_Form {
                    'id_site',
                    array_merge(
                                ['label' => $this->_('Bibliothèque'),
-                                'multiOptions' => array_merge(['0' => $this->_('Portail')], Class_Bib::findAllLabels())],
+                                'multiOptions' => ['0' => $this->_('Portail')] + Class_Bib::findAllLabels()],
                                $option))
 
       ->addElement('userGroup',
@@ -260,7 +260,7 @@ class ZendAfi_Form_Admin_User extends ZendAfi_Form {
 
     $user_library = $this->_user->getRedmineLibrary();
     $value = $user_library ? $user_library->getId() : 0;
-    $options = $this->_getLibraries();
+    $options = ['0' => $this->_('Aucune')] + Class_Bib::findAllLabels();
     $this
       ->addElement('select',
                    'redmine_library',
@@ -282,11 +282,5 @@ class ZendAfi_Form_Admin_User extends ZendAfi_Form {
                                     'library' => $user_library]);
     return $this;
   }
-
-
-  protected function _getLibraries() {
-    return array_merge(['0' => $this->_('Aucune')],
-                       Class_Bib::findAllLabels());
-  }
 }
 ?>
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/Admin/SearchUsers.php b/library/ZendAfi/View/Helper/Admin/SearchUsers.php
new file mode 100644
index 0000000000000000000000000000000000000000..0a8323578df527faa1ec10ebef55aa314b4bfc45
--- /dev/null
+++ b/library/ZendAfi/View/Helper/Admin/SearchUsers.php
@@ -0,0 +1,123 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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 ZendAfi_View_Helper_Admin_SearchUsers extends ZendAfi_View_Helper_BaseHelper {
+
+  protected $placeholder = 'PLACEHOLDER_ID_USER',
+    $users,
+    $total,
+    $params;
+
+  public function admin_searchUsers($users, $total, $form, $page, $params) {
+    Class_ScriptLoader::getInstance()->addJQueryReady('$("#by_role_level option[value=2]:not(:selected)").closest("form").find("tr:nth-child(3)").hide();$("#by_role_level").change(function() {$("#by_role_level option[value=2]:not(:selected)").closest("form").find("tr:nth-child(3)").hide();$("#by_role_level option[value=2]:selected").closest("form").find("tr:nth-child(3)").show();});');
+
+    $this->users = $users;
+    $this->total = $total;
+    $this->page = $page;
+    $this->params = $params;
+
+    return $this->_addButton() .
+      $this->view->renderForm($form) .
+      $this->view->tag('p', $this->view->_plural($this->total,
+                                                 'Auncun utilisateur trouvé',
+                                                 '%d utilisateur trouvé',
+                                                 '%d utilisateurs trouvés',
+                                                 $this->total)) .
+      $this->_getUsersTable();
+  }
+
+
+  protected function _addButton() {
+    return Class_Users::getIdentity()->isAdmin()
+      ? ($this->view->tag('center',
+                          $this->view->tag('div',
+                                           $this->view->bouton('id=19',
+                                                               'picto=add.gif',
+                                                               'texte='.$this->view->_('Ajouter un utilisateur'),
+                                                               'url='. $this->view->url(['action'=> 'add']),
+                                                               'largeur=210px'))))
+      : '';
+  }
+
+
+  protected function _getUsersTable() {
+    $pager = $this->view->Pager($this->total,
+                                20,
+                                $this->page,
+                                array_merge($this->params, ['page' => null]));
+
+    return $pager
+      . $this->_getTable()
+      . $pager;
+  }
+
+
+  protected function _getTable() {
+    $acl = new ZendAfi_Acl_AdminControllerRoles();
+
+    $role_renderer = function($model) use($acl){
+      return $acl->getLibelleRole($model->getRoleLevel());
+    };
+
+    $library_renderer = function($model) {
+      return $model->getLibelleBib();
+    };
+
+    $tag_edit = $this->view->tagAnchor($this->view->url(array_merge(['module' => 'admin',
+                                                                     'controller' => 'users',
+                                                                     'action' => 'edit',
+                                                                     'id' => $this->placeholder], $this->params)),
+                                       $this->view->boutonIco('type=edit'));
+
+    $tag_delete = $this->view->tagAnchor($this->view->url(array_merge(['module' => 'admin',
+                                                                       'controller' => 'users',
+                                                                       'action' => 'delete',
+                                                                       'id' => $this->placeholder], $this->params)),
+                                         $this->view->boutonIco('type=del'));
+
+    $actions = function($user) use($tag_edit, $tag_delete){
+      if(!Class_Users::getIdentity()->isAdmin())
+        return;
+
+      return str_replace($this->placeholder, $user->getId(), $tag_edit)
+      . str_replace($this->placeholder, $user->getId(), $tag_delete);
+    };
+
+    return $this->view->tagModelTable($this->users,
+                                      [$this->view->_('Identifiant'),
+                                       $this->view->_('Nom'),
+                                       $this->view->_('Prenom'),
+                                       $this->view->_('Role'),
+                                       $this->view->_('Bibliothèque')],
+                                      ['login',
+                                       'nom',
+                                       'prenom',
+                                       'role_level',
+                                       'library'],
+                                      [ $actions ],
+                                      null,
+                                      null,
+                                      ['role_level' => $role_renderer,
+                                       'library' => $library_renderer]);
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/Article/RenderAbstract.php b/library/ZendAfi/View/Helper/Article/RenderAbstract.php
index 72db49674a06d6fd35819b8ce4379610046cacf4..cc1567ef9105c1f82aace52566c4eda6ab776d7a 100644
--- a/library/ZendAfi/View/Helper/Article/RenderAbstract.php
+++ b/library/ZendAfi/View/Helper/Article/RenderAbstract.php
@@ -112,14 +112,7 @@ abstract class ZendAfi_View_Helper_Article_RenderAbstract extends ZendAfi_View_H
 
 
   public function renderReseauxSociaux($article) {
-    $url_reseau = $this->view->url(['controller'  => 'cms',
-                                    'action'      => 'reseau',
-                                    'id_article'  => $article->getId()], null, true);
-
-    return
-      '<div class="reseaux-sociaux" data-article-url="'.$url_reseau.'">'
-      .$this->view->tagImg(URL_IMG . 'patience.gif')
-      .'</div>';
+    return $this->view->reseauxSociaux($article);
   }
 
 
diff --git a/library/ZendAfi/View/Helper/Avis.php b/library/ZendAfi/View/Helper/Avis.php
index e13c8854fdf018a2ef04e5025d1e5d3cb8452ddf..048fcb0a6b0adf940601d84c11bb6b301eb4f854 100644
--- a/library/ZendAfi/View/Helper/Avis.php
+++ b/library/ZendAfi/View/Helper/Avis.php
@@ -25,6 +25,8 @@ class ZendAfi_View_Helper_Avis extends ZendAfi_View_Helper_BaseHelper {
   protected $_actions = [];
   protected $_admin_actions = [];
   protected $_url_context = [];
+  protected $_active_tab = 0;
+  protected $_page = 0;
 
   public function setVignetteLinkToAvis() {
     $this->_vignette_link_to_avis = true;
@@ -43,6 +45,16 @@ class ZendAfi_View_Helper_Avis extends ZendAfi_View_Helper_BaseHelper {
   }
 
 
+  public function setActiveTab($active_tab) {
+    $this->_active_tab = $active_tab;
+  }
+
+
+  public function setPage($page) {
+    $this->_page = $page;
+  }
+
+
   public function setAdminActions($actions) {
     $this->_admin_actions = $actions;
     return $this;
@@ -220,8 +232,11 @@ class ZendAfi_View_Helper_Avis extends ZendAfi_View_Helper_BaseHelper {
     $suffix = ($avis->isAvisNotice()) ? 'avisnotice' : '-aviscms';
     foreach($this->_actions as $action) {
       $link = $this->view->tagAnchor($this->_url(['action' => $action . $suffix,
-                                                  'id' => $avis->getId()]),
+                                                  'id' => $avis->getId(),
+                                                  'active_tab' => $this->_active_tab,
+                                                  'page' => $this->_page]),
                                      $this->view->boutonIco('type=' . $action));
+
       $html_actions .= $this->_tag('span', $link, ['rel' => $action]);
     }
 
@@ -237,11 +252,12 @@ class ZendAfi_View_Helper_Avis extends ZendAfi_View_Helper_BaseHelper {
 
   protected function _getAdminActionsTag($avis) {
     $html_actions = '';
-
     foreach($this->_admin_actions as $action) {
       $link = $this->view->tagAnchor($this->_url(['controller' => 'abonne',
                                                   'action' => $action . 'avisnotice',
-                                                  'id' => $avis->getId()]),
+                                                  'id' => $avis->getId(),
+                                                  'active_tab' => $this->_active_tab,
+                                                  'page' => $this->_page]),
                                      $this->view->boutonIco('type=' .$action),
                                      ['data-popup' => 'true']);
       $html_actions .= $this->_tag('span', $link, ['rel' => $action]);
diff --git a/library/ZendAfi/View/Helper/AvisBloc.php b/library/ZendAfi/View/Helper/AvisBloc.php
index 22ee7bf9ff49dbd6145d58f54fb9bf49b4b0665a..19361663327d357364ef23af531e600d117555c4 100644
--- a/library/ZendAfi/View/Helper/AvisBloc.php
+++ b/library/ZendAfi/View/Helper/AvisBloc.php
@@ -43,13 +43,33 @@ class ZendAfi_View_Helper_AvisBloc extends Zend_View_Helper_HtmlElement {
   protected function renderBlock() {
     if(!count($this->_list))
       return $this->view->tag('p',
-                              $this->view->_('Aucun avis %s à modérer.', ($this->_label ? $this->_label : '')),
+                              $this->view->_('Aucun avis %s à modérer.',
+                                             ($this->_label ? $this->_label : '')),
                               ['class' => 'error']);
 
-    return $this->injectPager($this->view->partialCycle('modo/_avis_partial.phtml',
-                                                              'avis',
-                                                              $this->_list,
-                                                              ['first', 'second']));
+    $html = '';
+    foreach ($this->_list as $avis)
+      $html .= $this->_renderAvis($avis);
+
+    return $this->injectPager($html);
+  }
+
+
+  protected function _renderAvis($avis) {
+    $actions = ['validate', 'edit', 'del'];
+    if ($avis->getFlags() >= 0)
+      $actions[] = ($avis->getFlags() == 0) ? 'invisible' : 'visible';
+
+    $helper = $this->view->getHelper('avis');
+
+    $helper->setActions($actions);
+    $helper->setActiveTab($this->_index);
+    $helper->setPage($this->_page);
+
+    $html = $this->view->avis($avis) .
+      $this->view->tag('div', '', ['class' => 'clear']);
+
+    return $this->view->tag('div', $html);
   }
 
 
diff --git a/library/ZendAfi/View/Helper/Calendar/Table.php b/library/ZendAfi/View/Helper/Calendar/Table.php
index 6b6a5faa41877ba441117bdd747474937cbefa62..c1689d8b8deccacf6b6bddbb77c1976954d5177a 100644
--- a/library/ZendAfi/View/Helper/Calendar/Table.php
+++ b/library/ZendAfi/View/Helper/Calendar/Table.php
@@ -213,17 +213,18 @@ class ZendAfi_View_Helper_Calendar_Table extends ZendAfi_View_Helper_BaseHelper
 
 
   protected function getTableCalendarHeader() {
-    $anchor_class = ['class' => 'calendar_title_month_clickable'];
-    $anchor_class['class'] .= $this->param['DISPLAY_FULL_PAGE']  ? '' : ' calendar_ajax_ready';
 
-    $previous = $this->view->tagAnchor($this->getUrl('LAST_MONTH'), '&laquo;&nbsp;', $anchor_class);
+    $attribs['class'] = implode(' ', array_filter(['calendar_title_month_clickable',
+                                                   $this->_getAjaxClass()]));
 
-    $current = $this->view
-      ->tagAnchor($this->getUrl('MONTH'),
-                  $this->MONTHS[$this->month-1] . strftime(' %Y', mktime(5,0,0, $this->month, 1, $this->year)),
-                  $anchor_class);
+    $next = $this->view->tagAnchor($this->getUrl('NEXT_MONTH'), '&nbsp;&raquo;', $attribs);
+    $previous = $this->view->tagAnchor($this->getUrl('LAST_MONTH'), '&laquo;&nbsp;', $attribs);
+
+    $current = $this->view->tagAnchor($this->getUrl('MONTH'),
+                                      $this->MONTHS[$this->month-1] .
+                                      strftime(' %Y', mktime(5,0,0, $this->month, 1, $this->year)),
+                                      $attribs);
 
-    $next = $this->view->tagAnchor($this->getUrl('NEXT_MONTH'), '&nbsp;&raquo;', $anchor_class);
 
     return $this->_tag('tr',
                        $this->_tag('td', '', ['class' => 'calendar_title_left_arrow'])
@@ -234,6 +235,11 @@ class ZendAfi_View_Helper_Calendar_Table extends ZendAfi_View_Helper_BaseHelper
   }
 
 
+  protected function _getAjaxClass() {
+    return (1 == $this->param['DISPLAY_FULL_PAGE']) ? '' : ' calendar_ajax_ready';
+  }
+
+
   protected function buildUrl($url = []) {
     if ($this->param['DISPLAY_FULL_PAGE'])
       return $url;
@@ -322,8 +328,7 @@ class ZendAfi_View_Helper_Calendar_Table extends ZendAfi_View_Helper_BaseHelper
       return $this->_tag('span', $day,
                          ['class' => implode(' ', $classes)]);
 
-    if ($this->param['DISPLAY_FULL_PAGE'])
-      $classes[] = 'calendar_ajax_ready';
+    $classes[] = $this->_getAjaxClass();
 
     return $this->view
       ->tagAnchor($this->getUrl('EVENTS', $day, $month),
diff --git a/library/ZendAfi/View/Helper/CosmoError.php b/library/ZendAfi/View/Helper/CosmoError.php
new file mode 100644
index 0000000000000000000000000000000000000000..ef94d80d5c430b3cbd5dfb1f0e6c544742d2aeea
--- /dev/null
+++ b/library/ZendAfi/View/Helper/CosmoError.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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 ZendAfi_View_Helper_CosmoError extends ZendAfi_View_Helper_BaseHelper {
+  public function cosmoError($message) {
+    return $this->_tag('br').$this->_tag('br')
+      . $this->_tag('center', $this->_tag('font', $message, ['size' => '5', 'color' => 'red']))
+      . $this->_tag('br').$this->_tag('br');
+  }
+}
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/FonctionsAdmin.php b/library/ZendAfi/View/Helper/FonctionsAdmin.php
index adbf04a365c98796f4b421b675b31ebc8480f9c6..06db21bde5ac04bdde17ebf629a9d19ddb2234b4 100644
--- a/library/ZendAfi/View/Helper/FonctionsAdmin.php
+++ b/library/ZendAfi/View/Helper/FonctionsAdmin.php
@@ -111,11 +111,12 @@ class ZendAfi_View_Helper_FonctionsAdmin extends ZendAfi_View_Helper_BaseHelper
 
     $onclick = "return confirm('". htmlspecialchars($this->_('Êtes-vous sur de vouloir supprimer cette boîte ?')) . "');";
 
-
     $img = $this->_current_skin->renderActionIconOn('delete', $this->view,
-                                                    ['onclick' => $onclick,
-                                                     'alt' => $label,
+                                                    ['alt' => $label,
                                                      'title' => $label]);
-    return $this->_tag('a', $img, ['href' => $url]);
+    return $this->_tag('a',
+                       $img,
+                       ['href' => $url,
+                        'onclick' => $onclick]);
   }
 }
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/Notice/FacettesTypeDoc.php b/library/ZendAfi/View/Helper/Notice/FacettesTypeDoc.php
index fa3580a29fa3c3caa170a7d477c9d8fccef78726..90207bbe38d84425571bb16e9ccc4aa372817ac8 100644
--- a/library/ZendAfi/View/Helper/Notice/FacettesTypeDoc.php
+++ b/library/ZendAfi/View/Helper/Notice/FacettesTypeDoc.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
  */
 class ZendAfi_View_Helper_Notice_FacettesTypeDoc extends Zend_View_Helper_HtmlElement {
   public function notice_FacettesTypeDoc($facettes) {
@@ -26,10 +26,10 @@ class ZendAfi_View_Helper_Notice_FacettesTypeDoc extends Zend_View_Helper_HtmlEl
     if (!isset($facettes['T']))
       $facettes['T'] = [];
 
-    foreach($facettes['T'] as $facette) {
-      if (!is_array($facette))
-        continue;
-      $html .= $this->renderFacette($facette['id'], $facette['libelle'], $facette['nombre']);
+    foreach($facettes['T'] as $code => $value) {
+      $label = Class_Codification::getInstance()->getLibelleFacette($code);
+
+      $html .= $this->renderFacette($code, $label, $value);
     }
 
     return $html.'</div>';
@@ -37,7 +37,7 @@ class ZendAfi_View_Helper_Notice_FacettesTypeDoc extends Zend_View_Helper_HtmlEl
 
 
   public function renderFacette($id, $libelle, $nombre) {
-    return $this->view->tagAnchor(['facette' => $id], $nombre, 
+    return $this->view->tagAnchor(['facette' => $id], $nombre,
                                   ['class' => 'type_doc_'.substr($id, 1 ),
                                    'libelle' => $libelle]);
   }
diff --git a/library/ZendAfi/View/Helper/Permalink.php b/library/ZendAfi/View/Helper/Permalink.php
index 30ab3c2152bff245323117325869289de5245137..e1a300254b195b36d327f7a877297da2ea60f6fc 100644
--- a/library/ZendAfi/View/Helper/Permalink.php
+++ b/library/ZendAfi/View/Helper/Permalink.php
@@ -26,22 +26,15 @@ class ZendAfi_View_Helper_Permalink extends ZendAfi_View_Helper_BaseHelper {
       ? $profil->getUrlImage($icon)
       : Class_Admin_Skin::current()->renderIconUrlOn('actions', 'permalink');
 
-    $lien_permanent = $this->translate()->_('Lien permanent');
-    $html = $this->view->tagImgHover($icon_url,
-                                     ['class' => 'permalien-img',
-                                      'title' => $lien_permanent,
-                                      'alt' => $lien_permanent,
-                                      'onclick' => '$(this).next().children().first().toggle()']);
+    $lien_permanent = $this->view->_('Lien permanent');
 
-    $html .= '<div><div style="display:none; z-index: 101;">';
-    $html .= '<div>' . $lien_permanent . '</div>';
-    $html .= '<div>' .
-      '<a href="#" onclick="$(this).parent().parent().hide(); return false">&raquo;&nbsp;' . $this->translate()->_('fermer cette fenêtre') . '</a>'.
-      '</div>';
-    $html .= $this->view->tag('span', $url, ['class' => 'permalink-url']);
-    $html .='</div></div>';
-
-    return $html;
+    return $this->view->tagImgHover($icon_url,
+                                    ['class' => 'permalink permalien-img', //permalien-img kept for previous skins compatibility
+                                     'alt' => $lien_permanent,
+                                     'title' => $lien_permanent,
+                                     'data-url' => $url,
+                                     'data-helptext' => $this->view->_('Copiez le lien suivant'),
+                                     'onclick' => 'popupPermalink(this)']);
   }
 }
 
diff --git a/library/ZendAfi/View/Helper/ReseauxSociaux.php b/library/ZendAfi/View/Helper/ReseauxSociaux.php
index 2bf203965e0b890a2f396e8902646e3886663307..a542741447002e62506d537c7c059667fc1a4098 100644
--- a/library/ZendAfi/View/Helper/ReseauxSociaux.php
+++ b/library/ZendAfi/View/Helper/ReseauxSociaux.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
  */
 
 class ZendAfi_View_Helper_ReseauxSociaux extends ZendAfi_View_Helper_BaseHelper {
@@ -32,16 +32,14 @@ class ZendAfi_View_Helper_ReseauxSociaux extends ZendAfi_View_Helper_BaseHelper
 
     if (!$article_or_notice_or_profil)
       return '';
-    
+
     return $article_or_notice_or_profil->renderOn($this);
 
   }
 
 
   public function renderArticle($article) {
-    $id_profil = Class_Profil::getCurrentProfil()->getId();
-    
-    return $this->links(['url_to_share'=>$this->view->url($article->getUrl()).'?id_profil='.$id_profil,
+    return $this->links(['url_to_share'=>$this->view->url($article->getUrl()).'?id_profil=' . Class_Profil::getCurrentProfil()->getId(),
                          'titre' => $article->getTitre(),
                          'message' => 'article',
                          'img_url' => $article->getFirstImageURL()]);
@@ -50,14 +48,14 @@ class ZendAfi_View_Helper_ReseauxSociaux extends ZendAfi_View_Helper_BaseHelper
 
   public function renderNotice($notice) {
     $id_profil = Class_Profil::getCurrentProfil()->getId();
-    
+
     return $this->links(['url_to_share'=>$this->view->urlNotice($notice).'?id_profil='.$id_profil,
                          'titre' => $notice->getTitreEtSousTitre().' - '.$notice->getAuteurPrincipal(),
                          'message' => $notice->getResume(),
                          'img_url' => $notice->getUrlVignette()]);
   }
 
-  
+
   public function renderProfil($profil) {
     return $this->headerLinks(['url_to_share'=>Zend_Controller_Front::getInstance()->getBaseUrl(),
                                'titre' => $profil->getTitreSite(),
@@ -67,14 +65,14 @@ class ZendAfi_View_Helper_ReseauxSociaux extends ZendAfi_View_Helper_BaseHelper
 
 
   public function links($info_to_share) {
-    $html='<div class="vignette-reseaux-sociaux">';
-    $html.= $this->shareLinkHtml($info_to_share);
+    $html='<div class="vignette-reseaux-sociaux reseaux-sociaux">';
+    $html.= $this->shareLinkHtmlHeader($info_to_share);
     $html.= $this->view->permalink($this->view->absoluteUrl($info_to_share['url_to_share']));
     $html.='</div>';
     return $html;
   }
 
-  
+
   public function headerLinks($info_to_share){
     $html= '<div class="share">';
     $html.= $this->shareLinkHtmlHeader($info_to_share);
@@ -83,11 +81,11 @@ class ZendAfi_View_Helper_ReseauxSociaux extends ZendAfi_View_Helper_BaseHelper
     return $html.= '</div>';
   }
 
-  
+
   public function shareLinkHtml($info) {
     $html = '';
     foreach($this->reseaux as $clef => $reseau) {
-      $html.= $this->shareLinkImgHtml($clef, 
+      $html.= $this->shareLinkImgHtml($clef,
                                       array_merge($this->shareLinkUrlTable($clef,$info),
                                                   $this->getShareIco($clef)));
     }
@@ -119,7 +117,7 @@ class ZendAfi_View_Helper_ReseauxSociaux extends ZendAfi_View_Helper_BaseHelper
     return $html.='<script type="text/javascript">$(function(){initializeImgHover()});</script>';
   }
 
-  
+
   public function shareLinkUrlTable($clef,$info){
     return ['on' => $clef,
             'url' => urlencode($info['url_to_share']),
@@ -133,8 +131,8 @@ class ZendAfi_View_Helper_ReseauxSociaux extends ZendAfi_View_Helper_BaseHelper
   public function getScriptFromController($url_table){
     return $this->view->url(['controller' => 'social-network',
                              'action' => 'share',
-                             'on' =>$url_table['on'], 
-                             'url' => $url_table['url'], 
+                             'on' =>$url_table['on'],
+                             'url' => $url_table['url'],
                              'titre' => $url_table['titre'],
                              'message'=> $url_table['message'],
                              'img_url' => $url_table['img_url']]);
diff --git a/library/ZendAfi/View/Helper/ShareUrl.php b/library/ZendAfi/View/Helper/ShareUrl.php
index a26b638a81213b7f0a469a43dd538cc2ca3ce3dc..2f08b61f2d2cd1eddb634df48fe61fd079d1bbcd 100644
--- a/library/ZendAfi/View/Helper/ShareUrl.php
+++ b/library/ZendAfi/View/Helper/ShareUrl.php
@@ -24,11 +24,7 @@ class ZendAfi_View_Helper_ShareUrl extends Zend_View_Helper_HtmlElement {
   protected $reseaux=["facebook" => ["url" => "https://www.facebook.com/sharer/sharer.php"],
                       "twitter"  => ["url" => "http://twitter.com/share?"]];
 
-  protected $url_shortener="http://is.gd/api.php?longurl=";         // Url pour obtenir une une url courte
 
-  //------------------------------------------------------------------------------------------------------
-  // Rend la structure
-  //------------------------------------------------------------------------------------------------------
   public function getReseaux($id_reseau=false)  {
     if($id_reseau)
       return $this->reseaux[$id_reseau];
@@ -37,9 +33,7 @@ class ZendAfi_View_Helper_ShareUrl extends Zend_View_Helper_HtmlElement {
   }
 
 
-  //------------------------------------------------------------------------------------------------------
-  // Rend l'url a passer en parametre
-  //------------------------------------------------------------------------------------------------------
+
   public function shareUrl($id_reseau,$url_afi,$titre= '', $message = '', $url_img = '')  {
     $url_afi = $this->view->absoluteUrl(urldecode($url_afi));
 
@@ -49,37 +43,13 @@ class ZendAfi_View_Helper_ShareUrl extends Zend_View_Helper_HtmlElement {
 
     if($id_reseau==='twitter')
       return $this->reseaux[$id_reseau]["url"].
-        $this->getTwitterUrl($this->shortenUrl($url_afi),
+        $this->getTwitterUrl($url_afi,
                              $titre,
                              $message);
   }
 
 
-  public function shortenUrl($original_url) {
-    $short_url = self::getDefaultWebClient()->open_url($this->url_shortener.urlencode($original_url));
-    if (!$short_url or substr($short_url,0,5)=="Error")
-      return $original_url;
-    return $short_url;
-  }
-
-
-  static public function getDefaultWebClient() {
-    if (!isset(self::$_web_client))
-      self::$_web_client = new Class_WebService_SimpleWebClient();
-    return self::$_web_client;
-  }
-
-
-  static public function setDefaultWebClient($web_client) {
-    self::$_web_client = $web_client;
-  }
-
-  static public function resetDefaultWebClient() {
-    self::$_web_client = null;
-  }
-
   public function getTwitterUrl($url_afi, $titre, $message) {
-
     return http_build_query(['url' => $url_afi,
                              'text' => $titre,
                              'counturl' => $url_afi],
diff --git a/library/ZendAfi/View/Helper/TagOneDTouch.php b/library/ZendAfi/View/Helper/TagOneDTouch.php
index 195ee426e26e22d8d3960baa660e60b5e36e7858..32f4b55383bb6bc7898d5d6008cdda314ca8cf58 100644
--- a/library/ZendAfi/View/Helper/TagOneDTouch.php
+++ b/library/ZendAfi/View/Helper/TagOneDTouch.php
@@ -24,7 +24,7 @@ class ZendAfi_View_Helper_TagOneDTouch extends ZendAfi_View_Helper_BaseHelper {
   public function tagOneDTouch($album) {
     return $this->_tag('a',
                        $this->_('Écouter l\'album sur 1DTouch'),
-                       ['href' => Class_OneDTouchLink::urlFor($album)]);
+                       ['href' => (new Class_OneDTouchLink())->urlFor($album)]);
   }
 }
 ?>
\ No newline at end of file
diff --git a/library/startup.php b/library/startup.php
index b729a09e260695537ba7e17b9f137f4a1e91f4d2..0a86439b609cb7bdcc0d6ce64e8145dc61d6caa3 100644
--- a/library/startup.php
+++ b/library/startup.php
@@ -64,7 +64,8 @@ function defineConstant($name, $value) {
 
 function setupConstants() {
   defineConstant('BOKEH_MAJOR_VERSION','7.5');
-  defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.4');
+
+  defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.8');
 
   defineConstant('BOKEH_REMOTE_FILES', 'http://git.afi-sa.fr/afi/opacce/');
 
diff --git a/public/admin/css/global.css b/public/admin/css/global.css
index e5feae98fda304759ca655d6f3a9106b05e2edd9..f022ca1329ef16f3e6bca91bca3dd4272a7ee67b 100644
--- a/public/admin/css/global.css
+++ b/public/admin/css/global.css
@@ -1335,6 +1335,10 @@ div#reader {
     background-color: red;
 }
 
+.redmine_edit-issue .models td {
+    max-width: 285px;
+}
+
 .redmine_status.redmine_green {
     background-color: green;
 }
diff --git a/public/admin/js/onload_utils.js b/public/admin/js/onload_utils.js
index 4637978cc0e3d562e587e36d725e8544beda91d5..41a04fb58a15344e2580d200a6d15b57deffaea8 100644
--- a/public/admin/js/onload_utils.js
+++ b/public/admin/js/onload_utils.js
@@ -77,9 +77,9 @@ var autoHideShowConfigurationModule = function() {
   autoHideShowTagOnParentHover('.select_kiosque_form', 'div.boite');
   autoHideShowTagOnParentHover('.edit_menu', '#menu_horizontal');
   autoHideShowTagOnParentHover('.newsadd', 'div.boite');
-
 }
 
+
 var autoHideShowTagOnParentHover = function (child_selector, parent_selector) {
   hide_selector = parent_selector + ' ' + child_selector;
   $(hide_selector).hide();
@@ -114,12 +114,11 @@ var initializeImgHover = function() {
 }
 
 
-
-var initializeReseauxSociaux = function() {
-	$('.reseaux-sociaux[data-article-url]').each(
-		function(index,element) {
-			$element = $(element);
-			$element.load($element.attr('data-article-url'));
-		}
-	);
+var popupPermalink = function(link) {
+  var link = $(link);
+  $("<div title='" + link.attr("title") + "'>"
+    + "<p>" + link.attr("data-helptext") + "</p>"
+    + "<input type='url' style='width:100%' value='" + link.attr("data-url") + "' readonly>"
+    + "</div>"
+   ).dialog({width:500, height:150});
 }
diff --git a/public/admin/skins/bokeh74/global.css b/public/admin/skins/bokeh74/global.css
index 6238835bb276bc31182aadbcd65110cea732d05a..e02e116e39bd237e0e5e3bdb3a621115b40756c3 100755
--- a/public/admin/skins/bokeh74/global.css
+++ b/public/admin/skins/bokeh74/global.css
@@ -212,6 +212,14 @@ table#suggestions td:last-child a {
     margin-left: 5px;
 } 
 
+.modules table.models td > a img {
+    margin-right: 5px;
+}
+
+.modules table.models td > .actions {
+    min-width: 100px;
+}
+
 .treeView .ui-accordion .ui-accordion-content {
     padding-top: 0.5em;
 }
@@ -250,6 +258,7 @@ table#suggestions td:last-child a {
 
 .main > .left .menuAdmin li {
     white-space: nowrap;
+    position: relative;
 }
 
 .main > .left img {
@@ -320,6 +329,8 @@ table {
 .left table li span {
     float: right;
     line-height: 2em;
+    position: absolute;
+    right: 0;
 }
 
 .modules {
diff --git a/public/admin/skins/retro/global.css b/public/admin/skins/retro/global.css
index d60bc84fd9ee3b33e25c8a9fbda422587fd3689e..e9850d7828178a43a1098d0addfc437c4a1890e0 100755
--- a/public/admin/skins/retro/global.css
+++ b/public/admin/skins/retro/global.css
@@ -213,7 +213,10 @@ li {
     width: 70%;
 }
 
-.modules .tree .actions a {
+.actions a,
+.actions > img,
+.treeMenu div[align=right] a,
+table#suggestions td:last-child a {
     margin-left: 5px;
 }
 
@@ -221,6 +224,23 @@ li {
     margin-left: 5px;
 } 
 
+.modules table.models td > a img {
+    margin-right: 5px;
+}
+
+.modules table.models td > .actions {
+    min-width: 100px;
+}
+
+.treeView .ui-accordion .ui-accordion-content {
+    padding-top: 0.5em;
+}
+
+.treeView .root {
+    margin-top: 20px;
+    padding-left: 20px;
+}
+
 .modules img.ico,
 .tree .actions img {
     height: 16px;
@@ -249,6 +269,7 @@ li {
 
 .main > .left .menuAdmin li {
     white-space: nowrap;
+    position: relative;
 }
 
 .main > .left img {
@@ -319,6 +340,8 @@ table {
 .left table li span {
     float: right;
     line-height: 2em;
+    position: absolute;
+    right: 0;
 }
 
 .modules {
diff --git a/public/opac/css/global.css b/public/opac/css/global.css
index a135885ca9e941d5a14369d8869ad3eca6160621..35e4ae22dd71ae8ac657e011258180005a405f18 100644
--- a/public/opac/css/global.css
+++ b/public/opac/css/global.css
@@ -103,6 +103,10 @@ form.login fieldset {
     display:none;
 }
 
+.vignette-reseaux-sociaux img {
+    width: 16px;
+}
+
 #boite_login input#login {
     display: none;
 }
@@ -2269,7 +2273,6 @@ button.vodeclic_link + img {
     float:left;
 }
 
-.permalink-url,
 .embed-code-to-copy {
     margin:5px;
     border:1px solid #C8C8C8;
diff --git a/public/opac/js/calendrier.js b/public/opac/js/calendrier.js
index 1fd15d79981734fc4456b2c9ea92bc9487684c21..9da8ae5fcc9472ca8f8b032854b1bb6c6b6148bb 100644
--- a/public/opac/js/calendrier.js
+++ b/public/opac/js/calendrier.js
@@ -48,7 +48,6 @@ var ajaxify_calendars = function () {
 
   if (typeof jQuery != "undefined") {
     $(document).ready(resize_func);
-    $(document).ready(initializeReseauxSociaux());
   }
 
   initializePopups();
diff --git a/tests/application/modules/AbstractControllerTestCase.php b/tests/application/modules/AbstractControllerTestCase.php
index 29948e1cf7b1202303957c4c4b52d0fd75185c8d..0a03f2d15a8abb893b17d9c51eaf5b6e564ed052 100644
--- a/tests/application/modules/AbstractControllerTestCase.php
+++ b/tests/application/modules/AbstractControllerTestCase.php
@@ -20,6 +20,7 @@
  */
 abstract class AbstractControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase {
   use Storm_Test_THelpers;
+
   protected
     $_registry_sql,
     $_storm_default_to_volatile = false;
@@ -306,6 +307,22 @@ abstract class AbstractControllerTestCase extends Zend_Test_PHPUnit_ControllerTe
         $this->fail("Flash messenger contains a popup");
     }
   }
+
+
+
+  public function xhprofile($closure) {
+    xhprof_enable();
+
+    $closure();
+
+    $xhprof_data = xhprof_disable();
+    require_once "xhprof/xhprof_lib/utils/xhprof_lib.php";
+    require_once "xhprof/xhprof_lib/utils/xhprof_runs.php";
+
+    $xhprof_runs = new XHProfRuns_Default();
+    $run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_testing");
+    var_dump('XHProfile data: ' . BASE_URL."/xhprof/xhprof_html/index.php?run={$run_id}&source=xhprof_testing");
+  }
 }
 
 ?>
\ No newline at end of file
diff --git a/tests/application/modules/admin/controllers/AdminAvisModerationControllerTest.php b/tests/application/modules/admin/controllers/AdminAvisModerationControllerTest.php
index 25a0cf157d6fdc1f3241a4c7c285e1f600f43711..3cbedea6db63b24887a68ca650206547b7342b85 100644
--- a/tests/application/modules/admin/controllers/AdminAvisModerationControllerTest.php
+++ b/tests/application/modules/admin/controllers/AdminAvisModerationControllerTest.php
@@ -103,23 +103,23 @@ class AdminAvisModerationControllerAvisToModerateTest extends AdminAvisModeratio
   }
 
   public function testClubCinqLinkValidate() {
-    $this->assertXPath("//a[@href='/admin/modo/validateavisnotice/id/38']");
+    $this->assertXPath("//a[@href='/admin/modo/validateavisnotice/id/38/active_tab/1/page/0']");
   }
 
   public function testRoutardLinkValidate() {
-    $this->assertXPath("//a[@href='/admin/modo/validateavisnotice/id/42']");
+    $this->assertXPath("//a[@href='/admin/modo/validateavisnotice/id/42/active_tab/1/page/0']");
   }
 
   public function testClubCinqLinkDel() {
-    $this->assertXPath("//a[@href='/admin/modo/delavisnotice/id/38']");
+    $this->assertXPath("//a[@href='/admin/modo/delavisnotice/id/38/active_tab/1/page/0']");
   }
 
   public function testRoutardLinkDel() {
-    $this->assertXPath("//a[@href='/admin/modo/delavisnotice/id/42']");
+    $this->assertXPath("//a[@href='/admin/modo/delavisnotice/id/42/active_tab/1/page/0']");
   }
 
   public function testClubCinqLinkEdit() {
-    $this->assertXPath("//a[@href='/admin/modo/editavisnotice/id/42']");
+    $this->assertXPath("//a[@href='/admin/modo/editavisnotice/id/42/active_tab/1/page/0']");
   }
 }
 
@@ -150,7 +150,7 @@ class AdminAvisModerationControllerUnknownAvisEditTest extends AdminAvisModerati
   }
 
   public function testRedirectToAvisPage() {
-    $this->assertRedirectTo('/admin/modo/avisnotice');
+    $this->assertRedirectTo('/admin/modo/avisnotice/status/0/active_tab/1/page/0');
   }
 }
 
@@ -228,7 +228,7 @@ class AdminAvisModerationControllerAvisEditPostTest extends AdminAvisModerationC
   }
 
   public function testRedirectToAvisPage() {
-    $this->assertRedirectTo('/admin/modo/avisnotice');
+    $this->assertRedirectTo('/admin/modo/avisnotice/status/0/active_tab/1/page/0');
   }
 
 
@@ -303,7 +303,7 @@ class AdminAvisModerationControllerAvisValidateTest extends AdminAvisModerationC
   }
 
   public function testRedirectToAvisPage() {
-    $this->assertRedirectTo('/admin/modo/avisnotice');
+    $this->assertRedirectTo('/admin/modo/avisnotice/status/0/active_tab/1/page/0');
   }
 
   public function testStatutIsOne() {
diff --git a/tests/application/modules/admin/controllers/CatalogueControllerTest.php b/tests/application/modules/admin/controllers/CatalogueControllerTest.php
index c00f210df2e9d4fe748640e3b23189f53a3eb025..48dd4c04870c852fe7f91bc80ffaeab32d4a64e7 100644
--- a/tests/application/modules/admin/controllers/CatalogueControllerTest.php
+++ b/tests/application/modules/admin/controllers/CatalogueControllerTest.php
@@ -355,7 +355,7 @@ class CatalogueControllerWithModoPortailTotalAccessIndexTest extends AdminCatalo
 
   /** @test */
   public function pageShouldContainsPermalinkForCataloguePolitique() {
-    $this->assertXPathContentContains('//div//span', "recherche/simple/id_catalogue/200");
+    $this->assertXPath('//img[contains(@class, "permalink")][contains(@data-url, "recherche/simple/id_catalogue/200")]');
   }
 
 
@@ -1266,7 +1266,7 @@ class CatalogueControllerPaniersHistoireTest extends AdminCatalogueControllerTes
 
   /** @test */
   public function pageShouldContainsPermalinkForPanier() {
-    $this->assertXPathContentContains('//div//span', "recherche/simple/id_panier/8");
+    $this->assertXPath('//img[contains(@class, "permalink")][contains(@data-url, "recherche/simple/id_panier/8")]');
   }
 
 
@@ -1467,6 +1467,9 @@ class CatalogueControllerPaniersRemovePanierAndUnindexTest extends AbstractContr
   public function setUp() {
     parent::setUp();
 
+    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Catalogue')
+      ->whenCalled('saveThesaurus')->answers(true);
+
     $pomme = $this->fixture('Class_Notice',
                             ['id' => 1456,
                              'clef_alpha' => 'POMME',
diff --git a/tests/application/modules/admin/controllers/CmsControllerTest.php b/tests/application/modules/admin/controllers/CmsControllerTest.php
index d41c4be3ae52932e19d0ac81e8eb82f664163e59..e65d3e03c4712cd5429e23caec3887d966d10a8d 100644
--- a/tests/application/modules/admin/controllers/CmsControllerTest.php
+++ b/tests/application/modules/admin/controllers/CmsControllerTest.php
@@ -724,7 +724,7 @@ class CmsControllerArticleConcertEditActionTest extends CmsControllerWithPermiss
 
   /** @test */
   public function permalinkShouldContainsArticleAbsoluteUrl() {
-    $this->assertXPathContentContains('//div//span', "cms/articleview/id/4");
+    $this->assertXPath('//img[contains(@class, "permalink")][@data-url="http://localhost' . BASE_URL . '/cms/articleview/id/4"]');
   }
 
 
@@ -2061,14 +2061,14 @@ class CmsControllerArticleEditActionWithFormTest extends CmsControllerWithPermis
                                      'description' => 'Mon article avec formulaire',
                                      'contenu' => '<form action="/formulaire/add/id_article/5" method="POST" name="mon form">',
                                      'debut' => '2011-03-20',
-                                     'fin' => '2011-03-28',
+                                     'fin' => '',
                                      'events_debut' =>  '2011-03-27 21:00',
                                      'events_fin' => '2011-03-28 22:30',
                                      'cacher_titre' => 1,
                                      'langue' => 'fr',
                                      'tags' => 'concert;jazz',
                                      'avis' => true,
-                                     'indexation' => false,
+                                     'indexation' => true,
                                      'date_creation' => '2010-12-25 10:23:23',
                                      'date_maj' => '2010-12-26  11:12:34',
                                      'domaine_ids' => [11,12],
@@ -2080,6 +2080,12 @@ class CmsControllerArticleEditActionWithFormTest extends CmsControllerWithPermis
   }
 
 
+  /** @test */
+  public function artcile5ShouldNotBeIndexed() {
+    $this->assertNull(Class_Article::find(5)->getNotice());
+  }
+
+
   /** @test */
   public function emailShouldBePresentOnFourthPosition() {
     $this->assertXPath("//table//tr[5]//input[@name='destination_email'][@type='email']",
@@ -2546,7 +2552,7 @@ class CmsControllerArticleExistingTraductionEditTest extends CmsControllerWithPe
 
   /** @test */
   function permalinkShouldContainsArticleUrl() {
-    $this->assertXPathContentContains('//div//span', "cms/articleview/id/41");
+    $this->assertXPath('//img[contains(@class, "permalink")][@data-url="http://localhost' . BASE_URL . '/cms/articleview/id/41"]');
   }
 
 
diff --git a/tests/application/modules/admin/controllers/MenusControllerTest.php b/tests/application/modules/admin/controllers/MenusControllerTest.php
index d122e917fba5a23382f262068e340f8b6c9f0457..9858bcf35ee3a1fffa95d6335534ce2d8b603633 100644
--- a/tests/application/modules/admin/controllers/MenusControllerTest.php
+++ b/tests/application/modules/admin/controllers/MenusControllerTest.php
@@ -16,16 +16,18 @@
  *
  * 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 'AdminAbstractControllerTestCase.php';
 
 
 abstract class Admin_MenusControllerProfilJazzTestCase extends Admin_AbstractControllerTestCase {
-  protected $_profil_jazz;
+  protected
+    $_storm_default_to_volatile = true,
+    $_profil_jazz;
 
   public function setUp() {
-    parent::setUp();  
+    parent::setUp();
 
     $cfg_menus = ['H' => ['libelle' => 'Menu horizontal',
                           'picto' => 'vide.gif',
@@ -68,7 +70,7 @@ abstract class Admin_MenusControllerProfilJazzTestCase extends Admin_AbstractCon
                                        'libelle' => 'Libelle du catalogue',
                                        'preferences' => ['titre' => 'Titre du catalogue'],
                                        'picto' => 'vide.gif' ]
-                                      
+
                           ],
         ],
 
@@ -87,8 +89,8 @@ abstract class Admin_MenusControllerProfilJazzTestCase extends Admin_AbstractCon
 
 class Admin_MenusControllerProfilJazzIndexActionTest extends Admin_MenusControllerProfilJazzTestCase {
   public function setUp() {
-    parent::setUp();  
-    
+    parent::setUp();
+
     $this->dispatch('admin/menus/index?'.
                     http_build_query(array('id_profil' => '5',
                                            'id_bib' => 'null',
@@ -149,7 +151,7 @@ class Admin_MenusControllerEditMenuBibNumTest extends Admin_AbstractControllerTe
                                 ->setParentId(4)
                                 ->setSousCategories(array())
                                 ->setLibelle('BD')
-                                ->setAlbums(array( 
+                                ->setAlbums(array(
                                                   $fitzgerald = Class_Album::getLoader()
                                                   ->newInstanceWithId(421)
                                                   ->setCatId(42)
@@ -160,7 +162,7 @@ class Admin_MenusControllerEditMenuBibNumTest extends Admin_AbstractControllerTe
                                                    ->setCatId(42)
                                                    ->setTitre('Armstrong')
                                                    ))
-                                )                 
+                                )
                           );
 
 
@@ -173,7 +175,7 @@ class Admin_MenusControllerEditMenuBibNumTest extends Admin_AbstractControllerTe
       ->answers(array($fitzgerald, $armstrong));
   }
 
-  
+
   public function setUp() {
     parent::setUp();
     $this->createBibNum();
@@ -196,16 +198,16 @@ class Admin_MenusControllerEditMenuBibNumTest extends Admin_AbstractControllerTe
 
   /** @test */
   function albumSelectShouldContainsFitzgerald() {
-    $this->assertXPathContentContains("//select[@id='album_id']//option[@value='421']", 
-                                      "Jazz&gt;BD&gt;Fitzgerald", 
+    $this->assertXPathContentContains("//select[@id='album_id']//option[@value='421']",
+                                      "Jazz&gt;BD&gt;Fitzgerald",
                                       $this->_response->getBody());
   }
 
 
   /** @test */
   function albumSelectShouldContainsArmstrong() {
-    $this->assertXPathContentContains("//select//option[@value='422'][@selected='selected']", 
-                                      "Jazz&gt;BD&gt;Armstrong", 
+    $this->assertXPathContentContains("//select//option[@value='422'][@selected='selected']",
+                                      "Jazz&gt;BD&gt;Armstrong",
                                       $this->_response->getBody());
   }
 
@@ -216,6 +218,9 @@ class Admin_MenusControllerEditMenuBibNumTest extends Admin_AbstractControllerTe
   }
 }
 
+
+
+
 class Admin_MenusControllerEditMenuAlbumLinkTest extends Admin_AbstractControllerTestCase {
   public function setUp() {
     parent::setUp();
@@ -231,10 +236,10 @@ class Admin_MenusControllerEditMenuAlbumLinkTest extends Admin_AbstractControlle
                                            'libelle' => 'Lien vers un album',
                                            'picto' => 'book.png',
                                            'preferences' => 'album_id=421')));
-  
+
   }
 
-  
+
 /** @test */
   public function linkAlbumWithoutCategoryShouldReturnCategoryNotClassified() {
     $this->assertXPathContentContains('//div', 'non classé', $this->_response->getBody());
@@ -324,7 +329,7 @@ class Admin_MenusControllerProfilJazzPostCalendrierActionTest extends Admin_Menu
 
   /** @test */
   public function responseShouldBeContainsMajProprietesTitleAgenda() {
-    $this->assertContains('parent.retourMajProprietes("3","Agenda","vide.gif","titre=Agenda|nb_events=10")', 
+    $this->assertContains('parent.retourMajProprietes("3","Agenda","vide.gif","titre=Agenda|nb_events=10")',
                           $this->_response->getBody());
   }
 }
@@ -337,6 +342,9 @@ class Admin_MenusControllerProfilJazzPostCatalogueActionTest extends Admin_Menus
   public function setUp() {
     parent::setUp();
 
+    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_PanierNotice')
+      ->whenCalled('findAllBelongsToAdmin')->answers([]);
+
     $this->postDispatch('admin/menus/catalogue?'.http_build_query(['id_module' => 7,
                                                                     'id_profil' => 5,
                                                                     'type_menu' => 'CATALOGUE']),
@@ -345,7 +353,7 @@ class Admin_MenusControllerProfilJazzPostCatalogueActionTest extends Admin_Menus
 
   /** @test */
   public function responseShouldBeContainsNouveaute() {
-    $this->assertContains('parent.retourMajProprietes("7","Nouveauté","vide.gif","titre=Titre du catalogue', 
+    $this->assertContains('parent.retourMajProprietes("7","Nouveauté","vide.gif","titre=Titre du catalogue',
                           $this->_response->getBody());
   }
 }
@@ -357,13 +365,31 @@ class Admin_MenusControllerProfilJazzEditCatalogueActionTest extends Admin_Menus
   public function setUp() {
     parent::setUp();
 
-    $panier_bd = Class_PanierNotice::newInstanceWithId(1, ['libelle' => 'bd']);
-    $panier_romans = Class_PanierNotice::newInstanceWithId(2, ['libelle' => 'romans']);
-    $panier_musique = Class_PanierNotice::newInstanceWithId(3, ['libelle' => 'musique']);
-    
+    $panier_bd = $this->fixture('Class_PanierNotice',
+                                ['id' => 1,
+                                 'libelle' => 'bd']);
+
+    $panier_romans = $this->fixture('Class_PanierNotice',
+                                    ['id' => 2,
+                                     'libelle' => 'romans']);
+
+    $panier_musique = $this->fixture('Class_PanierNotice',
+                                     ['id' => 3,
+                                      'libelle' => 'musique']);
+
+    $panier_autres = $this->fixture('Class_PanierNotice',
+                                    ['id' => 4,
+                                     'libelle' => 'autres']);
+
+
+    $this->fixture('Class_Catalogue',
+                   ['id' => 9,
+                    'libelle' => 'Domaine livres',
+                    'panier_notices' => [$panier_romans, $panier_bd]]);
+
     Class_Users::getIdentity()->setPaniers([$panier_bd]);
+
     Storm_Test_ObjectWrapper::onLoaderOfModel('Class_PanierNotice')
-    ->whenCalled('findAllWithCatalogue')->answers([$panier_bd, $panier_romans])
     ->whenCalled('findAllBelongsToAdmin')->answers([$panier_musique]);
 
     $this->dispatch('admin/menus/catalogue?'.http_build_query(['id_module' => 7,
@@ -388,9 +414,15 @@ class Admin_MenusControllerProfilJazzEditCatalogueActionTest extends Admin_Menus
 
   /** @test */
   public function selectIdPanierShouldContainsPanierMusique() {
-    $this->assertXPathContentContains('//select[@name="id_panier"]/option[@value="3"]', 
+    $this->assertXPathContentContains('//select[@name="id_panier"]/option[@value="3"]',
                                       'musique');
   }
+
+
+  /** @test */
+  public function selectIdPanierShouldNotContainsPanierAutres() {
+    $this->assertNotXPath('//select[@name="id_panier"]/option[@value="4"]');
+  }
 }
 
 ?>
\ No newline at end of file
diff --git a/tests/application/modules/admin/controllers/ModoControllerFormulaireTest.php b/tests/application/modules/admin/controllers/ModoControllerFormulaireTest.php
index d20548b8156661ceed159921d172f440e9b69ff5..1265516790cbd31d6aba5f035887772d376ce6da 100644
--- a/tests/application/modules/admin/controllers/ModoControllerFormulaireTest.php
+++ b/tests/application/modules/admin/controllers/ModoControllerFormulaireTest.php
@@ -257,7 +257,7 @@ class ModoControllerFormulaireForArticleValidateFormulaireMireilleTest extends M
 class ModoControllerFormulaireForArticleDeleteTest extends ModoControllerFormulaireForArticleTestCase {
   public function setUp() {
     parent::setUp();
-
+    $_SERVER['HTTP_REFERER'] = '/admin/modo/formulaires/id_article/12';
     $this->dispatch('admin/modo/delete-formulaire/id_article/12/id/5', true);
   }
 
diff --git a/tests/application/modules/admin/controllers/ModoControllerTest.php b/tests/application/modules/admin/controllers/ModoControllerTest.php
index 8f3c6265355282f573808412be43de240ec10dcc..2f46be2ff81945c77a61d56f0a9cac788902bc68 100644
--- a/tests/application/modules/admin/controllers/ModoControllerTest.php
+++ b/tests/application/modules/admin/controllers/ModoControllerTest.php
@@ -637,31 +637,49 @@ class ModoControllerAvisnoticeActionTest extends Admin_AbstractControllerTestCas
 
   public function setup() {
     parent::setup();
+
+    $this->fixture('Class_AvisNotice', ['id' => 622,
+                                        'id_notice' => 1002,
+                                        'entete' => 'Orphan Test',
+                                        'note'=> 2,
+                                        'id_user' => null,
+                                        'flags' => 1,
+                                        'avis' => 'Un bon livre !',
+                                        'id_notice' => 1032,
+                                        'statut' => 0,
+                                        'abon_ou_bib' => 1]);
+
     $this->dispatch('admin/modo/avisnotice', true);
   }
 
 
   /** @test **/
   public function avisnoticeShouldContainsListAvisBibliothecaires() {
-    $this->assertXpathContentContains('//div//h2', 'bibliothécaires', $this->_response->getBody());
+    $this->assertXpathContentContains('//div//h2', 'bibliothécaires');
   }
 
 
   /** @test **/
   public function avisnoticeShouldContainsListAvisAbonnes() {
-    $this->assertXpathContentContains('//div//h2', 'abonnés', $this->_response->getBody());
+    $this->assertXpathContentContains('//div//h2', 'abonnés');
   }
 
 
   /** @test **/
-  public function avisnoticeShouldContainsOrphanFlag() {
-    $this->assertXpathContentContains('//div//h2', 'Avis orphelins', $this->_response->getBody());
+  public function avisnoticeShouldContainsOrphanFlagWithOnOpinion() {
+    $this->assertXpathContentContains('//div//h2', 'Avis orphelins (1)');
+  }
+
+
+  /** @test */
+  public function avisnoticeShouldContainsOneOpinion() {
+    $this->assertXPathContentContains('//div[@class="critique"]//a[contains(@href, "blog/viewavis/id/622")]', "Orphan Test");
   }
 
 
   /** @test */
   public function LinkToAllModeratedReviewsShouldBeDisplayed() {
-    $this->assertXPathContentContains('//a', 'Afficher tous les avis modérés', $this->_response->getBody());
+    $this->assertXPathContentContains('//a', 'Afficher tous les avis modérés');
   }
 }
 
@@ -673,7 +691,7 @@ class ModoControllerAllReviewsActionTest extends ModoControllerIndexActionTestCa
 
   public function setup() {
     parent::setup();
-    $this->dispatch('admin/modo/allreviews', true);
+    $this->dispatch('admin/modo/avisnotice/status/1', true);
   }
 
 
@@ -718,21 +736,21 @@ class ModoControllerAllReviewsPageActionTest extends ModoControllerIndexActionTe
 
   /** @test **/
   public function moderatedReviewsShouldBeDisplayedEvenIfPageIsOutOfBound() {
-    $this->dispatch('admin/modo/allreviews/page/10', true);
+    $this->dispatch('admin/modo/avisnotice/status/1/page/10', true);
     $this->assertXpathContentContains('//div//h2', 'B comme bière : la bière expliquée aux (grands) enfants');
   }
 
 
   /** @test **/
   public function page3ShouldNotConstainsTheLastReviewSaved139() {
-    $this->dispatch('admin/modo/allreviews/page/3/active_tab/1', true);
+$this->dispatch('admin/modo/avisnotice/status/1/page/3/active_tab/1', true);
     $this->assertNotXpathContentContains('//div[@class="critique"]//div[@class="contenu_critique"]//a[contains(@href, "blog/viewavis")]', '139');
   }
 
 
   /** @test */
   public function page1ShouldContains10Reviews() {
-    $this->dispatch('admin/modo/allreviews/page/1/active_tab/1', true);
+    $this->dispatch('admin/modo/avisnotice/status/1/page/1/active_tab/1', true);
     $this->assertXPathContentContains('//div[2]/span', 'résultats sur cette page.', $this->_response->getBody());
   }
 }
diff --git a/tests/application/modules/admin/controllers/UsersControllerTest.php b/tests/application/modules/admin/controllers/UsersControllerTest.php
index 39cfbbdac828bca8acf5fc02b8f35f1d15fb4bd4..2172c42b50d0cc55249aa1fc9eb68923defd21c3 100644
--- a/tests/application/modules/admin/controllers/UsersControllerTest.php
+++ b/tests/application/modules/admin/controllers/UsersControllerTest.php
@@ -61,7 +61,7 @@ abstract class UsersControllerWithMarcusTestCase extends AbstractControllerTestC
                                                    'password' => 'mysecret',
                                                    'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
                                                    'idabon' => '00123',
-                                                   'bib' => $this->mybib,
+                                                   'id_site' => 100,
                                                    'ordreabon' => 1,
                                                    'date_debut' => '19-07-2009',
                                                    'date_fin' => '19-07-2010',
@@ -74,7 +74,7 @@ abstract class UsersControllerWithMarcusTestCase extends AbstractControllerTestC
 
     $this->marcus->setFicheSIGB(['type_comm' => 0, 'nom_aff' => 'Marcus'])
                  ->setUserGroups([$group_vodeclic,$group_referent])
-                 ->setIntBib($this->fixture('Class_IntBib', ['id' => 1, 'comm_sigb' => 0]));
+                 ->setIntBib($this->fixture('Class_IntBib', ['id' => 100, 'comm_sigb' => 0]));
 
     $this->user_loader = Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Users');
 
@@ -97,19 +97,119 @@ abstract class UsersControllerWithMarcusTestCase extends AbstractControllerTestC
 class UsersControllerIndexTest extends UsersControllerWithMarcusTestCase {
   public function setUp() {
     parent::setUp();
-    $this->dispatch('/admin/users', true);
+
+    $user = $this->fixture('Class_Users',
+                           ['id' => 1,
+                            'login' => 'tom',
+                            'password' => 'rom',
+                            'role_level' => ZendAfi_Acl_AdminControllerRoles::SUPER_ADMIN]);
+
+    $francis = $this->fixture('Class_Users',
+                              ['id' => 57,
+                               'login' => 'francis',
+                               'password' => 'francis']);
+
+    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Users')
+      ->whenCalled('getIdentity')
+      ->answers($user)
+
+      ->whenCalled('hasIdentity')
+      ->answers($user)
+
+      ->whenCalled('findSearched')
+      ->with(['id_site' => 'all',
+              'role_level' => '2'] ,
+             ['login' => 'francis',
+              'nom' => 'francis',
+              'prenom' => 'francis',
+              'pseudo' => 'francis',
+              'mail' => 'francis',
+              'idabon' => 'francis'],
+             '1',
+             [1, 20])
+      ->answers([$francis])
+
+      ->whenCalled('countSearched')
+      ->with(['id_site' => 'all',
+              'role_level' => '2'] ,
+             ['login' => 'francis',
+              'nom' => 'francis',
+              'prenom' => 'francis',
+              'pseudo' => 'francis',
+              'mail' => 'francis',
+              'idabon' => 'francis'],
+             '1')
+      ->answers(55)
+
+      ->beStrict();
+
+    $this->dispatch('/admin/users?by_id_site=all&by_role_level=2&by_valide_subscription=1&search_for=\"\'fra"n\'cis"', true);
   }
 
 
   /** @test */
-  public function formShouldContainsInputForNom() {
-    $this->assertXPath('//input[@name="nom"]');
+  public function formShouldContainsInputSearch() {
+    $this->assertXPath('//input[@name="search_for"]');
   }
 
 
   /** @test */
   public function formShouldContainsRoleSelect() {
-    $this->assertXPath('//select[@name="role"]',$this->_response->getBody());
+    $this->assertXPath('//select[@name="by_role_level"]');
+  }
+
+
+  /** @test */
+  public function libSelectorShouldBePresent() {
+    $this->assertXPath('//select[@name="by_id_site"]');
+  }
+
+
+  /** @test */
+  public function addUserButtonShouldBePresent() {
+    $this->assertXPath('//div[contains(@onclick, "admin/users/add")]');
+  }
+
+
+  /** @test */
+  public function totalUsersShouldBeFiftyFive() {
+    $this->assertXPathContentContains('//p','55 utilisateurs trouvés');
+  }
+
+
+  /** @test */
+  public function linkToEditFrancisShouldBePresent() {
+    $this->assertXPath('//table//tr//a[contains(@href, "users/edit/id/57/by_id_site/all/by_role_level/2")]');
+  }
+
+
+  /** @test */
+  public function linkToDeleteFrancisShouldBePresent() {
+    $this->assertXPath('//table//tr//a[contains(@href, "users/delete/id/57/by_id_site/all/by_role_level/2")]');
+  }
+
+
+  /** @test */
+  public function pagerShouldBePresent() {
+    $this->assertXPath('//div[@class="pager"]//span[1][@class="current"]');
+  }
+
+
+  /** @test */
+  public function jsToogleValideSubscriptionShouldBePresent() {
+    $this->assertXPathContentContains('//script', '$("#by_role_level option[value=2]:selected")');
+  }
+
+
+  /** @test */
+  public function allRoleLevelShouldBeSelectable() {
+    $this->assertXPath('//select[@name="by_role_level"]//option[@value="all"]');
+  }
+
+
+  /** @test */
+  public function allLibraryShouldBeSelectable() {
+    $this->assertXPath('//select[@name="by_id_site"]//option[@value="all"]');
   }
 }
 
@@ -155,7 +255,7 @@ class UsersControllerEditMarcusTest extends UsersControllerWithMarcusTestCase {
 
   /** @test **/
   public function testGroupesAreMultimediaAndReferent() {
-    $this->assertXPath("//input[@name='user_group_ids'][@value='20-22']",$this->_response->getBody());
+    $this->assertXPath("//input[@name='user_group_ids'][@value='20-22']");
   }
 
 
@@ -174,13 +274,13 @@ class UsersControllerEditMarcusTest extends UsersControllerWithMarcusTestCase {
 
   /** @test **/
   public function testDisabledInputForRole() {
-    $this->assertXPath("//select[@name='role_level'][@disabled='disabled']//option[@value='2'][@selected='selected']",$this->_response->getBody());
+    $this->assertXPath("//select[@name='role_level'][@disabled='disabled']//option[@value='2'][@selected='selected']");
   }
 
 
   /** @test **/
-  public function testSelectedBibIsIdOne() {
-    $this->assertXPath("//select[@name='id_site']//option[@value='1'][@selected]", $this->_response->getBody());
+  public function testSelectedBibIsIdOneHundred() {
+    $this->assertXPath("//select[@name='id_site']//option[@value='100'][@selected]");
   }
 
 
@@ -334,7 +434,6 @@ class UsersControllerPostMarcusDataTest extends UsersControllerWithMarcusTestCas
   public function setUp() {
     parent::setUp();
 
-
     $this->_postEditData(['login' => 'mdavis',
                           'password' => 'tutu',
                           'nom' => 'Davis',
@@ -642,29 +741,26 @@ class UsersControllerReferentIndexTest extends UsersControllerWithMarcusTestCase
 
   /** @test **/
   public function testSelectedRoleForReferentIsAbonneSIGB() {
-    $this->assertXPathContentContains("//select[@name='role']/option[@value='2'][@selected='selected']",
-                                      'abonné identifié SIGB',$this->_response->getBody());
+    $this->assertXPathContentContains("//select[@name='by_role_level']/option[@value='2'][@selected='selected']", 'Abonné SIGB');
   }
 
 
   /** @test **/
   public function testRolesForReferentShouldContainsOnlyAbonnesSIGB() {
-    $this->assertNotXPath("//select[@name='role_level']/option[@value='3']"
-                          ,$this->_response->getBody());
+    $this->assertNotXPath("//select[@name='role_level']/option[@value='3']");
   }
 
 
   /** @test **/
   public function testReferentCanNotCreateNewUser() {
     $this->assertNotXPathContentContains("//td",
-                                         'Ajouter un utilisateur',$this->_response->getBody());
+                                         'Ajouter un utilisateur');
   }
 
 
   /** @test **/
   public function testReferentCanNotEditUser() {
-    $this->assertNotXPath("//table//a[contains(@href, '/users/edit')]",
-                          $this->_response->getBody());
+    $this->assertNotXPath("//table//a[contains(@href, '/users/edit')]");
   }
 }
 
@@ -691,7 +787,7 @@ class UsersControllerAddPostTest extends UsersControllerWithMarcusTestCase {
                        'pseudo' => '',
                        'mail' => 'mdavis@free.fr',
                        'role_level' => '4',
-                       'id_site' => '1',
+                       'id_site' => '100',
                        'idabon' => '2341',
                        'ordreabon' => '2',
                        'telephone' => '',
@@ -709,17 +805,18 @@ class UsersControllerAddPostTest extends UsersControllerWithMarcusTestCase {
 
   public function testValidDataRedirectedToUsers() {
     $this->user_loader
-      ->whenCalled('save')->answers(true)
-      ->whenCalled('findFirstBy')->answers(null)
+      ->whenCalled('save')
+      ->answers(true)
+      ->whenCalled('findFirstBy')
+      ->answers(null)
       ->whenCalled('getIdentity')
-      ->answers(Class_Users::getLoader()->newInstanceWithId(777)
+      ->answers(Class_Users::getLoader()
+                ->newInstanceWithId(777)
                 ->setLogin('sysadmin')
                 ->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::SUPER_ADMIN)
-                ->setPseudo('admin'))
-      ;
+                ->setPseudo('admin'));
 
     $this->_postData();
-
     $this->assertRedirect();
   }
 
@@ -792,12 +889,12 @@ abstract class Admin_UsersControllerEditAdminTestCase extends Admin_AbstractCont
                     'libelle' => 'Region Savoie']);
 
     $this->_lib_ac = $this->fixture('Class_Bib',
-                                 ['id' => 1,
+                                 ['id' => 7,
                                   'libelle' => 'AC',
                                   'id_zone' => 1]);
 
     $this->_lib_po = $this->fixture('Class_Bib',
-                                 ['id' => 2,
+                                 ['id' => 15,
                                   'libelle' => 'PO',
                                   'id_zone' => 1,
                                   'redmine_api_key' => '123abc']);
@@ -839,7 +936,7 @@ class Admin_UsersControllerFormEditAdminTest extends Admin_UsersControllerEditAd
 
   /** @test */
   public function libACSHouldBeSelected() {
-    $this->assertXPathContentContains('//form//select[@name="id_site"]//option[@value="1"][@selected]', 'AC');
+    $this->assertXPathContentContains('//form//select[@name="id_site"]//option[@value="7"][@selected]', 'AC');
   }
 
 
@@ -863,13 +960,13 @@ class Admin_UsersControllerFormEditAdminTest extends Admin_UsersControllerEditAd
 
   /** @test */
   public function defaultRedmineLibraryShouldBeAC() {
-    $this->assertXPathContentContains('//table//tr//td//select[@name="redmine_library"]/option[@value="1"][@selected="selected"]', 'AC', $this->_response->getBody());
+    $this->assertXPathContentContains('//table//tr//td//select[@name="redmine_library"]/option[@value="7"][@selected="selected"]', 'AC', $this->_response->getBody());
   }
 
 
   /** @test */
   public function libraryPoShouldBeAnOption() {
-    $this->assertXPathContentContains('//table//tr//td//select[@name="redmine_library"]/option[@value="2"]', 'PO', $this->_response->getBody());
+    $this->assertXPathContentContains('//table//tr//td//select[@name="redmine_library"]/option[@value="15"]', 'PO', $this->_response->getBody());
   }
 }
 
@@ -886,7 +983,7 @@ class UsersControllerPostEditAdminTest extends Admin_UsersControllerEditAdminTes
                                                     'pseudo' => 'Dave',
                                                     'mail' => 'mdavis@free.fr',
                                                     'role_level' => ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL,
-                                                    'id_site' => '1',
+                                                    'id_site' => '7',
                                                     'idabon' => '2341',
                                                     'ordreabon' => '2',
                                                     'telephone' => '',
@@ -899,13 +996,14 @@ class UsersControllerPostEditAdminTest extends Admin_UsersControllerEditAdminTes
                                                     'date_debut' => '',
                                                     'date_fin' => '',
                                                     'user_group_ids' => '',
-                                                    'redmine_library' => '2']);
+                                                    'redmine_library' => '15']);
   }
 
 
   /** @test */
   public function terminatorRedmineLibraryShouldBePo() {
-    $this->assertEquals($this->_admin->getRedmineLibrary()->getLibelle(), $this->_lib_po->getLibelle());
+    $this->assertEquals($this->_admin->getRedmineLibrary()->getLibelle(),
+                        $this->_lib_po->getLibelle());
   }
 }
 
diff --git a/tests/application/modules/opac/controllers/BlogControllerTest.php b/tests/application/modules/opac/controllers/BlogControllerTest.php
index c01c62513941be41e1a273e92b26b1c476e153ab..6144366da1567f14fad2bcb3d12ee21cdf43f6a8 100644
--- a/tests/application/modules/opac/controllers/BlogControllerTest.php
+++ b/tests/application/modules/opac/controllers/BlogControllerTest.php
@@ -145,7 +145,9 @@ class BlogControllerHierarchicalTest extends AbstractControllerTestCase {
 
   /** @test */
   public function kspShouldBePresent() {
-    $this->assertXPathContentContains('//h2', 'Kerbal Space Program',$this->_response->getBody());
+    $this->assertXPathContentContains('//h2',
+                                      'Kerbal Space Program',
+                                      $this->_response->getBody());
   }
 
 
diff --git a/tests/application/modules/opac/controllers/CmsControllerCalendarActionTest.php b/tests/application/modules/opac/controllers/CmsControllerCalendarActionTest.php
index fc23f086800090bd84dea4e21a8c46074dda347f..5278437d740f4057c3d84249381277c494d63981 100644
--- a/tests/application/modules/opac/controllers/CmsControllerCalendarActionTest.php
+++ b/tests/application/modules/opac/controllers/CmsControllerCalendarActionTest.php
@@ -352,39 +352,45 @@ class CmsControllerCalendarActionWithDayTest extends AbstractControllerTestCase
 
 
 
+
 class CmsControllerCalendarActionHeaderTest extends AbstractControllerTestCase {
+
   public function setUp() {
     parent::setUp();
-    $this->cfg_accueil = [
-                          'modules' => [
-                                        '1' => [
-                                                'division' => '1',
-                                                'type_module' => 'CALENDAR',
-                                                'preferences' => [
-                                                                  'titre' => 'Rendez-vous',
-                                                                  'rss_avis' => false,
-                                                                  'id_categorie' => '12-2',
-                                                                  'display_cat_select' => true,
-                                                                  'enabled_filters' => 'date;place;custom_field_2;zork',
-                                                                  'display_event_info' => 'none'
-                                                ]
-                                        ]
-                          ],
-                          'options' => []
+
+    $cfg_accueil = [
+                    'modules' => [
+                                  '1' => [
+                                          'division' => '1',
+                                          'type_module' => 'CALENDAR',
+                                          'preferences' => [
+                                                            'titre' => 'Rendez-vous',
+                                                            'rss_avis' => false,
+                                                            'id_categorie' => '12-2',
+                                                            'display_cat_select' => true,
+                                                            'enabled_filters' => 'date;place;custom_field_2;zork',
+                                                            'display_event_info' => 'none',
+                                          ]
+                                  ]
+                    ],
+                    'options' => []
     ];
 
 
     $this->fixture('Class_Profil',
-                   ['id' => 3,
+                   ['id' => 4,
                     'browser' => 'opac',
                     'libelle' => 'Rendez-vous',
-                    'cfg_accueil' => $this->cfg_accueil]);
+                    'cfg_accueil' => $cfg_accueil]);
 
-    $this->dispatch('/index/index/id_profil/3');
+
+    $this->dispatch('/index/index/id_profil/4');
   }
 
+
   /** @test */
   public function calendarHeaderShouldContainsThreeLinks() {
+
     $this->assertXPathCount(3, '//td[@class="calendar_title_month"]/a');
     $this->assertXPathContentContains('//td[@class="calendar_title_month"]/a[1]', '«');
     $this->assertXPathContentContains('//td[@class="calendar_title_month"]/a[3]', '»');
@@ -394,6 +400,65 @@ class CmsControllerCalendarActionHeaderTest extends AbstractControllerTestCase {
 
 
 
+class CmsControllerCalendarActionAjaxLinkTest extends AbstractControllerTestCase {
+
+  public function setUp() {
+    parent::setUp();
+
+    $cfg_accueil = [
+                    'modules' => [
+                                  '1' => [
+                                          'division' => '1',
+                                          'type_module' => 'CALENDAR',
+                                          'preferences' => [
+                                                            'titre' => 'Rendez-vous',
+                                                            'rss_avis' => false,
+                                                            'id_categorie' => '12-2',
+                                                            'display_cat_select' => true,
+                                                            'enabled_filters' => 'date;place;custom_field_2;zork',
+                                                            'display_event_info' => 'none',
+                                                            'display_full_page' => 1
+                                          ]
+                                  ]
+                    ],
+                    'options' => []
+    ];
+
+
+    $this->fixture('Class_Profil',
+                   ['id' => 5,
+                    'browser' => 'opac',
+                    'libelle' => 'Rendez-vous',
+                    'cfg_accueil' => $cfg_accueil]);
+
+    $articles = [$this->fixture('Class_Article',
+                               ['id' => 25,
+                                'titre' => 'News of the 30th September',
+                                'contenu' => 'youpi !',
+                                'events_debut' => '2014-09-28',
+                                'events_fin' => '2014-09-30'])];
+
+    $time_source = new TimeSourceForTest('2014-09-02 14:14:14');
+    ZendAfi_View_Helper_CalendarContent::setTimeSource($time_source);
+    ZendAfi_View_Helper_Calendar_Table::setTimeSource($time_source);
+
+    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Article')
+      ->whenCalled('getArticlesByPreferences')
+      ->answers($articles);
+
+    $this->dispatch('/index/index/id_profil/5');
+  }
+
+
+  /** @test */
+  public function calendarDayLinkShouldNotContainsRenderAjax() {
+    $this->assertXPath('//td//a[@class="calendar_day_non_clickable day_clickable calendar_day_event_start "][not(contains(@href, "/render/ajax"))]', $this->_response->getBody());
+  }
+}
+
+
+
+
 class CmsControllerCalendarActionWithOutDateTest extends AbstractControllerTestCase {
   public function setUp() {
     parent::setUp();
@@ -452,4 +517,4 @@ class CmsControllerCalendarActionWithOutDateTest extends AbstractControllerTestC
   public function gatArticleByPreferencesShouldBeCallWithEventDAteAfter() {
     $this->assertXPathContentContains('//div', 'Kitchen', $this->_response->getBody());
   }
-}
+}
\ No newline at end of file
diff --git a/tests/application/modules/opac/controllers/CmsControllerTest.php b/tests/application/modules/opac/controllers/CmsControllerTest.php
index c366143b22ad53ea2e64ac14ce3070d2583b5f83..009805941eb249b1f843e7657714c79b8a8998d3 100644
--- a/tests/application/modules/opac/controllers/CmsControllerTest.php
+++ b/tests/application/modules/opac/controllers/CmsControllerTest.php
@@ -998,14 +998,7 @@ class CmsControllerArticleViewTest extends CmsControllerWithFeteDeLaFriteTestCas
   /** @test */
   public function socialNetworksContainerShouldBePresent() {
     //on garde le @id="reseaux-sociaux-224" pour la compatibilité avec les persos graphiques
-    $this->assertXpath('//div[@class="reseaux-sociaux"][contains(@data-article-url, "cms/reseau/id_article/224")]/img[contains(@src, "patience.gif")]');
-  }
-
-
-  /** @test */
-  public function initializeResauxSociauxScriptShouldBePresent() {
-    $this->assertXPathContentContains('//script',
-                                      "initializeReseauxSociaux");
+    $this->assertXpath('//div[contains(@class, "reseaux-sociaux")]//img[contains(@data-url, "cms/articleview/id/224")]');
   }
 
 
diff --git a/tests/application/modules/opac/controllers/PanierControllerTest.php b/tests/application/modules/opac/controllers/PanierControllerTest.php
index d6777afc4119f19faad7070cb9313b0d1b32c6c0..80d6e0f7f4ecdd007d44a1e6f958109e3a510772 100644
--- a/tests/application/modules/opac/controllers/PanierControllerTest.php
+++ b/tests/application/modules/opac/controllers/PanierControllerTest.php
@@ -52,14 +52,11 @@ abstract class PanierControllerSimpleLoggedUserTestCase extends AbstractControll
 
 
 abstract class PanierControllerTestCase extends AbstractControllerTestCase {
+  protected
+    $_storm_default_to_volatile = true;
+
   public function setUp() {
     parent::setUp();
-    Class_Users::beVolatile();
-    Class_NoticeDomain::beVolatile();
-    Class_UserGroup::beVolatile();
-    Class_Notice::beVolatile();
-    Class_PanierNotice::beVolatile();
-    Class_PanierNoticeCatalogue::beVolatile();
 
     $this->manon = $this->fixture('Class_Users', [
       'id' => 23,
@@ -120,39 +117,41 @@ abstract class PanierControllerTestCase extends AbstractControllerTestCase {
               'order' => 'FIELD(clef_alpha, "MONTESPAN")'])
       ->answers([$montespan]);
 
-    $this->panier_loader = Storm_Test_ObjectWrapper::onLoaderOfModel('Class_PanierNotice')
-      ->whenCalled('save')->answers(true)
-      ->whenCalled('delete')->answers(true)
-
-      ->whenCalled('findAll')->answers([$this->panier_bd, $this->panier_romans])
 
-      ->whenCalled('findAllBy')
-      ->with(['role' => 'user', 'model' => $this->manon])
-      ->answers([$this->panier_bd, $this->panier_romans]);
-
-    $panier_domaine_histoire = Class_PanierNoticeCatalogue::newInstanceWithId(71);
+    $panier_domaine_histoire = $this->fixture('Class_PanierNoticeCatalogue',
+                                              ['id' => 71]);
     $panier_domaine_histoire
-      ->setPanierNotice(Class_PanierNotice::newInstanceWithId(38,
-                                                              ['libelle' => 'selection jeunesse',
-                                                               'user' => Class_Users::newInstanceWithId(45, ['nom' => 'Dupont']),
-                                                               'date_maj' => '19/01/2013',
-                                                               'panier_notice_catalogues' => [$panier_domaine_histoire]]))
-      ->setCatalogue(Class_Catalogue::newInstanceWithId(97, ['libelle' => 'histoire']))->save();
-
-
-    $panier_domaine_bd = Class_PanierNoticeCatalogue::newInstanceWithId(72);
+      ->setPanierNotice($this->fixture('Class_PanierNotice',
+                                       ['id' => 38,
+                                        'libelle' => 'selection jeunesse',
+                                        'user' => Class_Users::newInstanceWithId(45, ['nom' => 'Dupont']),
+                                        'date_maj' => '19/01/2013',
+                                        'panier_notice_catalogues' => [$panier_domaine_histoire]]))
+      ->setCatalogue($this->fixture('Class_Catalogue',
+                                    ['id' => 97,
+                                     'libelle' => 'histoire']))
+      ->save();
+
+
+    $panier_domaine_bd = $this->fixture('Class_PanierNoticeCatalogue',
+                                        ['id' => 72]);
     $panier_domaine_bd
       ->setPanierNotice($this->panier_bd)
-      ->setCatalogue(Class_Catalogue::newInstanceWithId(199,
-                                                        ['libelle' => 'bd',
-                                                         'panier_notice_catalogues' => [$panier_domaine_bd]]))->save();
-
-    $panier_domaine_orphelin = Class_PanierNoticeCatalogue::newInstanceWithId(456);
+      ->setCatalogue($this->fixture('Class_Catalogue',
+                                    ['id' => 199,
+                                     'libelle' => 'bd',
+                                     'panier_notice_catalogues' => [$panier_domaine_bd]]))
+      ->save();
+
+    $panier_domaine_orphelin = $this->fixture('Class_PanierNoticeCatalogue',
+                                              ['id' => 456]);
     $panier_domaine_orphelin
       ->setPanierNotice($this->panier_orphelin)
-      ->setCatalogue(Class_Catalogue::newInstanceWithId(1789,
-                                                        ['libelle' => 'orphelin',
-                                                         'panier_notice_catalogues' => [$panier_domaine_orphelin]]))->save();
+      ->setCatalogue($this->fixture('Class_Catalogue',
+                                    ['id' => 1789,
+                                     'libelle' => 'orphelin',
+                                     'panier_notice_catalogues' => [$panier_domaine_orphelin]]))
+      ->save();
 
   }
 }
@@ -442,6 +441,7 @@ class PanierControllerSupprimerNoticeBlacksadFromBDTest extends PanierController
   public function setUp() {
     parent::setUp();
     $this->dispatch('/panier/paniersupprimernotice/id_panier/2/id_notice/12', true);
+    Class_PanierNotice::clearCache();
   }
 
 
@@ -451,13 +451,6 @@ class PanierControllerSupprimerNoticeBlacksadFromBDTest extends PanierController
   }
 
 
-  /** @test */
-  public function panierShouldHaveBeenSaved() {
-    $this->assertTrue(Class_PanierNotice::methodHasBeenCalled('save'));
-  }
-
-
-  /** @test */
   public function responseShouldRedirectToIndex() {
     $this->assertRedirectTo('/opac/panier/index/id_panier/2');
   }
@@ -469,12 +462,13 @@ class PanierControllerSupprimerBDTest extends PanierControllerTestCase {
   public function setUp() {
     parent::setUp();
     $this->dispatch('/panier/supprimerpanier/id_panier/2', true);
+    Class_PanierNotice::clearCache();
   }
 
 
   /** @test */
   public function panierShouldHaveBeenDeleted() {
-    $this->assertTrue(Class_PanierNotice::methodHasBeenCalled('delete'));
+    $this->assertEmpty(Class_PanierNotice::find(2));
   }
 
 
@@ -493,14 +487,15 @@ class PanierControllerOtherUserSecurityTest extends PanierControllerTestCase {
     Class_PanierNotice::newInstanceWithId(39,
                                           ['libelle' => 'panier Markus',
                                            'user' => Class_Users::newInstanceWithId(98, ['nom' => 'Markus']),
-                                           'date_maj' => '19/01/2013']);
+                                           'date_maj' => '19/01/2013'])->assertSave();
   }
 
 
   /** @test */
   public function panierDomaineHistoireShouldNotBeDeletable() {
     $this->dispatch('/panier/supprimerpanier/id_panier/39', true);
-    $this->assertFalse(Class_PanierNotice::methodHasBeenCalled('delete'));
+    Class_PanierNotice::clearCache();
+    $this->assertNotEmpty(Class_PanierNotice::find(39));
   }
 
 
@@ -521,25 +516,34 @@ class PanierControllerOtherUserSecurityTest extends PanierControllerTestCase {
   /** @test */
   public function addPanierToMarkusShouldBeForbidden() {
     $this->dispatch('/panier/panierajouternotice/id_panier/39/id_notice/12', true);
-    $this->assertFalse(Class_PanierNotice::methodHasBeenCalled('save'));
+    Class_PanierNotice::clearCache();
+    $this->assertNotContains('BLACKSAD',
+                             Class_PanierNotice::find(39)->getClesNotices());
     $this->assertRedirectTo('/opac/panier');
   }
 
 
   /** @test */
-  public function addPanierAjaxToMarkusShouldBeForbidden() {
+  public function addPanierAjaxToMarkusByAbonneSIGBShouldBeForbidden() {
     $this->manon->setRoleLevel(ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB);
     ZendAfi_Auth::getInstance()->logUser($this->manon);
+
     $this->postDispatch('/panier/ajout-ajax/id_panier/39/id_notice/12', []);
-    $this->assertFalse(Class_PanierNotice::methodHasBeenCalled('save'));
+    $this->assertNotContains('BLACKSAD',
+                             Class_PanierNotice::find(39)->getClesNotices());
+
     $this->assertRedirectTo('/opac/panier');
   }
 
 
   /** @test */
   public function removeNoticeFromPanierMarkusShouldBeForbidden() {
+    Class_PanierNotice::find(39)->setClesNotices(['BLACKSAD'])->assertSave();
     $this->postDispatch('/panier/paniersupprimernotice/id_panier/39/id_notice/12', []);
-    $this->assertFalse(Class_PanierNotice::methodHasBeenCalled('save'));
+
+    Class_PanierNotice::clearCache();
+    $this->assertContains('BLACKSAD', Class_PanierNotice::find(39)->getClesNotices());
+
     $this->assertRedirectTo('/opac/panier');
   }
 
@@ -547,7 +551,8 @@ class PanierControllerOtherUserSecurityTest extends PanierControllerTestCase {
   /** @test */
   public function majTitrePanierMarkusShouldBeForbidden() {
     $this->postDispatch('/panier/majtitrepanier/id_panier/39/', ['new_libelle' => 'crack']);
-    $this->assertFalse(Class_PanierNotice::methodHasBeenCalled('save'));
+    Class_PanierNotice::clearCache();
+    $this->assertEquals('panier Markus', Class_PanierNotice::find(39)->getLibelle());
     $this->assertRedirectTo('/opac/panier');
   }
 }
@@ -617,17 +622,9 @@ class PanierControllerAjoutNoticeBlackSadToPanierMesRomansTest extends PanierCon
   public function setUp() {
     parent::setUp();
 
-    $this->panier_loader
-      ->whenCalled('maxIdPanierForUser')
-      ->answers(4);
-
     $this->dispatch('/panier/panierajouternotice/id_panier/15/id_notice/12', true);
-  }
-
-
-  /** @test */
-  public function panierShouldHaveBeenSaved() {
-    $this->assertTrue(Class_PanierNotice::methodHasBeenCalled('save'));
+    Class_PanierNotice::clearCache();
+    $this->panier_romans = Class_PanierNotice::find(15);
   }
 
 
@@ -651,10 +648,6 @@ class PanierControllerAjoutUnknownNoticeToPanierMesRomansTest extends PanierCont
   public function setUp() {
     parent::setUp();
 
-    $this->panier_loader
-      ->whenCalled('maxIdPanierForUser')
-      ->answers(4);
-
     $this->dispatch('/panier/panierajouternotice/id_panier/15/id_notice/-1', true);
   }
 
@@ -673,12 +666,7 @@ class PanierControllerAjoutNoticeBlackSadToPanierDomaineHistoireTest extends Pan
     parent::setUp();
     $this->manon->changeRoleTo(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
     $this->dispatch('/panier/panierajouternotice/id_panier/38/id_notice/12', true);
-  }
-
-
-  /** @test */
-  public function panierShouldHaveBeenSaved() {
-    $this->assertTrue(Class_PanierNotice::methodHasBeenCalled('save'));
+    Class_PanierNotice::clearCache();
   }
 
 
@@ -698,14 +686,10 @@ class PanierControllerModifierTitrePanierMesRomansToMesLivresTest extends Panier
     $this->postDispatch('/panier/majtitrepanier/id_panier/15',
                         ['new_libelle' => 'Mes livres'],
                         true);
+    Class_PanierNotice::clearCache();
   }
 
 
-  /** @test */
-  public function panierShouldHaveBeenSaved() {
-    $this->assertTrue(Class_PanierNotice::methodHasBeenCalled('save'));
-  }
-
 
   /** @test */
   public function responseShouldRedirectToIndex() {
@@ -715,7 +699,7 @@ class PanierControllerModifierTitrePanierMesRomansToMesLivresTest extends Panier
 
   /** @test */
   public function panierLibelleShouldBeMesLivres() {
-    $this->assertEquals('Mes livres', $this->panier_romans->getLibelle());
+    $this->assertEquals('Mes livres', Class_PanierNotice::find(15)->getLibelle());
   }
 }
 
@@ -731,12 +715,8 @@ class PanierControllerModifierCataloguePanierTest extends PanierControllerTestCa
     $this->postDispatch('/panier/majtitrepanier/id_panier/15',
                         ['domaine_ids' => '97-199'],
                         true);
-  }
-
-
-  /** @test */
-  public function panierShouldHaveBeenSaved() {
-    $this->assertTrue(Class_PanierNotice::methodHasBeenCalled('save'));
+    Class_PanierNotice::clearCache();
+    $this->panier_romans = Class_PanierNotice::find(15);
   }
 
 
@@ -1041,34 +1021,15 @@ class PanierControllerCreerPanierPostTest extends PanierControllerTestCase {
     parent::setUp();
     $this->manon->setPaniers([]);
 
-    $lesBonLivres= (new Class_PanierNotice);
-    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_PanierNotice')
-      ->whenCalled('save')
-      ->answers(true)
-      ->whenCalled('maxIdPanierForUser')
-      ->answers(1)
-      ->whenCalled('getId')
-      ->answers(1)
-      ->whenCalled('find')
-      ->answers(((new Class_PanierNotice())
-                 ->setUser($this->manon)
-                 ->setLibelle('Par ici les bons livres')
-                 ->setIdPanier(1)));
-
-
     $this->postDispatch('/panier/creer-panier',
                         ['titre'=>'Par ici les bons livres']);
   }
 
-  /** @test */
-  public function panierParIciLesBonsLivresShouldHaveBeenSaved() {
-    $this->assertTrue(Class_PanierNotice::methodHasBeenCalled('save'));
-  }
-
 
   /** @test */
   public function validFormShouldCreatePanierWithLabelleParIciLesBonsLivres() {
-    $this->assertEquals('Par ici les bons livres', Class_PanierNotice::find(1)->getLibelle());
+    $this->assertEquals('Par ici les bons livres',
+                        Class_PanierNotice::findFirstBy(['order' => 'id desc'])->getLibelle());
   }
 }
 
@@ -1084,7 +1045,6 @@ class PanierControllerCreationPanierSuccessTest extends PanierControllerTestCase
     $lesBonLivres= (new Class_PanierNotice);
     Storm_Test_ObjectWrapper::onLoaderOfModel('Class_PanierNotice')
       ->whenCalled('save')->answers(true)
-      ->whenCalled('maxIdPanierForUser')->answers(1)
       ->whenCalled('getId')->answers(1)
       ->whenCalled('find')->answers((new Class_PanierNotice())
                                     ->setUser($this->manon)
@@ -1194,13 +1154,8 @@ class PanierControllerSupprimerNoticeBlacksadFromBDAndRedirectToRefererTest exte
 
   /** @test */
   public function afterDeletePanierShouldContainsOnlyCombatOrdinaire() {
-    $this->assertEquals('COMBAT ORDINAIRE', $this->panier_bd->getNotices());
-  }
-
-
-  /** @test */
-  public function afterDeletePanierShouldHaveBeenSaved() {
-    $this->assertTrue(Class_PanierNotice::methodHasBeenCalled('save'));
+    Class_PanierNotice::clearCache();
+    $this->assertEquals('COMBAT ORDINAIRE', Class_PanierNotice::find(2)->getNotices());
   }
 
 
@@ -1382,16 +1337,15 @@ class PanierControllerEditActionAsAbonneTest extends AbstractControllerTestCase
 
 
 class PanierControllerEditActionAsAdminTest extends AbstractControllerTestCase {
+  protected
+    $_storm_default_to_volatile = true;
+
   public function setup() {
     parent::setup();
 
     Class_Users::beVolatile();
     Class_PanierNotice::beVolatile();
 
-    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_PanierNotice')
-      ->whenCalled('findAllWithCatalogue')
-      ->answers([]);
-
     $roger = Class_Users::newInstanceWithId(23, ['pseudo' => 'RogerL',
                                                  'nom' => 'plou',
                                                  'login' => 'man',
@@ -1432,17 +1386,12 @@ class PanierControllerEditActionAsAdminTest extends AbstractControllerTestCase {
 
 
 class PanierControllerEditActionAsContributeurWithOutRightForAccessDomaineTest extends AbstractControllerTestCase {
+  protected
+    $_storm_default_to_volatile = true;
+
   public function setup() {
     parent::setup();
 
-    Class_Users::beVolatile();
-    Class_PanierNotice::beVolatile();
-    Class_UserGroup::beVolatile();
-
-    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_PanierNotice')
-      ->whenCalled('findAllWithCatalogue')
-      ->answers([]);
-
     $roger = Class_Users::newInstanceWithId(23, ['pseudo' => 'RogerL',
                                                  'nom' => 'plou',
                                                  'login' => 'man',
diff --git a/tests/application/modules/opac/controllers/ProfilOptionsControllerTest.php b/tests/application/modules/opac/controllers/ProfilOptionsControllerTest.php
index 36620c78a3190c19d8c17f935eb6930b0304182e..55abf04364d8c6030072ace6e454929acc2a0015 100644
--- a/tests/application/modules/opac/controllers/ProfilOptionsControllerTest.php
+++ b/tests/application/modules/opac/controllers/ProfilOptionsControllerTest.php
@@ -87,7 +87,7 @@ abstract class ProfilOptionsControllerWithProfilAdulteTestCase extends AbstractC
                                                          'picto' => 'vide.gif',
                                                          'preferences' => [
                                                                            'titre' => 'Nouvelles',
-                                                                           'nb_aff' => 0]],
+                                                                           'nb_aff' => 2]],
 
 
                                                         ['type_menu' => 'PROFIL',
@@ -363,28 +363,13 @@ class ProfilOptionsControllerProfilAdulteWithCacheTest extends ProfilOptionsCont
 class ProfilOptionsControllerTwitterLinkWithProfilAdulteTest extends ProfilOptionsControllerWithProfilAdulteTestCase {
   protected $_mock_web_client;
 
-  public function setUp() {
-    parent::setUp();
-    $this->_mock_web_client = Storm_Test_ObjectWrapper::on(new Class_WebService_SimpleWebClient());
-    ZendAfi_View_Helper_ShareUrl::setDefaultWebClient($this->_mock_web_client);
-
-    $this->_mock_web_client
-      ->whenCalled('open_url')
-      ->answers('http://is.gd/PkdNgD');
-
-  }
-
-
-  public function tearDown() {
-    ZendAfi_View_Helper_ShareUrl::resetDefaultWebClient();
-    parent::tearDown();
-  }
-
-
   /** @test */
   public function twitterLinkShouldReturnJavascriptForTweet() {
-    $this->dispatch('/opac/index/share/on/twitter/titre/Profil+Adulte?url='.urlencode('http://localhost'.BASE_URL.'/index/index'), true);
-    $this->assertContains("window.open('http://twitter.com/share?url=http%3A%2F%2Fis.gd%2FPkdNgD&text=Profil+Adulte&counturl=http%3A%2F%2Fis.gd%2FPkdNgD','_blank','toolbar=0,status=0,width=800, height=410');",
+    $url = 'http://localhost'.BASE_URL.'/index/index';
+    $this->dispatch('/opac/index/share/on/twitter/titre/Profil+Adulte?url=' . urlencode($url), true);
+
+    $expected_url = urlencode('http://localhost'.BASE_URL.'/index/index?id_profil=22');
+    $this->assertContains("window.open('http://twitter.com/share?url=" . $expected_url . "&text=Profil+Adulte&counturl=" . $expected_url . "','_blank','toolbar=0,status=0,width=800, height=410');",
                           $this->_response->getBody());
   }
 
diff --git a/tests/application/modules/opac/controllers/RechercheControllerAlbum1DTouchTest.php b/tests/application/modules/opac/controllers/RechercheControllerAlbum1DTouchTest.php
index 8ffa9ef5c0ad7506119587d8fcd63660f9d24b53..e908af5683fa6d38fdf3b5ba86027a570bd4f810 100644
--- a/tests/application/modules/opac/controllers/RechercheControllerAlbum1DTouchTest.php
+++ b/tests/application/modules/opac/controllers/RechercheControllerAlbum1DTouchTest.php
@@ -66,6 +66,11 @@ class RechercheControllerAlbum1DTouchWithSSOTest
                    ['id' => 'ONEDTOUCH_ID',
                     'clef' => 'ONEDTOUCH_ID',
                     'valeur' => 'my_bib']);
+
+    $this->fixture('Class_AdminVar',
+                   ['id' => 'ONEDTOUCH_VERSION_URL',
+                    'clef' => 'ONEDTOUCH_VERSION_URL',
+                    'valeur' => Class_OneDTouchLink::OLD_VERSION]);
   }
 
 
@@ -74,6 +79,32 @@ class RechercheControllerAlbum1DTouchWithSSOTest
     $this->assertXPathContentContains('//a[@href="http://music.1dtouch.com/users/auth/my_bib?dest=albums/1"]',
                                       'l\'album sur 1DTouch');
   }
+
+}
+
+
+class RechercheControllerAlbum1DTouchWithSSOVersion2Test
+  extends RechercheControllerAlbum1DTouchTestCase {
+
+  protected function _prepareFixtures() {
+    $this->fixture('Class_AdminVar',
+                   ['id' => 'ONEDTOUCH_ID',
+                    'clef' => 'ONEDTOUCH_ID',
+                    'valeur' => 'my_bib']);
+
+    $this->fixture('Class_AdminVar',
+                   ['id' => 'ONEDTOUCH_VERSION_URL',
+                    'clef' => 'ONEDTOUCH_VERSION_URL',
+                    'valeur' => Class_OneDTouchLink::NEW_VERSION]);
+  }
+
+
+  /** @test */
+  public function externalUrlWithBibParamAsUrlShouldBeSSO() {
+
+    $this->assertXPathContentContains('//a[@href="http://music.1dtouch.com/users/auth/afi?bibid=my_bib&dest=albums/1"]',
+                                      'l\'album sur 1DTouch',$this->_response->getBody());
+  }
 }
 
 
diff --git a/tests/application/modules/opac/controllers/RechercheControllerTest.php b/tests/application/modules/opac/controllers/RechercheControllerTest.php
index d6aa5054515a45ea847ca40b41fcb52ed0fa49bc..6f301b06b2450f1a1e81fbbd26bb35ca52ee1ab6 100644
--- a/tests/application/modules/opac/controllers/RechercheControllerTest.php
+++ b/tests/application/modules/opac/controllers/RechercheControllerTest.php
@@ -137,41 +137,6 @@ class RechercheControllerPrintTest extends RechercheControllerNoticeTestCase {
 
 
 
-
-class RechercheControllerReseauTest extends RechercheControllerNoticeTestCase {
-  public function setUp() {
-    ZendAfi_View_Helper_ShareUrl::setDefaultWebClient(Storm_Test_ObjectWrapper::mock()
-                                                      ->whenCalled('open_url')
-                                                      ->answers(false));
-    parent::setUp();
-    $this->dispatch(sprintf('recherche/reseau/id_notice/%d/type_doc/1',
-                            $this->notice->getId()),
-                    true);
-  }
-
-
-  public function tearDown() {
-    parent::tearDown();
-    ZendAfi_View_Helper_ShareUrl::setDefaultWebClient(null);
-  }
-
-
-  /** @test */
-  public function getResauShouldContainsTwitterGif() {
-    $this->assertXPath('//img[contains(@src, "twitter.gif")]');
-  }
-
-
-  /** @test */
-  public function getResauShouldContainsTwitterLink() {
-    $this->assertContains("$.getScript('/social-network/share/id_notice/345/type_doc/1/on/twitter/url",
-                          $this->_response->getBody());
-  }
-}
-
-
-
-
 class RechercheControllerViewNoticeBabelthequeTest extends RechercheControllerNoticeTestCase {
   /** @test */
   public function withoutBabelthequeJSShouldNotBeLoaded() {
@@ -2322,7 +2287,7 @@ class RechercheControllerAjoutNoticePanierUrlWithMurConfigTest extends Recherche
 
   /** @test **/
   public function permalinkShouldBeDisplay() {
-    $this->assertXPathContentContains('//span', "recherche/viewnotice/expressionRecherche/potter/facettes/T1/facette/B1/page/2/clef/PETITESSCENESDEBALCONTERRASSE-SUIVIDE100PLANTESPO---RUSTICA-2009-1/id/42225?id_profil=2",$this->_response->getBody());
+    $this->assertXPath('//img[contains(@class, "permalink")][contains(@data-url, "recherche/viewnotice/expressionRecherche/potter/facettes/T1/facette/B1/page/2/")]');
   }
 
 
diff --git a/tests/application/modules/opac/controllers/SocialNetworkControllerTest.php b/tests/application/modules/opac/controllers/SocialNetworkControllerTest.php
index 554e4f372f0f119314c7c99d5ece853a8767b809..ed8dead0ad755d80ed7a2acf97f276f93a6f057b 100644
--- a/tests/application/modules/opac/controllers/SocialNetworkControllerTest.php
+++ b/tests/application/modules/opac/controllers/SocialNetworkControllerTest.php
@@ -21,37 +21,11 @@
 require_once 'AbstractControllerTestCase.php';
 
 class SocialNetworkControllerShareActionTest extends AbstractControllerTestCase {
-  protected $_mock_web_client;
-
-  public function setUp() {
-    parent::setUp();
-    $this->_mock_web_client = Storm_Test_ObjectWrapper::on(new Class_WebService_SimpleWebClient());
-    ZendAfi_View_Helper_ShareUrl::setDefaultWebClient($this->_mock_web_client);
-  }
-
-
-  public function tearDown() {
-    ZendAfi_View_Helper_ShareUrl::resetDefaultWebClient();
-    parent::tearDown();
-  }
-
-
-  protected function _expectClientOpenUrlWithLongUrlAndAnswer($url, $answer) {
-      $this->_mock_web_client
-        ->whenCalled('open_url')
-        ->with(sprintf('http://is.gd/api.php?longurl=%s', urlencode($url)))
-        ->answers($answer)
-        ->beStrict();
-  }
-
-
   /** @test */
   public function shareOnTwitterShouldInjectShortUrlAndMessageAndCountUrl() {
-    $this->_expectClientOpenUrlWithLongUrlAndAnswer('http://www.institut-francais.com',
-                                                    'http://is.gd/PkdNgD');
     $this->dispatch('/social-network/share/on/twitter/url/'.urlencode('http://www.institut-francais.com').'/titre/'.urlencode('Vive bucarest !').'/counturl/'.urlencode('http://www.institut-francais.com'), true);
 
-    $this->assertEquals("window.open('http://twitter.com/share?url=http%3A%2F%2Fis.gd%2FPkdNgD&text=Vive+bucarest+%21&counturl=http%3A%2F%2Fis.gd%2FPkdNgD','_blank','toolbar=0,status=0,width=800, height=410');",
+    $this->assertEquals("window.open('http://twitter.com/share?url=http%3A%2F%2Fwww.institut-francais.com&text=Vive+bucarest+%21&counturl=http%3A%2F%2Fwww.institut-francais.com','_blank','toolbar=0,status=0,width=800, height=410');",
                         $this->_response->getBody());
   }
 
diff --git a/tests/fixtures/onedtouch_error_response.html b/tests/fixtures/onedtouch_error_response.html
new file mode 100644
index 0000000000000000000000000000000000000000..c14892b3bc38555581a8fc9c8d1306a86f576f75
--- /dev/null
+++ b/tests/fixtures/onedtouch_error_response.html
@@ -0,0 +1,7 @@
+<html>
+<head><title>504 Gateway Time-out</title></head>
+<body bgcolor="white">
+<center><h1>504 Gateway Time-out</h1></center>
+<hr><center>nginx/1.4.6 (Ubuntu)</center>
+</body>
+</html>
diff --git a/tests/library/Class/AvisNoticeTest.php b/tests/library/Class/AvisNoticeTest.php
index 392e64d903698cdce9b3edd233af9e5b45c18a57..3da89743ccca2597475d1430f093575091c6cfc2 100644
--- a/tests/library/Class/AvisNoticeTest.php
+++ b/tests/library/Class/AvisNoticeTest.php
@@ -603,14 +603,14 @@ class AvisLoaderGetAvisFromPreferencesTest extends AvisTestFindAllTestCase {
   public function testDefaultSQLQuery() {
     $this->assertQueryIs("SELECT `notices_avis`.* ".
                          "FROM `notices_avis` ".
-                         "WHERE (flags=0) ORDER BY `DATE_AVIS` DESC");
+                         "WHERE (flags=0) ORDER BY `DATE_AVIS` DESC LIMIT 30");
   }
 
   public function testWithAllAndModoAPosteriori() {
     $this->preferences['abon_ou_bib'] = 'all';
     $this->assertQueryIs("SELECT `notices_avis`.* ".
                          "FROM `notices_avis` ".
-                         "WHERE (flags=0) ORDER BY `DATE_AVIS` DESC");
+                         "WHERE (flags=0) ORDER BY `DATE_AVIS` DESC LIMIT 30");
   }
 
 
@@ -620,7 +620,7 @@ class AvisLoaderGetAvisFromPreferencesTest extends AvisTestFindAllTestCase {
     $this->assertQueryIs("SELECT `notices_avis`.* ".
                          "FROM `notices_avis` ".
                          "WHERE (flags=0) AND ((STATUT=1 OR ABON_OU_BIB=1)) ".
-                         "ORDER BY `DATE_AVIS` DESC");
+                         "ORDER BY `DATE_AVIS` DESC LIMIT 30");
   }
 
 
@@ -630,7 +630,7 @@ class AvisLoaderGetAvisFromPreferencesTest extends AvisTestFindAllTestCase {
     $this->assertQueryIs("SELECT `notices_avis`.* ".
                          "FROM `notices_avis` ".
                          "WHERE (flags=0) AND ((STATUT=1 OR ABON_OU_BIB=0)) ".
-                         "ORDER BY `DATE_AVIS` DESC");
+                         "ORDER BY `DATE_AVIS` DESC LIMIT 30");
   }
 
 
@@ -644,7 +644,7 @@ class AvisLoaderGetAvisFromPreferencesTest extends AvisTestFindAllTestCase {
                          "FROM `notices_avis` ".
                          "WHERE (flags=0) AND ((STATUT=1 OR ABON_OU_BIB=1) ".
                          "AND (STATUT=1 OR ABON_OU_BIB=0)) ".
-                         "ORDER BY `DATE_AVIS` DESC");
+                         "ORDER BY `DATE_AVIS` DESC LIMIT 30");
   }
 
 
@@ -653,7 +653,7 @@ class AvisLoaderGetAvisFromPreferencesTest extends AvisTestFindAllTestCase {
     $this->assertQueryIs("SELECT `notices_avis`.* ".
                          "FROM `notices_avis` ".
                          "WHERE (flags=0) AND (ABON_OU_BIB='0') ".
-                         "ORDER BY `DATE_AVIS` DESC");
+                         "ORDER BY `DATE_AVIS` DESC LIMIT 30");
   }
 
 
@@ -665,7 +665,7 @@ class AvisLoaderGetAvisFromPreferencesTest extends AvisTestFindAllTestCase {
                          "FROM `notices_avis` ".
                          "WHERE (flags=0) AND (ABON_OU_BIB='0') ".
                          "AND ((STATUT=1 OR ABON_OU_BIB=1)) ".
-                         "ORDER BY `DATE_AVIS` DESC");
+                         "ORDER BY `DATE_AVIS` DESC LIMIT 30");
   }
 
 
@@ -674,7 +674,7 @@ class AvisLoaderGetAvisFromPreferencesTest extends AvisTestFindAllTestCase {
     $this->assertQueryIs("SELECT `notices_avis`.* ".
                          "FROM `notices_avis` ".
                          "WHERE (flags=0) AND (ABON_OU_BIB='1') ".
-                         "ORDER BY `DATE_AVIS` DESC");
+                         "ORDER BY `DATE_AVIS` DESC LIMIT 30");
   }
 
   public function testWithBiblioAndModoAPriori() {
@@ -685,7 +685,7 @@ class AvisLoaderGetAvisFromPreferencesTest extends AvisTestFindAllTestCase {
                          "FROM `notices_avis` ".
                          "WHERE (flags=0) AND (ABON_OU_BIB='1') ".
                          "AND ((STATUT=1 OR ABON_OU_BIB=0)) ".
-                         "ORDER BY `DATE_AVIS` DESC");
+                         "ORDER BY `DATE_AVIS` DESC LIMIT 30");
   }
 }
 
@@ -865,6 +865,7 @@ class AvisNoticeAvisFromPreferencesTest extends Storm_Test_ModelTestCase {
       ->with(['order' => 'DATE_AVIS DESC',
               'clef_oeuvre' => ['POTTER'],
               'flags' => '0',
+              'limitPage' => [1, 30],
               'where' => '(STATUT=1 OR ABON_OU_BIB=1) AND (STATUT=1 OR ABON_OU_BIB=0)'])
       ->answers([$this->_avis_bib_moderated, $this->_avis_abon_moderated]);
 
@@ -882,6 +883,7 @@ class AvisNoticeAvisFromPreferencesTest extends Storm_Test_ModelTestCase {
               'clef_oeuvre' => ['POTTER'],
               'ABON_OU_BIB' => 0,
               'flags' => 0,
+              'limitPage' => [1, 30],
               'where' => '(STATUT=1 OR ABON_OU_BIB=1) AND (STATUT=1 OR ABON_OU_BIB=0)'])
       ->answers([$this->_avis_abon_moderated]);
 
@@ -898,6 +900,7 @@ class AvisNoticeAvisFromPreferencesTest extends Storm_Test_ModelTestCase {
               'clef_oeuvre' => ['POTTER'],
               'ABON_OU_BIB' => 1,
               'flags' => 0,
+              'limitPage' => [1, 30],
               'where' => '(STATUT=1 OR ABON_OU_BIB=1) AND (STATUT=1 OR ABON_OU_BIB=0)'])
       ->answers([$this->_avis_bib_moderated]);
 
@@ -916,6 +919,7 @@ class AvisNoticeAvisFromPreferencesTest extends Storm_Test_ModelTestCase {
               'clef_oeuvre' => ['POTTER'],
               'ABON_OU_BIB' => 0,
               'flags' => 0,
+              'limitPage' => [1, 30],
               'where' => '(STATUT=1 OR ABON_OU_BIB=0)'])
       ->answers([$this->_avis_abon_moderated, $this->_avis_abon_not_moderated]);
 
@@ -934,6 +938,7 @@ class AvisNoticeAvisFromPreferencesTest extends Storm_Test_ModelTestCase {
       ->with(['order' => 'DATE_AVIS DESC',
               'clef_oeuvre' => ['POTTER'],
               'flags' => 0,
+              'limitPage' => [1, 30],
               'where' => '(STATUT=1 OR ABON_OU_BIB=0)'])
       ->answers([$this->_avis_bib_moderated, $this->_avis_abon_moderated, $this->_avis_abon_not_moderated]);
 
@@ -943,6 +948,26 @@ class AvisNoticeAvisFromPreferencesTest extends Storm_Test_ModelTestCase {
   }
 
 
+  /** @test */
+  public function withNbAffTwoAvisShouldLimitPageToSix() {
+    Class_AdminVar::newInstanceWithId('MODO_AVIS', ['valeur' => 0]);
+
+    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_AvisNotice')
+      ->whenCalled('findAllBy')
+      ->with(['order' => 'DATE_AVIS DESC',
+              'clef_oeuvre' => ['POTTER'],
+              'flags' => 0,
+              'limitPage' => [1, 6],
+              'where' => '(STATUT=1 OR ABON_OU_BIB=0)'])
+      ->answers([$this->_avis_bib_moderated, $this->_avis_abon_moderated, $this->_avis_abon_not_moderated]);
+
+    $this->assertEquals([$this->_avis_bib_moderated, $this->_avis_abon_moderated, $this->_avis_abon_not_moderated],
+                        Class_AvisNotice::getAvisFromPreferences(['id_panier' => 1,
+                                                                  'nb_aff_avis' => 2,
+                                                                  'abon_ou_bib' => 'all']));
+  }
+
+
 
   /** @test */
   public function withAPosterioriBibModerationAllAvisShouldReturnModeratedRatingFromAbon() {
@@ -954,6 +979,7 @@ class AvisNoticeAvisFromPreferencesTest extends Storm_Test_ModelTestCase {
       ->with(['order' => 'DATE_AVIS DESC',
               'clef_oeuvre' => ['POTTER'],
               'flags' => 0,
+              'limitPage' => [1, 30],
               'where' => '(STATUT=1 OR ABON_OU_BIB=1)'])
       ->answers([$this->_avis_bib_moderated, $this->_avis_bib_not_moderated, $this->_avis_abon_moderated]);
 
@@ -978,6 +1004,7 @@ class AvisNoticeAvisFromPreferencesTest extends Storm_Test_ModelTestCase {
       ->whenCalled('findAllBy')
       ->with(['order' => 'DATE_AVIS DESC',
               'flags' => 0,
+              'limitPage' => [1, 30],
               'id_notice' => -1])
       ->answers([$this->_avis_bib_moderated, $this->_avis_bib_not_moderated, $this->_avis_abon_moderated]);
 
diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseItemFacetsTest.php b/tests/library/Class/Cosmogramme/Integration/PhaseItemFacetsTest.php
index e9557875b50f7b20270c61114f2b808f12d4faf9..d7b9cc1f40410ee8ce62f9402dbcad800feab99e 100644
--- a/tests/library/Class/Cosmogramme/Integration/PhaseItemFacetsTest.php
+++ b/tests/library/Class/Cosmogramme/Integration/PhaseItemFacetsTest.php
@@ -25,6 +25,7 @@ abstract class PhaseItemFacetsTestCase extends Class_Cosmogramme_Integration_Pha
     parent::setUp();
 
     $this->_phase = $this->_buildPhase('ItemFacets')
+                         ->setMemoryCleaner(function() {})
                          ->noDbReset()
                          ->run();
   }
@@ -87,7 +88,7 @@ class PhaseItemFacetsExpectedPreviousPhaseTest extends PhaseItemFacetsTestCase {
 
   /** @test */
   public function lastFacetsUpdateDateShouldBeSet() {
-    $this->assertNotEquals('', Class_CosmoVar::getValueOf('date_maj_facettes'));
+    $this->assertNotEmpty(Class_CosmoVar::getValueOf('date_maj_facettes'));
   }
 }
 
@@ -111,4 +112,27 @@ abstract class PhaseItemFacetsCallbackTest extends PhaseItemFacetsTestCase {
                                 ['id' => 1,
                                  'date_maj' => '2015-04-05 15:08:34'])]);
   }
+}
+
+
+
+class PhaseItemFacetsExpectedExceptionPhaseTest extends PhaseItemFacetsTestCase {
+  protected function _getPreviousPhase() {
+    return (new Class_Cosmogramme_Integration_Phase(4))
+      ->beCron();
+  }
+
+
+  protected function _prepareFixtures() {
+    $this
+      ->onLoaderOfModel('Class_Notice')
+      ->whenCalled('findAllAfter')
+      ->answers('error');
+  }
+
+
+  /** @test */
+  public function logShouldContainsPhaseLabel() {
+    $this->assertLogContains('<h4>Mise à jour des facettes exemplaires</h4><span class="vert"> 0 records updated </span><p class="rouge">Erreur lors de l\'execution de la phase Mise à jour des facettes exemplaires : </br>Invalid argument supplied for foreach()</p>');
+  }
 }
\ No newline at end of file
diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTestCase.php b/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTestCase.php
index 7095a3c7a522e35e6ca13893fe7b320e97a33da1..0c8fd99ce43e6676e2f89a8a0ce12f9b11be1819 100644
--- a/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTestCase.php
+++ b/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTestCase.php
@@ -28,7 +28,9 @@ class PhaseNoticeTestCase extends Class_Cosmogramme_Integration_PhaseTestCase {
     $this->fixture('Class_CosmoVar',
                    ['id' => 'unimarc_zone_matiere', 'valeur' => '610a']);
 
-    $this->_phase = $this->_buildPhase('Notice')->run();
+    $this->_phase = $this->_buildPhase('Notice')
+                         ->setMemoryCleaner(function() {})
+                         ->run();
     Class_Notice::clearCache();
     Class_Exemplaire::clearCache();
   }
diff --git a/tests/library/Class/Cosmogramme/Integration/PhasePanierTest.php b/tests/library/Class/Cosmogramme/Integration/PhasePanierTest.php
index e60477f5be71db5377a1e7453d30e07c148008eb..443763cea4ed558d0b205725eb0d54f391d52acc 100644
--- a/tests/library/Class/Cosmogramme/Integration/PhasePanierTest.php
+++ b/tests/library/Class/Cosmogramme/Integration/PhasePanierTest.php
@@ -61,8 +61,9 @@ abstract class PhasePanierTestCase extends Class_Cosmogramme_Integration_PhaseTe
     parent::setUp();
 
     $this->_phase = $this->_buildPhase('Panier')
-      ->setPrinter($this->_printer)
-      ->run();
+                         ->setMemoryCleaner(function() {})
+                         ->setPrinter($this->_printer)
+                         ->run();
   }
 }
 
diff --git a/tests/library/Class/Cosmogramme/Integration/PhasePatronsTest.php b/tests/library/Class/Cosmogramme/Integration/PhasePatronsTest.php
index cd123f5255169a8b53c38d23bcc25fa8f497db22..cdcd4dcbe7dce15ef6b83f757cd6cdad522e0162 100644
--- a/tests/library/Class/Cosmogramme/Integration/PhasePatronsTest.php
+++ b/tests/library/Class/Cosmogramme/Integration/PhasePatronsTest.php
@@ -68,6 +68,7 @@ abstract class PhasePatronsTestCase extends Class_Cosmogramme_Integration_PhaseT
   public function setUp() {
     parent::setUp();
     $this->_phase = $this->_buildPhase('Patrons')
+                         ->setMemoryCleaner(function() {})
                          ->setPrinter($this->_printer);
   }
 }
diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseReservationTest.php b/tests/library/Class/Cosmogramme/Integration/PhaseReservationTest.php
index 87e43bc6d98bb7a18365b4a2059203bc71207dc8..083363609a6f0a3cf21a38ac6a6ed89036b1bd6d 100644
--- a/tests/library/Class/Cosmogramme/Integration/PhaseReservationTest.php
+++ b/tests/library/Class/Cosmogramme/Integration/PhaseReservationTest.php
@@ -27,7 +27,8 @@ abstract class PhaseReservationTestCase extends Class_Cosmogramme_Integration_Ph
     parent::setUp();
 
     $this->_phase = $this->_buildPhase('Reservation')
-      ->run();
+                         ->setMemoryCleaner(function() {})
+                         ->run();
   }
 
 
diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseReviewsTest.php b/tests/library/Class/Cosmogramme/Integration/PhaseReviewsTest.php
index a5f97cd83d4407c8b0a289b39011b2eb744a03b2..3e38c9ecb4e09fa5183959ed8db976a35c9b0950 100644
--- a/tests/library/Class/Cosmogramme/Integration/PhaseReviewsTest.php
+++ b/tests/library/Class/Cosmogramme/Integration/PhaseReviewsTest.php
@@ -25,6 +25,7 @@ abstract class PhaseReviewsTestCase extends Class_Cosmogramme_Integration_PhaseT
     parent::setUp();
 
     $this->_phase = $this->_buildPhase('Reviews')
+                         ->setMemoryCleaner(function() {})
                          ->noDbReset()
                          ->run();
   }
diff --git a/tests/library/Class/PanierNoticeTest.php b/tests/library/Class/PanierNoticeTest.php
index 4c12f0b26fb5190643bc2e1f5bc83ddd31ba659f..679ce6ca0e3bf8e599b596b077e3791db6d341a6 100644
--- a/tests/library/Class/PanierNoticeTest.php
+++ b/tests/library/Class/PanierNoticeTest.php
@@ -422,6 +422,10 @@ class PanierNoticeWithWrongUserIdTest extends AbstractControllerTestCase {
 class PanierNoticeIndexAllTest extends ModelTestCase {
   public function setUp() {
     parent::setUp();
+
+    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Catalogue')
+      ->whenCalled('saveThesaurus')->answers(true);
+
     $this->fixture('Class_Notice', ['id' => 4,
                                     'titre_principal' => 'Le Montespan',
                                     'auteur_principal' => 'Jean Teulテδゥ',
diff --git a/tests/library/Class/WebService/OneDTouchTest.php b/tests/library/Class/WebService/OneDTouchTest.php
index a8a0182ea5d42f5cc9728639bbdcd90cd619ca31..1846ddbdae974724c91d55ef599a9be7d88bf97a 100644
--- a/tests/library/Class/WebService/OneDTouchTest.php
+++ b/tests/library/Class/WebService/OneDTouchTest.php
@@ -216,4 +216,40 @@ class OneDTouchIncTest extends ModelTestCase {
     $this->assertEquals(1, Class_Album::findFirstBy(['titre' => 'WOLFEP026'])->getId());
   }
 }
-?>
+
+
+
+class oneDTouchWithErrorResponseTest extends ModelTestCase {
+ protected $_storm_default_to_volatile = true;
+
+  public function setUp() {
+    parent::setUp();
+
+    RessourcesNumeriquesFixtures::activate1Dtouch();
+    $error_response = file_get_contents(realpath(dirname(__FILE__)). '/../../../fixtures/onedtouch_error_response.html');
+
+    $this->_http_client = $this->mock();
+    $this->_http_client
+      ->whenCalled('open_url')
+      ->with('http://dev.1dtouch.com/oai?verb=ListRecords&metadataPrefix=oai1dtouch_dc')
+      ->answers($error_response)
+      ->beStrict();
+
+    $this->fixture('Class_WebService_HarvestLog',
+                   ['id' => 1,
+                    'end_date' => '2015-02-01',
+                    'type_doc' => Class_TypeDoc::ONEDTOUCH]);
+
+    $this->_service = new Class_WebService_BibNumerique_OneDTouch();
+    $this->_service->setTimeSource(new TimeSourceForTest('2015-03-18 10:00:00'));
+    Class_WebService_BibNumerique_OneDTouch::setDefaultHttpClient($this->_http_client);
+    $this->_service->harvest();
+    Class_Album::clearCache();
+  }
+
+
+  /** @test */
+  public function shouldNotHaveAlbums() {
+    $this->assertEmpty(Class_Album::findAll());
+  }
+}
\ No newline at end of file
diff --git a/tests/library/ZendAfi/View/Helper/Accueil/PanierTest.php b/tests/library/ZendAfi/View/Helper/Accueil/PanierTest.php
index 80529c25dc5210e146dc80eecb37a78b01c203b2..9add766864f3eeaad7ebb83849e0daf8eec0e902 100644
--- a/tests/library/ZendAfi/View/Helper/Accueil/PanierTest.php
+++ b/tests/library/ZendAfi/View/Helper/Accueil/PanierTest.php
@@ -16,15 +16,13 @@
  *
  * 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';
-
-
 
 abstract class AbstractPanierHelperTest extends ViewHelperTestCase {
-  
-  protected $_tom;
+  protected
+    $_tom,
+    $_storm_default_to_volatile = true;
 
   public function setup() {
     parent:: setup();
@@ -33,12 +31,12 @@ abstract class AbstractPanierHelperTest extends ViewHelperTestCase {
 
     ZendAfi_Auth::getInstance()->logUser($this->_tom);
 
-    $this->_helper = 
-      new ZendAfi_View_Helper_Accueil_Panier(5, 
+    $this->_helper =
+      new ZendAfi_View_Helper_Accueil_Panier(5,
                                              ['type_module' => 'PANIER',
                                               'division' => '1',
                                               'preferences' => ['titre' => 'Panier']] );
-    
+
     $this->_helper->setView(new ZendAfi_Controller_Action_Helper_View());
 
   }
@@ -46,7 +44,7 @@ abstract class AbstractPanierHelperTest extends ViewHelperTestCase {
 
 
 
-class PanierTestWithConnectedUser extends AbstractPanierHelperTest {  
+class PanierTestWithConnectedUser extends AbstractPanierHelperTest {
   public function setUp() {
     parent::setUp();
     $this->_html = $this->_helper->getBoite();
@@ -68,39 +66,53 @@ class PanierTestWithConnectedUser extends AbstractPanierHelperTest {
 
 
 
-class PanierTestWithConnectedUserPanierNoticesFromUserAndNoCurrentPanier extends AbstractPanierHelperTest { 
+
+abstract class PanierTestWithConnectedUserTestCase extends AbstractPanierHelperTest {
   public function setUp() {
     parent::setUp();
-    $cuisiner_la_pomme = 
-      Class_Notice::newInstanceWithId(18, 
-                                      ['titre_principal' => 'Cuisiner la pomme',                                                              
-                                       'clef_alpha' => 'cuisiner la pomme']);
-    $cuisiner_la_poire = 
-      Class_Notice::newInstanceWithId(19, 
-                                      ['titre_principal' => 'Cuisiner la poire',                                                              
-                                       'clef_alpha' => 'cuisiner la poire']);
+    $cuisiner_la_pomme = $this->fixture('Class_Notice',
+                                        ['id' => 18,
+                                         'titre_principal' => 'Cuisiner la pomme',
+                                         'auteur_principal' => 'Tom Apple',
+                                         'clef_alpha' => 'CUISINER-LA-POMME']);
+
+    $cuisiner_la_poire = $this->fixture('Class_Notice',
+                                        ['id' => 19,
+                                         'titre_principal' => 'Cuisiner la poire',
+                                         'auteur_principal' => 'Tom Pear',
+                                         'clef_alpha' => 'CUISINER-LA-POIRE']);
+
+    $panier_cuisine = $this->fixture('Class_PanierNotice',
+                                     ['id' => 987,
+                                      'libelle' => 'Panier cuisine']);
+    $panier_cuisine
+      ->addNotice($cuisiner_la_pomme)
+      ->addNotice($cuisiner_la_poire)
+      ->assertSave();
 
-    $panier_cuisine = 
-      Class_PanierNotice::newInstanceWithId(987, ['libelle' => 'Panier cuisine'])
-      ->setNotices([$cuisiner_la_pomme, $cuisiner_la_poire]);
 
+    $catalogue_adultes = $this->fixture('Class_Catalogue',
+                                        ['id' => 6,
+                                         'libelle' => 'Adultes']);
 
-    $catalogue_adultes = Class_Catalogue::newInstanceWithId(6,['libelle' => 'Adultes']);
+    $panier_romans = $this->fixture('Class_PanierNotice',
+                                    ['id' => 666,
+                                     'libelle' => 'Romans',
+                                     'catalogues' => [$catalogue_adultes]]);
+  }
+}
 
-    $panier_romans = Class_PanierNotice::newInstanceWithId(666, ['libelle' => 'Romans',
-                                                                 'catalogues' => [$catalogue_adultes]]);
 
-    $this->_tom->setPaniers([$panier_cuisine]);
 
-    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_PanierNotice')
-      ->whenCalled('findAllWithCatalogue')
-      ->answers([$panier_romans]);
 
+class PanierTestWithConnectedUserPanierNoticesFromUserAndNoCurrentPanier extends PanierTestWithConnectedUserTestCase {
+  public function setUp() {
+    parent::setUp();
 
     $this->_html = $this->_helper->getBoite();
   }
 
-  
+
   /** @test **/
   public function actionBarShouldNotContainsShareAction() {
     $this->assertNotXPath($this->_html, '//div[@class="panier-action-bar"]/ul/li//input[contains(@value,"recherche/simple/")]');
@@ -116,54 +128,31 @@ class PanierTestWithConnectedUserPanierNoticesFromUserAndNoCurrentPanier extends
 
 
 
-class PanierTestWithConnectedUserAndCurrentPanierWithNotice extends AbstractPanierHelperTest {  
+class PanierTestWithConnectedUserAndCurrentPanierWithNotice extends PanierTestWithConnectedUserTestCase {
   public function setUp() {
     parent::setUp();
 
-    $cuisiner_la_pomme =  
-      Class_Notice::newInstanceWithId(18, 
-                                      ['titre_principal' => 'Cuisiner la pomme',
-                                       'auteur_principal' => 'Tom Apple',
-                                       'clef_alpha' => 'CUISINER-LA-POMME']);
-    $cuisiner_la_poire = 
-      Class_Notice::newInstanceWithId(19, 
-                                      ['titre_principal' => 'Cuisiner la poire',
-                                       'auteur_principal' => 'Tom Pear',
-                                       'clef_alpha' => 'CUISINER-LA-POIRE']);
-
-    $panier_cuisine = 
-      Class_PanierNotice::newInstanceWithId(987, ['libelle' => 'Panier cuisine'])
-      ->addNotice($cuisiner_la_pomme)
-      ->addNotice($cuisiner_la_poire);
-    
-    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Notice')
-      ->whenCalled('findAllBy')
-      ->answers([$cuisiner_la_pomme, $cuisiner_la_poire]);
-
-    $this->_tom
-      ->setPaniers([$panier_cuisine])
-      ->setPanierCourant($panier_cuisine);
+    $this->_tom->setPanierCourant(Class_PanierNotice::find(987));
 
     $this->_html = $this->_helper->getBoite();
   }
 
-  
+
   /** @test **/
   public function boitePanierShouldDisplayPanierCuisinerLaPomme() {
-    $this->assertXPathContentContains($this->_html, '//tbody/tr[1]', 'Cuisiner la pomme', $this->_html);
+    $this->assertXPathContentContains($this->_html, '//tbody/tr[2]', 'Cuisiner la pomme', $this->_html);
   }
 
-  
+
   /** @test **/
   public function boitePanierShouldDisplayPanierCuisinerLaPommeByTomApple() {
-    $this->assertXPathContentContains($this->_html, '//tbody/tr[1]', 'Tom Apple', $this->_html);
+    $this->assertXPathContentContains($this->_html, '//tbody/tr[2]', 'Tom Apple', $this->_html);
   }
 
 
-
   /** @test **/
   public function boitePanierShouldDisplayPanierCuisinerLaPoire() {
-    $this->assertXPathContentContains($this->_html, '//tbody/tr[2]', 'Cuisiner la poire', $this->_html);
+    $this->assertXPathContentContains($this->_html, '//tbody/tr[1]', 'Cuisiner la poire', $this->_html);
   }
 
 
@@ -177,7 +166,7 @@ class PanierTestWithConnectedUserAndCurrentPanierWithNotice extends AbstractPani
   public function rowShouldContainsDelAction() {
     $this->assertXPath($this->_html, '//tbody/tr//a[contains(@href,"/paniersupprimernotice/id_panier/987/id_notice/18/redirect/referer")]');
   }
-  
+
 
   /** @test **/
   public function actionBarShouldContainsAfficherAsResultatDeRechercheAction() {
diff --git a/tests/library/ZendAfi/View/Helper/Accueil/RechSimpleTest.php b/tests/library/ZendAfi/View/Helper/Accueil/RechSimpleTest.php
index 3b6b3c4fa86444671353d28a0798d60619e7507c..e67a637000846b1df9cc459c670dc52b179d2aa1 100644
--- a/tests/library/ZendAfi/View/Helper/Accueil/RechSimpleTest.php
+++ b/tests/library/ZendAfi/View/Helper/Accueil/RechSimpleTest.php
@@ -71,7 +71,7 @@ class ZendAfi_View_Helper_Accueil_RechSimpleWithAdminTest extends ZendAfi_View_H
 
   /** @test */
   public function deleteBlockActionShouldBePresent() {
-    $this->assertLocalXPath('//a[contains(@href, "/admin/accueil/delete-block/id_module/1/division/1")]');
+    $this->assertLocalXPath('//a[contains(@href, "/admin/accueil/delete-block/id_module/1/division/1")][contains(@onclick, "return confirm(")]');
   }
 }
 
diff --git a/tests/library/ZendAfi/View/Helper/Notice/FacettesTypeDocTest.php b/tests/library/ZendAfi/View/Helper/Notice/FacettesTypeDocTest.php
index 4383f1fea08caf4701d4c15ccd0cdf8dc5b8ba2a..cf14bfb1c8867a1afe3575cbb8f14153ee171f17 100644
--- a/tests/library/ZendAfi/View/Helper/Notice/FacettesTypeDocTest.php
+++ b/tests/library/ZendAfi/View/Helper/Notice/FacettesTypeDocTest.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
  */
 
 class ZendAfi_View_Helper_Notice_FacettesTypeDocTest extends ViewHelperTestCase {
@@ -26,29 +26,22 @@ class ZendAfi_View_Helper_Notice_FacettesTypeDocTest extends ViewHelperTestCase
     parent::setUp();
     $this->_helper = new ZendAfi_View_Helper_Notice_FacettesTypeDoc();
     $this->_helper->setView(new ZendAfi_Controller_Action_Helper_View());
-    $this->_html = $this->_helper->notice_FacettesTypeDoc(['T' => [ 'titre' => 'Type de document',
-                                                                    1 => ['id' => 'T1',
-                                                                          'libelle' => 'Livres',
-                                                                          'nombre' => 22],
-                                                                    2 => ['id' => 'T3',
-                                                                          'libelle' => 'DVD',
-                                                                          'nombre' => 34]]]);
+    $this->_html = $this->_helper->notice_FacettesTypeDoc(['T' => ['T1' => 22,
+                                                                   'T3' => 34]]);
   }
 
 
   /** @test */
   public function linkForTypeDocLivreShouldContains22() {
     $this->assertXPathContentContains($this->_html,
-                                      '//div[@class="facettes_type_doc"]//a[@class="type_doc_1"][contains(@href, "facette/T1")]',
-                                      '22');
+                                      '//div[@class="facettes_type_doc"]//a[@class="type_doc_1"][contains(@href, "facette/T1")]', '22');
   }
 
 
   /** @test */
   public function linkForTypeDVDShouldContains34() {
     $this->assertXPathContentContains($this->_html,
-                                      '//div[@class="facettes_type_doc"]//a[@class="type_doc_3"][contains(@href, "facette/T3")]',
-                                      '34');
+                                      '//div[@class="facettes_type_doc"]//a[@class="type_doc_3"][contains(@href, "facette/T3")]', '34');
   }
 }
 ?>
\ No newline at end of file
diff --git a/tests/library/ZendAfi/View/Helper/ShareUrlTest.php b/tests/library/ZendAfi/View/Helper/ShareUrlTest.php
deleted file mode 100644
index e5376d191ce91aa445188e737d15154b550f9080..0000000000000000000000000000000000000000
--- a/tests/library/ZendAfi/View/Helper/ShareUrlTest.php
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-/**
- * Copyright (c) 2012, 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
- */
-require_once 'ViewHelperTestCase.php';
-
-class ZendAfi_View_Helper_ShareUrlTest extends ViewHelperTestCase {
-  public function setUp() {
-    parent::setUp();
-    $this->_mock_web_client = Storm_Test_ObjectWrapper::on(new Class_WebService_SimpleWebClient());
-    ZendAfi_View_Helper_ShareUrl::setDefaultWebClient($this->_mock_web_client);
-
-    $this->_helper = new ZendAfi_View_Helper_ShareUrl();
-    $this->_helper->setView(new ZendAfi_Controller_Action_Helper_View());
-  }
-
-  public function tearDown() {
-    ZendAfi_View_Helper_ShareUrl::resetDefaultWebClient();
-    parent::tearDown();
-  }
-
-
-  /** @test */
-  public function shortenUrlShouldReturnIsGdUrl() {
-    $this->_expectClientOpenUrlWithLongUrlAndAnswer('http://www.institut-francais.com',
-                                                    'http://is.gd/PkdNgD');
-
-    $this->assertEquals('http://is.gd/PkdNgD',
-                        $this->_helper->shortenUrl('http://www.institut-francais.com'));
-  }
-
-
-  /** @test */
-  public function getTwitterUrlViewNoticeShouldReturnShortenUrlWithServerHost() {
-    $_SERVER["HTTP_HOST"] = 'localhost';
-    $this->_expectClientOpenUrlForShortenViewNotice2();
-    $this->assertEquals("http://twitter.com/share?url=http%3A%2F%2Fis.gd%2FPkdNg2&text=&counturl=http%3A%2F%2Fis.gd%2FPkdNg2",
-                        $this->_helper->shareUrl("twitter", '/recherche/viewnotice/id/2'));
-  }
-
-
-  /** @test */
-  public function getTwitterUrlViewNoticeWithMessageShouldReturnShortenUrlWithServerHost() {
-    $_SERVER["HTTP_HOST"] = 'localhost';
-    $this->_expectClientOpenUrlForShortenViewNotice2();
-    $this->assertEquals("http://twitter.com/share?url=http%3A%2F%2Fis.gd%2FPkdNg2&text=venez+voir+%21&counturl=http%3A%2F%2Fis.gd%2FPkdNg2",
-                        $this->_helper->shareUrl("twitter", '/recherche/viewnotice/id/2', 'venez voir !'));
-  }
-
-
-  /** @test */
-  public function shortenUrlWithErrorShouldReturnOriginalUrl() {
-    $this->_expectClientOpenUrlWithLongUrlAndAnswer('http://www.institut-francais.com',
-                                                    'Error');
-
-    $this->assertEquals('http://www.institut-francais.com',
-                        $this->_helper->shortenUrl('http://www.institut-francais.com'));
-  }
-
-
-  /** @test */
-  public function shortenUrlWithNullShouldReturnOriginalUrl() {
-    $this->_expectClientOpenUrlWithLongUrlAndAnswer('http://www.institut-francais.com',
-                                                    null);
-
-    $this->assertEquals('http://www.institut-francais.com',
-                        $this->_helper->shortenUrl('http://www.institut-francais.com'));
-  }
-
-
-  protected function _expectClientOpenUrlWithLongUrlAndAnswer($url, $answer) {
-      $this->_mock_web_client
-        ->whenCalled('open_url')
-        ->with('http://is.gd/api.php?longurl=http%3A%2F%2Flocalhost%2Frecherche%2Fviewnotice%2Fid%2F2')
-        ->answers($answer)
-
-        ->whenCalled('open_url')
-        ->with(sprintf('http://is.gd/api.php?longurl=%s', urlencode($url)))
-        ->answers($answer)
-        ->beStrict();
-
-  }
-
-
-  protected function _expectClientOpenUrlForShortenViewNotice2() {
-    $this->_expectClientOpenUrlWithLongUrlAndAnswer('http://localhost'. BASE_URL .'/recherche/viewnotice/id/2',
-                                                    'http://is.gd/PkdNg2');
-  }
-}
-
-
-?>
\ No newline at end of file