diff --git a/VERSIONS_WIP/50182 b/VERSIONS_WIP/50182
new file mode 100644
index 0000000000000000000000000000000000000000..e61d1ba23a31a4870fa93d0080b428f902d89582
--- /dev/null
+++ b/VERSIONS_WIP/50182
@@ -0,0 +1 @@
+ - ticket #50182 : ajout d'un rapport html + json sur l'état du portail: intégrations, connecteurs, communication SIGB
\ No newline at end of file
diff --git a/application/modules/admin/controllers/HarvestController.php b/application/modules/admin/controllers/HarvestController.php
index b86b03277164bad8c13a91b8638a30d2aa9bc0c1..217841aa3b4df02193745f57bcb7d7a3b7614810 100644
--- a/application/modules/admin/controllers/HarvestController.php
+++ b/application/modules/admin/controllers/HarvestController.php
@@ -116,7 +116,7 @@ class Admin_HarvestController extends ZendAfi_Controller_Action {
 
   public function arteVodAjaxAction() {
     $this->_helper->viewRenderer->setNoRender();
-    if (!Class_AdminVar::isArteVodEnabled())
+    if (!Class_AdminVar::isArteVODEnabled())
       return;
 
     $service = new Class_WebService_BibNumerique_ArteVOD();
diff --git a/application/modules/admin/controllers/SystemeController.php b/application/modules/admin/controllers/SystemeController.php
index 490cf70fea3c6f1acca5cdd9ebcdbfdbfe190b6d..e5089697706eefdb9b3ada1e08f73f05f67d31cf 100644
--- a/application/modules/admin/controllers/SystemeController.php
+++ b/application/modules/admin/controllers/SystemeController.php
@@ -300,5 +300,10 @@ class Admin_SystemeController extends Zend_Controller_Action {
 
     $this->view->form = $form;
   }
+
+
+  public function statusAction() {
+    $this->view->titre = $this->_('Etat du système');
+  }
 }
 ?>
\ No newline at end of file
diff --git a/application/modules/admin/views/scripts/bibnum/index.phtml b/application/modules/admin/views/scripts/bibnum/index.phtml
index d89b99e08ed942cd1619c0cd44ab42dc7928c96a..bddf56a1aa7b4dff0193df5ed2b9b4f5a90abe43 100644
--- a/application/modules/admin/views/scripts/bibnum/index.phtml
+++ b/application/modules/admin/views/scripts/bibnum/index.phtml
@@ -5,10 +5,9 @@ echo $this->_("Bokeh s'interface avec un certain nombre de ressources numérique
 echo $this->_("Si vous souhaitez ajouter une ressource à votre portail, il vous faut contractualiser avec le fournisseur de la ressource et demander un devis pour le connecteur à <a href='mailto:cial-bib@afi-sa.fr'>votre commercial</a>.");
 ?></p>
 <?php
-$datas = json_decode(file_get_contents(__DIR__ . '/../../../../../../public/opac/js/digital_connectors.js'), true);
-
-$datas = array_merge($datas, Class_DigitalResource::getInstance()->getPluginsDescription());
+$datas = (new Class_WebService_BibNumerique_Connectors())->getDescription();
 $datas = json_decode(json_encode($datas));
+
 ?>
 <table class="digital_connectors">
   <tbody>
@@ -46,7 +45,7 @@ $datas = json_decode(json_encode($datas));
                                 ['href' => $connector->sales_contact->url,
                                  'target' => '_blank']);
     ?>
-      <tr>
+      <tr data-code="<?php echo strtolower($connector->code) ?>" >
         <td><?php echo $thumb; ?></td>
         <td><?php echo $connector->desc; ?>
           <?php if ($features) { ?>
@@ -56,6 +55,9 @@ $datas = json_decode(json_encode($datas));
           <?php if ($contact) { ?>
             <br/><br/>
             <?php echo $this->tag('strong', $this->_('Contact : ')) . implode(', ', $contact);?>
+            <br/><br/>
+            <?php if ($connector->enabled)
+              echo $this->tag('div', $this->_('Activé'), ['class' => 'enabled']);?>
           <?php } ?>
         </td>
       </tr>
diff --git a/application/modules/admin/views/scripts/systeme/status.phtml b/application/modules/admin/views/scripts/systeme/status.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..776bef2b19da576cec0c4441e7eb4e478c58d9c6
--- /dev/null
+++ b/application/modules/admin/views/scripts/systeme/status.phtml
@@ -0,0 +1,3 @@
+<?php
+echo $this->status_Html();
+?>
diff --git a/application/modules/opac/controllers/ModulesController.php b/application/modules/opac/controllers/ModulesController.php
index 8233ef1e30960b7188f07dd1cfdbdbaff97f2f2e..fe063e77517161113c60f90d7053d6352b3e1855 100644
--- a/application/modules/opac/controllers/ModulesController.php
+++ b/application/modules/opac/controllers/ModulesController.php
@@ -54,7 +54,7 @@ class ModulesController extends ZendAfi_Controller_Action {
 
 
   public function artevodAction() {
-    $arte = new Class_Systeme_ModulesMenu_ArteVod();
+    $arte = new Class_Systeme_ModulesMenu_ArteVOD();
     return $this->checkNotifyMessage($arte, $arte->getDynamiqueUrl());
   }
 
diff --git a/library/Class/AdminVar.php b/library/Class/AdminVar.php
index d47339a06604b897c041d32f2b6cd2f07ab1fc7f..322ebeedbdb385c51efd05dee281199f10fed09f 100644
--- a/library/Class/AdminVar.php
+++ b/library/Class/AdminVar.php
@@ -159,7 +159,6 @@ class Class_AdminVarLoader extends Storm_Model_Loader {
                                                                            [ 'options' => ['fields' => [['name' => 'site_label', 'label' => $this->_('Nom du site')],
                                                                                                         ['name' => 'site_url', 'label' => $this->_('Url de recherche')] ]]]),
                     'NOM_DOMAINE' => Class_AdminVar_Meta::newDefault($this->_('Nom de domaine principal de l\'OPAC, ex: monopac.macommune.fr')),
-                    'DATE_LAST_FULL_INTEGRATION_USERS' => Class_AdminVar_Meta::newDefault($this->_('Date du dernier import total des abonnés (modifié par cosmogramme)')),
                     'BOITE_PANIER_AUTO' => Class_AdminVar_Meta::newOnOff($this->_('Ajouter automatiquement une boîte panier dans la division flottante')),
                     'EXTRA_SKIN_PATH' => Class_AdminVar_Meta::newDefault($this->_('Chemin vers les skins personnalisées, relatif à %s', Class_Profil_Skin::EXTRA_PATH)),
                     'ENABLE_COLLABORATIVE_BROWSING' => Class_AdminVar_Meta::newOnOff($this->_('Activation de la navigation collaborative')),
@@ -169,6 +168,12 @@ class Class_AdminVarLoader extends Storm_Model_Loader {
                     'URL_COSMOGRAMME' => Class_AdminVar_Meta::newDefault('')->bePrivate(),
                     'PACK_MOBILE' => Class_AdminVar_Meta::newOnOff($this->_('Activation des fonctions avancées du téléphone'))->bePrivate(),
                     'CNIL_CONSENT_ENABLE' => Class_AdminVar_Meta::newOnOff('Affiche la demande de consentement avant l\'insertion de cookies ou autres traceurs')],
+
+       'cosmogramme' => [
+                         'DATE_LAST_FULL_INTEGRATION_USERS' => Class_AdminVar_Meta::newDefault($this->_('Date du dernier import total des abonnés (modifié par cosmogramme)')),
+                         'INTEGRATIONS_TOO_LONG_ALERT_THRESHOLD' => Class_AdminVar_Meta::newDefault($this->_('Seuil d\'alerte en heures pour détecter que les traitements d\'intégration prennent trop de temps. Par défaut: 2', ['value' => 2]))
+       ],
+
        'catalogue' => [
                        'OAI_SERVER' => Class_AdminVar_Meta::newOnOff($this->_('Activation du serveur OAI: permet le moissonnage des domaines par d\'autres logiciels via OAI'))],
        'newsletter' => [
@@ -385,7 +390,7 @@ class Class_AdminVarLoader extends Storm_Model_Loader {
 
     foreach(explode(';', strtolower($langues_value)) as $langue)
       $langues []= trim($langue);
-    return array_unique(array_filter($langues));
+    return array_values(array_unique(array_filter($langues)));
   }
 
 
@@ -650,7 +655,7 @@ class Class_AdminVarLoader extends Storm_Model_Loader {
   /**
    * @return bool
    */
-  public function isArteVodEnabled() {
+  public function isArteVODEnabled() {
     return (('' != Class_AdminVar::get('ARTE_VOD_LOGIN'))
             && ('' != Class_AdminVar::get('ARTE_VOD_KEY'))
             && ('' != Class_AdminVar::get('ARTE_VOD_SSO_KEY')));
@@ -844,7 +849,6 @@ class Class_AdminVar extends Storm_Model_Abstract {
 
   protected $_fixed_id = true;
 
-
   public function getValeur() {
     return $this->_get('valeur');
   }
diff --git a/library/Class/CosmoVar.php b/library/Class/CosmoVar.php
index 77e2eae6b87b71c03738abdf6894161bb5ff4ba3..96e289ba85f47622efcb8f6758e8b529d7194ed4 100644
--- a/library/Class/CosmoVar.php
+++ b/library/Class/CosmoVar.php
@@ -27,8 +27,9 @@ class Class_CosmoVarLoader extends Storm_Model_Loader {
 
 
   public function setValueOf($name, $value) {
-    return ($model = Class_CosmoVar::find($name)) ?
-      $model->setValeur($value)->save() : false;
+    if (!$model = Class_CosmoVar::find($name))
+      $model = Class_CosmoVar::newInstance()->setClef($name);
+    $model->setValeur($value)->save();
   }
 
 
@@ -120,7 +121,7 @@ class Class_CosmoVar extends Storm_Model_Abstract {
   protected $_table_name = 'variables';
   protected $_table_primary = 'clef';
   protected $_loader_class = 'Class_CosmoVarLoader';
-
+  protected $_fixed_id = true;
   const DOUBLE_SEARCH_NONE = 2;
   const DOUBLE_SEARCH_ALPHA_KEY = 1;
   const DOUBLE_SEARCH_IDS = 0;
diff --git a/library/Class/DigitalResource/Config.php b/library/Class/DigitalResource/Config.php
index 5ca9b2d326c4bc992b5479ea050ad1cf0db633bb..743b4dc4fe56b0fb58ec518b4793bbddcf4e2a34 100644
--- a/library/Class/DigitalResource/Config.php
+++ b/library/Class/DigitalResource/Config.php
@@ -90,12 +90,15 @@ class Class_DigitalResource_Config extends Class_Entity {
 
   public function getDescription() {
     return ['label' => static::getName(),
+            'code' => static::getName(),
+            'doctype_id' => static::getName(),
             'url' => $this->getUrl(),
             'image_url' => $this->getIcon(),
             'desc' => $this->getIntroduction(),
             'features' => $this->getFeatures(),
             'sales_contact' => ['mail' => $this->getMail(),
-                                'url' => $this->getMailUrl()]];
+                                'url' => $this->getMailUrl()],
+            'enabled' => $this->isEnabled()];
   }
 
 
diff --git a/library/Class/Systeme/ModulesMenu.php b/library/Class/Systeme/ModulesMenu.php
index b9c5ebdda0ebbd97a1807ad242811ce7bbd1b1db..8a122b1249207777675560c05569816f18aa056d 100644
--- a/library/Class/Systeme/ModulesMenu.php
+++ b/library/Class/Systeme/ModulesMenu.php
@@ -121,7 +121,7 @@ class Class_Systeme_ModulesMenu extends Class_Systeme_ModulesAbstract {
                                      "TOUTAPPRENDRE" => new Class_Systeme_ModulesMenu_ToutApprendre(),
                                      "CVS" => new Class_Systeme_ModulesMenu_CVS(),
                                      "NUMILOG" => new Class_Systeme_ModulesMenu_Numilog(),
-                                     "ARTEVOD" => new Class_Systeme_ModulesMenu_ArteVod(),
+                                     "ARTEVOD" => new Class_Systeme_ModulesMenu_ArteVOD(),
                                      "LEKIOSK" => new Class_Systeme_ModulesMenu_LeKiosk(),
                                      "ORTHODIDACTE" => new Class_Systeme_ModulesMenu_Orthodidacte(),
                                      "MUSICME" => new Class_Systeme_ModulesMenu_MusicMe(),
diff --git a/library/Class/Systeme/ModulesMenu/ArteVod.php b/library/Class/Systeme/ModulesMenu/ArteVOD.php
similarity index 93%
rename from library/Class/Systeme/ModulesMenu/ArteVod.php
rename to library/Class/Systeme/ModulesMenu/ArteVOD.php
index a3b87c84255a38b31ace87ddfbc1555534655093..01d68042ae1a11df4f3965bad2fbbf1fbd51e914 100644
--- a/library/Class/Systeme/ModulesMenu/ArteVod.php
+++ b/library/Class/Systeme/ModulesMenu/ArteVOD.php
@@ -18,7 +18,7 @@
  * along with BOKEH; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
-class Class_Systeme_ModulesMenu_ArteVod extends Class_Systeme_ModulesMenu_Null {
+class Class_Systeme_ModulesMenu_ArteVOD extends Class_Systeme_ModulesMenu_SSOAbstract {
   /** @var string */
   protected $_group = Class_Systeme_ModulesMenu::GROUP_MENU_ABONNES;
 
@@ -61,6 +61,6 @@ class Class_Systeme_ModulesMenu_ArteVod extends Class_Systeme_ModulesMenu_Null {
 
 
   public function isVisibleForProfil($profil) {
-    return Class_AdminVar::isArteVodEnabled();
+    return Class_AdminVar::isArteVODEnabled();
   }
 }
diff --git a/library/Class/Systeme/ModulesMenu/MusicMe.php b/library/Class/Systeme/ModulesMenu/MusicMe.php
index 5e55f411cf577a68f8b080b6bdf1d88821bf8d4e..b0e9d01f93c0ccc4d658f88984cefda5a59154e8 100644
--- a/library/Class/Systeme/ModulesMenu/MusicMe.php
+++ b/library/Class/Systeme/ModulesMenu/MusicMe.php
@@ -18,7 +18,7 @@
  * along with BOKEH; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
-class Class_Systeme_ModulesMenu_MusicMe extends Class_Systeme_ModulesMenu_Null {
+class Class_Systeme_ModulesMenu_MusicMe extends Class_Systeme_ModulesMenu_SSOAbstract {
   /** @var string */
   protected $_group = Class_Systeme_ModulesMenu::GROUP_MENU_ABONNES;
 
diff --git a/library/Class/Systeme/ModulesMenu/Numilog.php b/library/Class/Systeme/ModulesMenu/Numilog.php
index 5e2b7925659ee29b4c724f9a5414a32b1705a5ad..722d935fa0aba783ddcc422b2affbe9912d1012c 100644
--- a/library/Class/Systeme/ModulesMenu/Numilog.php
+++ b/library/Class/Systeme/ModulesMenu/Numilog.php
@@ -18,7 +18,7 @@
  * along with BOKEH; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
-class Class_Systeme_ModulesMenu_Numilog extends Class_Systeme_ModulesMenu_Null {
+class Class_Systeme_ModulesMenu_Numilog extends Class_Systeme_ModulesMenu_SSOAbstract {
   /** @var string */
   protected $_group = Class_Systeme_ModulesMenu::GROUP_MENU_ABONNES;
 
diff --git a/library/Class/Systeme/Report.php b/library/Class/Systeme/Report.php
new file mode 100644
index 0000000000000000000000000000000000000000..adb13dd86acc502e5f024292103d0891c556f8c0
--- /dev/null
+++ b/library/Class/Systeme/Report.php
@@ -0,0 +1,237 @@
+<?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_Systeme_Report extends Class_Systeme_Report_Abstract {
+  public function acceptVisitor($visitor) {
+    $visitor->visitSection('headers' ,
+                           $this->_('Entêtes'),
+                           new Class_Systeme_Report_Headers());
+
+    $visitor->visitSection('portal',
+                           $this->_('Portail'),
+                           new Class_Systeme_Report_Portal());
+
+    $visitor->visitSection('data_integrations',
+                           $this->_('Intégration des données'),
+                           new Class_Systeme_Report_Cosmogramme());
+
+    $visitor->visitSection('records',
+                           $this->_('Notices'),
+                           new Class_Systeme_Report_Records());
+
+    $visitor->visitSection('users',
+                           $this->_('Utilisateurs'),
+                           new Class_Systeme_Report_Users());
+
+    $visitor->visitSection('ils',
+                           $this->_('SIGB'),
+                           new Class_Systeme_Report_Ils());
+
+    $visitor->visitSection('digital_connectors',
+                           $this->_('Ressources Numériques'),
+                           new Class_Systeme_Report_DigitalConnectors());
+
+    $visitor->visitSection('libraries',
+                           $this->_('Bibliothèques'),
+                           new Class_Systeme_Report_Libraries());
+
+    $visitor->visitSection('variables',
+                           $this->_('Variables'),
+                           new Class_Systeme_Report_Variables());
+
+  }
+}
+
+
+
+
+class Class_Systeme_Report_Headers extends Class_Systeme_Report_Abstract {
+ public function acceptVisitor($visitor) {
+   $visitor->visitDatetime('creation_datetime', $this->_('Généré le'), $this->getCurrentTime());
+   $visitor->visitData('version', $this->_('Version'), BOKEH_RELEASE_NUMBER);
+ }
+}
+
+
+
+
+class Class_Systeme_Report_Portal extends Class_Systeme_Report_Abstract {
+ public function acceptVisitor($visitor) {
+   $visitor->visitData('url', $this->_('URL principale'), Class_Url::siteUrl());
+   $visitor->visitData('label', $this->_('Libellé principal'), Class_Profil::getPortail()->getLibelle());
+   $visitor->visitDataArray('skins', $this->_('Thèmes utilisés'), $this->_profilSkins());
+ }
+
+
+  protected function _profilSkins() {
+    return
+      array_values(
+        array_unique((new Storm_Model_Collection(Class_Profil::findTopProfils()))
+                     ->collect('skin')
+                     ->getArrayCopy()));
+  }
+
+}
+
+
+
+
+class Class_Systeme_Report_Records extends Class_Systeme_Report_Abstract {
+ public function acceptVisitor($visitor) {
+   $visitor->visitCounter('all', $this->_('Tous'), Class_Notice::count());
+
+   foreach(Class_TypeDoc::findAll() as $typedoc)
+     $this->_reportTypeDoc($visitor, $typedoc);
+ }
+
+
+ protected function _reportTypeDoc($visitor, $typedoc) {
+   $records_count = [];
+   if ($count = Class_Notice::countBy(['type_doc' => $typedoc->getId()]))
+     $visitor->visitCounter($typedoc->getId(),
+                            $typedoc->getLabel(),
+                            $count);
+ }
+}
+
+
+
+
+class Class_Systeme_Report_Users extends Class_Systeme_Report_Abstract {
+ public function acceptVisitor($visitor) {
+   $visitor->visitCounter('all', $this->_('Tous'), Class_Users::count());
+
+   foreach(ZendAfi_Acl_AdminControllerRoles::getListeRoles() as $id => $label)
+     $visitor->visitCounter($id,
+                            $label,
+                            Class_Users::countBy(['role_level' => $id]));
+ }
+}
+
+
+
+
+class Class_Systeme_Report_Ils extends Class_Systeme_Report_Abstract {
+ public function acceptVisitor($visitor) {
+   $visitor->visitRecordHeader(['type' => $this->_('Type'),
+                                'url' => $this->_('URL'),
+                                'communication_status' => $this->_('Etat de la communication'),
+                                ]);
+
+   foreach(Class_IntBib::findAll() as $int_bib)
+     $this->reportIntBib($int_bib, $visitor);
+ }
+
+
+ public function reportIntBib($int_bib, $visitor) {
+   if (!$ils_service = $int_bib->getSIGBComm())
+     return $this;
+
+   $message = $ils_service->test();
+
+   $ils_type = preg_replace('/.*_(.*)_Service/',
+                            '$1',
+                            get_class($ils_service));
+   $report_communication =  ['type' => strtolower($ils_type),
+                             'url' => $ils_service->getServerRoot(),
+                             'communication_status' => $ils_service->testCommunicationStatus()];
+
+   $visitor->visitRecordValues($report_communication);
+   return $this;
+ }
+}
+
+
+
+class Class_Systeme_Report_DigitalConnectors extends Class_Systeme_Report_Abstract {
+  public function acceptVisitor($visitor) {
+    $visitor->visitRecordHeader(['label' => $this->_('Libellé'),
+                                 'enabled' => $this->_('Activé'),
+                                 'features' =>  $this->_('Fonctionnalités'),
+                                 'album_count' => $this->_('Nombre d\'albums')]);
+
+    array_map(function($description) use ($visitor) { $this->_reportConnector($visitor, $description); },
+              (new Class_WebService_BibNumerique_Connectors())->getDescription());
+  }
+
+
+  protected function _reportConnector($visitor, $description) {
+    $record = ['code' => $description['code'],
+               'label' => $description['label'],
+               'enabled' => $description['enabled'] ? '1' : '0',
+               'features' => $description['features']];
+
+    if ($description['doctype_id'] && in_array('HARVEST', $description['features']))
+      $record['album_count'] = Class_Album::countBy(['type_doc_id' => $description['doctype_id']]);
+
+    if ($description['enabled'] || isset($record['album_count']))
+      $visitor->visitRecordValues($record);
+  }
+}
+
+
+
+
+class Class_Systeme_Report_Libraries extends Class_Systeme_Report_Abstract {
+  public function acceptVisitor($visitor) {
+    $visitor->visitRecordHeader(['label' => $this->_('Label'),
+                                 'address' => $this->_('Adresse'),
+                                 'postal_code' =>  $this->_('CP'),
+                                 'city' => $this->_('Ville'),
+                                 'coordinates' => $this->_('Coordonnées')]);
+
+    foreach(Class_Bib::findAll() as $library) {
+      $report = ['label' => $library->getLibelle(),
+                 'address' => $library->getAdresse(),
+                 'postal_code' => $library->getCp(),
+                 'city' => $library->getVille(),
+                 'coordinates' => ['latitude' => $library->getLatitude(),
+                                   'longitude' => $library->getLongitude()]];
+      $visitor->visitRecordValues($report);
+    }
+  }
+
+}
+
+
+
+
+class Class_Systeme_Report_Variables extends Class_Systeme_Report_Abstract {
+  public function acceptVisitor($visitor) {
+    $visitor->visitData('LANGUES', 'LANGUES', Class_AdminVar::getLangues());
+    (new Storm_Model_Collection(Class_AdminVar::findAll()))
+      ->select('isOnOff')
+      ->eachDo(function($variable) use ($visitor)
+               {
+                 $this->_reportVariable($visitor, $variable);
+               });
+  }
+
+
+  protected function _reportVariable($visitor, $variable) {
+    $visitor->visitData($variable->getClef(),
+                        $variable->getClef(),
+                        $variable->getValeur() ? $variable->getValeur() : 0);
+  }
+}
+
+
+?>
\ No newline at end of file
diff --git a/library/Class/Systeme/Report/Abstract.php b/library/Class/Systeme/Report/Abstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..0dc1123abd2a258ddbe31b728ef00d0a5830efdd
--- /dev/null
+++ b/library/Class/Systeme/Report/Abstract.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
+ */
+
+
+abstract class Class_Systeme_Report_Abstract {
+  use Trait_Translator, Trait_TimeSource;
+  abstract public function acceptVisitor($visitor);
+}
+
+
+?>
\ No newline at end of file
diff --git a/library/Class/Systeme/Report/Cosmogramme.php b/library/Class/Systeme/Report/Cosmogramme.php
new file mode 100644
index 0000000000000000000000000000000000000000..227a2ae0e13784b5be1f55d9bfae9c3c28f960c7
--- /dev/null
+++ b/library/Class/Systeme/Report/Cosmogramme.php
@@ -0,0 +1,105 @@
+<?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_Systeme_Report_Cosmogramme extends Class_Systeme_Report_Abstract {
+  public function acceptVisitor($visitor) {
+    $this->_date_integration = Class_CosmoVar::getValueOf('integration_date');
+    $this
+      ->_reportLastRun($visitor)
+      ->_reportCurrentRun($visitor)
+      ->_reportIntegrationsLate($visitor)
+      ->_reportTasksWaiting($visitor);
+  }
+
+
+  protected function _reportLastRun($visitor) {
+    if ($this->isRunning())
+      return $this;
+
+    $visitor->visitDatetime('last_run',
+                            $this->_('Dernier traitement d\'intégration effectué le'),
+                            $this->_date_integration);
+    return $this;
+  }
+
+
+  protected function _reportCurrentRun($visitor) {
+    if (!$this->isRunning())
+      return $this;
+
+    $visitor->visitDatetime('started_at',
+                            $this->_('Traitement en cours depuis le'),
+                            strtotime($this->_date_integration));
+
+    $visitor->visitData('phase',
+                        $this->_('Phase en cours'),
+                        Class_CosmoVar::getValueOf('traitement_phase'));
+
+    return $this->_reportIntegrationsTooLong($visitor);
+  }
+
+
+  protected function _reportIntegrationsTooLong($visitor) {
+    $hours_from_integration_start = $this->getTimeSource()
+                                         ->hoursFrom(strtotime($this->_date_integration));
+    if ($hours_from_integration_start < Class_AdminVar::getValueOrDefault('INTEGRATIONS_TOO_LONG_ALERT_THRESHOLD'))
+      return $this;
+
+    $visitor->visitAlert('database_blocked',
+                         $this->_('Traitement non terminé depuis'),
+                         'hour',
+                         $hours_from_integration_start);
+    return $this;
+  }
+
+
+  protected function _reportIntegrationsLate($visitor) {
+    if (!$this->_date_integration
+        || (!$frequence = (int)Class_CosmoVar::getValueOf('integration_frequence')))
+      return $this;
+
+    $diff = $this->getTimeSource()->daysFrom(strtotime($this->_date_integration));
+    $late = $diff - $frequence;
+
+    if ($frequence < $diff)
+      $visitor->visitAlert('integration_late',
+                           $this->_('Traitements d\'intégration en retard de'),
+                           'day',
+                           $late);
+    return $this;
+  }
+
+
+  protected function _reportTasksWaiting($visitor) {
+    $count = Class_Cosmogramme_Integration::countBy(['traite' => 'non']);
+
+    $visitor->visitData('queue', $this->_('Fichier(s) en file d\'attente'),
+                        $count);
+    return $this;
+  }
+
+
+  protected function isRunning() {
+    return '1' == Class_CosmoVar::getValueOf('clef_traitements');
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/Class/TimeSource.php b/library/Class/TimeSource.php
index 54bc37b228bc3b4c748a80ccdfaedc13fa50adbc..a165fb0df3f9a75ca44f18f964fb3e0b429870c1 100644
--- a/library/Class/TimeSource.php
+++ b/library/Class/TimeSource.php
@@ -91,6 +91,11 @@ class Class_TimeSource {
 
 
   public function daysFrom($time) {
-    return (int)(($this->time() - $time) / 3660 / 24);
+    return (int)($this->hoursFrom($time) / 24);
   }
+
+  public function hoursFrom($time) {
+    return (int)(($this->time() - $time) / 3660);
+  }
+
 }
\ No newline at end of file
diff --git a/library/Class/Url.php b/library/Class/Url.php
index 467b4aee57e16e5eb0413d017ec3951e9464be9b..bf43638643be20e35517fedf6d65165f42a9bc02 100644
--- a/library/Class/Url.php
+++ b/library/Class/Url.php
@@ -44,9 +44,13 @@ class Class_Url {
 
 
   public static function siteUrl() {
-    return Class_AdminVar::get('NOM_DOMAINE')
+    $url = Class_AdminVar::get('NOM_DOMAINE')
       ? Class_AdminVar::get('NOM_DOMAINE')
       : self::rootUrl() . self::baseUrl();
+
+    return false === strpos($url, '://')
+      ? 'http://' . $url
+      : $url;
   }
 
 
diff --git a/library/Class/WebService/BibNumerique/ArteVOD.php b/library/Class/WebService/BibNumerique/ArteVOD.php
index 7d1e50699d8734b20eb346f7871af18aea67bd51..6407d646165a0ec0a60949ed3efb49d4b78bdcd7 100644
--- a/library/Class/WebService/BibNumerique/ArteVOD.php
+++ b/library/Class/WebService/BibNumerique/ArteVOD.php
@@ -87,7 +87,7 @@ class Class_WebService_BibNumerique_ArteVOD extends Class_WebService_BibNumeriqu
   }
 
   public function isEnabled() {
-    return Class_AdminVar::isArteVodEnabled();
+    return Class_AdminVar::isArteVODEnabled();
   }
 
 
diff --git a/library/Class/WebService/BibNumerique/Connectors.php b/library/Class/WebService/BibNumerique/Connectors.php
new file mode 100644
index 0000000000000000000000000000000000000000..74b3fe40532a47eaf43180eb54e8d24788d52d10
--- /dev/null
+++ b/library/Class/WebService/BibNumerique/Connectors.php
@@ -0,0 +1,64 @@
+<?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_WebService_BibNumerique_Connectors {
+  public function getDescription() {
+    $descriptions = array_merge(
+                                $this->_getDescriptionsFromDigitalConnectorJS(),
+                                Class_DigitalResource::getInstance()->getPluginsDescription());
+    usort($descriptions, [$this, '_compareDescriptions']);
+    return $descriptions;
+  }
+
+
+  protected function _compareDescriptions($a, $b) {
+    if ($a['enabled'] === $b['enabled'])
+      return 0;
+
+
+    if ($a['enabled'] === true)
+      return -1;
+
+    return 1;
+  }
+
+
+  protected function _getDescriptionsFromDigitalConnectorJS() {
+    $datas = json_decode(file_get_contents(ROOT_PATH.'public/opac/js/digital_connectors.js'), true);
+
+    return array_map([$this, '_updateConnector'], array_keys($datas), $datas);
+  }
+
+
+  protected function _updateConnector($key, $connector) {
+    $connector['enabled'] = ($connector['enabled'] == 'PROVIDER')
+      ? ''
+      : call_user_func(['Class_AdminVar', $connector["enabled"]]);
+
+    $connector['code'] = $key;
+
+    $type_doc_constant = 'Class_TypeDoc::' . strtoupper($key);
+    $connector['doctype_id'] = defined($type_doc_constant) ? constant($type_doc_constant) : null;
+    return $connector;
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/Class/WebService/MappedSoapClient.php b/library/Class/WebService/MappedSoapClient.php
index 2e4c16334c7987e0c2c66cd01c5b9d27c3f99ac4..51a22c57d9cd3b7a4afb581c94ad5286f1da435d 100644
--- a/library/Class/WebService/MappedSoapClient.php
+++ b/library/Class/WebService/MappedSoapClient.php
@@ -25,7 +25,9 @@
  */
 class Class_WebService_MappedSoapClient extends SoapClient {
   protected static $_logger;
-  protected $_soap_server;
+  protected
+    $_wsdl_url,
+    $_soap_server;
 
   public static function setLogger($logger) {
     static::$_logger = $logger;
@@ -81,6 +83,8 @@ class Class_WebService_MappedSoapClient extends SoapClient {
 
 
   public function __construct($wsdl, $options=[]) {
+    $this->_wsdl_url = $wsdl;
+
     $options['exceptions'] = true;
     if (static::$_logger) {
       $options['trace'] = true;
@@ -95,6 +99,11 @@ class Class_WebService_MappedSoapClient extends SoapClient {
   }
 
 
+  public function getWsdlUrl() {
+    return $this->_wsdl_url;
+  }
+
+
   public function setServer($server) {
     $this->_soap_server = $server;
     return $this;
diff --git a/library/Class/WebService/Redmine.php b/library/Class/WebService/Redmine.php
index 6cbc609bad04b5fc9418c1162254a9d3b5a92755..daa11a004ac154787da22d2b59b08fa2076791c7 100644
--- a/library/Class/WebService/Redmine.php
+++ b/library/Class/WebService/Redmine.php
@@ -20,34 +20,34 @@
  */
 
 class Class_WebService_Redmine extends Class_WebService_Abstract {
-  use Trait_Translator;
+   use Trait_Translator;
 
-  const CUSTOM_PRIORITY_ID = 5;
-  const CUSTOM_MODULE_ID = 37;
-  const CUSTOM_CONTACT_PERSON = 43;
-  const CUSTOM_CUSTOMER = 1;
-  const CUSTOM_QUALIFICATION = 38;
+   const CUSTOM_PRIORITY_ID = 5;
+   const CUSTOM_MODULE_ID = 37;
+   const CUSTOM_CONTACT_PERSON = 43;
+   const CUSTOM_CUSTOMER = 1;
+   const CUSTOM_QUALIFICATION = 38;
 
-  protected static $_redmine_client, $_admin_client;
+   protected static $_redmine_client, $_admin_client;
 
-  protected
-    $_library,
-    $_custom_fields_cache,
-    $_issue_statuses_cache,
-    $_issue_priorities_cache;
+   protected
+     $_library,
+     $_custom_fields_cache,
+     $_issue_statuses_cache,
+     $_issue_priorities_cache;
 
 
-  public function __construct($library) {
-    $this->_library = $library;
-  }
+   public function __construct($library) {
+     $this->_library = $library;
+   }
 
 
-  public function getLibrary() {
-    return $this->_library;
-  }
+   public function getLibrary() {
+     return $this->_library;
+   }
 
 
-  protected function missingApiRequirement() {
+   protected function missingApiRequirement() {
     return ($error_message = $this->validate())
       ? ['error_message' => $error_message]
       : null;
@@ -139,10 +139,16 @@ class Class_WebService_Redmine extends Class_WebService_Abstract {
   protected function getIssuesWithParams($params=[]) {
     $params['project_id'] = Class_AdminVar::get('REDMINE_PROJECT_ID');
 
-    $data = $this->getIssueApi()->all($params);
+    try {
+      $data = $this->getIssueApi()->all($params);
+    } catch (Exception $e) {
+      return [];
+    }
+
     if (!isset($data['issues']))
       return [];
 
+
     return array_map([$this, 'newIssue'],
                      $data['issues']);
 
diff --git a/library/Class/WebService/SIGB/AbstractService.php b/library/Class/WebService/SIGB/AbstractService.php
index e57587dcaa9617b3954d5fa3d5c234c46b418d0e..efc2e6942755851feadaefacecfe66f392da6117 100644
--- a/library/Class/WebService/SIGB/AbstractService.php
+++ b/library/Class/WebService/SIGB/AbstractService.php
@@ -22,6 +22,13 @@
 abstract class Class_WebService_SIGB_AbstractService {
   use Trait_Translator;
 
+  const
+    COMMUNICATION_OK = 'ok',
+    COMMUNICATION_ERROR = 'error',
+    COMMUNICATION_NOT_IMPLEMENTED = 'na';
+
+
+
   protected static $_logger;
   protected $_notice_cache;
 
@@ -61,6 +68,7 @@ abstract class Class_WebService_SIGB_AbstractService {
     return [];
   }
 
+  abstract public function getServerRoot();
 
   abstract public function getEmprunteur($user);
 
@@ -169,6 +177,11 @@ abstract class Class_WebService_SIGB_AbstractService {
   }
 
 
+  public function testCommunicationStatus() {
+    return static::COMMUNICATION_NOT_IMPLEMENTED;
+  }
+
+
   public function canConsult($field) {
     return false;
   }
diff --git a/library/Class/WebService/SIGB/CdScript/Service.php b/library/Class/WebService/SIGB/CdScript/Service.php
index a55cf129827c8163c4f5aebc80aeb60eaa58e44c..5b03c682a65194023a18c52704208b97b0ac9531 100644
--- a/library/Class/WebService/SIGB/CdScript/Service.php
+++ b/library/Class/WebService/SIGB/CdScript/Service.php
@@ -35,6 +35,11 @@ class Class_Webservice_SIGB_CdScript_Service extends Class_WebService_SIGB_Abstr
   }
 
 
+  public function getServerRoot() {
+    return $this->_server_url;
+  }
+
+
   protected function setServerUrl($url) {
     $this->_server_url = $url;
     return $this;
diff --git a/library/Class/WebService/SIGB/Koha/Service.php b/library/Class/WebService/SIGB/Koha/Service.php
index 44c1a1dba261209c59bb9f7f50588e6945c77c6d..384be9b64fd738e9bfd86437fe38035f009c0c47 100644
--- a/library/Class/WebService/SIGB/Koha/Service.php
+++ b/library/Class/WebService/SIGB/Koha/Service.php
@@ -231,6 +231,13 @@ class Class_WebService_SIGB_Koha_Service extends Class_WebService_SIGB_AbstractR
   }
 
 
+  public function testCommunicationStatus() {
+    return (false !== strpos( $this->test(), '<?xml version="1.0"'))
+      ? static::COMMUNICATION_OK
+      : static::COMMUNICATION_ERROR;
+  }
+
+
   public function test() {
     $validator = new ZendAfi_Validate_Url();
     if (!$validator->isValid($this->getServerRoot()))
@@ -238,7 +245,7 @@ class Class_WebService_SIGB_Koha_Service extends Class_WebService_SIGB_AbstractR
 
     try {
       $this->getNotice(1);
-      $httpClient = Zend_Registry::get('httpClient');
+      $httpClient = $this->getWebClient()->getHttpClient();
       $message = $httpClient->getLastRequest();
       if ($response = $httpClient->getLastResponse())
         $message .= $response->getStatus() . " " . $response->getMessage()
diff --git a/library/Class/WebService/SIGB/Microbib/Service.php b/library/Class/WebService/SIGB/Microbib/Service.php
index 2c0375bf1273d95e59978dbde21734d1c0b1be09..64a2549e2ffe9cebb9881953b2e19d3387376877 100644
--- a/library/Class/WebService/SIGB/Microbib/Service.php
+++ b/library/Class/WebService/SIGB/Microbib/Service.php
@@ -37,6 +37,11 @@ class Class_WebService_SIGB_Microbib_Service extends Class_WebService_SIGB_Abstr
   }
 
 
+  public function getServerRoot() {
+    return $this->_search_client->getServer();
+  }
+
+
   public function getNotice($id) {
     try {
       $xml = $this->_search_client->infos_exemplaires($id);
diff --git a/library/Class/WebService/SIGB/Nanook/Service.php b/library/Class/WebService/SIGB/Nanook/Service.php
index e3b9ad3042d3a18c27f451f60bd47be4855c0a94..c61bcdfe0b81d924cb2141d1350970c84ccfe9e9 100644
--- a/library/Class/WebService/SIGB/Nanook/Service.php
+++ b/library/Class/WebService/SIGB/Nanook/Service.php
@@ -176,6 +176,13 @@ class Class_Webservice_SIGB_Nanook_Service extends Class_WebService_SIGB_Abstrac
   }
 
 
+  public function testCommunicationStatus() {
+    return (false !== strpos($this->test(), '<?xml version="1.0"'))
+      ? static::COMMUNICATION_OK
+      : static::COMMUNICATION_ERROR;
+  }
+
+
   public function test() {
     $validator = new ZendAfi_Validate_Url();
     if (!$validator->isValid($this->getServerRoot()))
@@ -186,7 +193,7 @@ class Class_Webservice_SIGB_Nanook_Service extends Class_WebService_SIGB_Abstrac
         ->ilsdiGetRecords(1,
                           Class_WebService_SIGB_Nanook_GetRecordsResponseReader::newInstance());
 
-      $httpClient = Zend_Registry::get('httpClient');
+      $httpClient = $this->getWebClient()->getHttpClient();
       $message = $httpClient->getLastRequest();
       if ($response = $httpClient->getLastResponse())
         $message .= $response->getStatus() . $response->getMessage() . $response->getBody();
diff --git a/library/Class/WebService/SIGB/Opsys/Service.php b/library/Class/WebService/SIGB/Opsys/Service.php
index 3858d3f9875171fd8dcd08f4121222c57752d5c1..1f93daaf5380c3d54032c45453351b9be9992052 100644
--- a/library/Class/WebService/SIGB/Opsys/Service.php
+++ b/library/Class/WebService/SIGB/Opsys/Service.php
@@ -139,6 +139,11 @@ class Class_WebService_SIGB_Opsys_Service extends Class_WebService_SIGB_Abstract
   }
 
 
+  public function getServerRoot() {
+    return $this->search_client->getWsdlUrl();
+  }
+
+
   public function getCatalogClient() {
     return $this->catalog_client;
   }
diff --git a/library/Class/WebService/SIGB/Opsys/ServiceFactory.php b/library/Class/WebService/SIGB/Opsys/ServiceFactory.php
index 5801dd0d0dc835c14e1bd7fb18d72499fa205abf..1789417de90b438a6e3639147c72a76367dc1ae7 100644
--- a/library/Class/WebService/SIGB/Opsys/ServiceFactory.php
+++ b/library/Class/WebService/SIGB/Opsys/ServiceFactory.php
@@ -76,7 +76,9 @@ class Class_WebService_SIGB_Opsys_ServiceFactory{
       $catalog_client = new NullCatalogSoapClient();
     }
 
-    return new Class_WebService_SIGB_Opsys_Service($search_client, $catalog_client, $is_reserver_retrait_bib_abonne);
+    return new Class_WebService_SIGB_Opsys_Service($search_client,
+                                                   $catalog_client,
+                                                   $is_reserver_retrait_bib_abonne);
   }
 
   public static function createService($url_aloes, $extra_options=array()){
diff --git a/library/Class/WebService/SIGB/Orphee/Service.php b/library/Class/WebService/SIGB/Orphee/Service.php
index 9da34d15711ace723d930e775ade25acf10f8851..389b42051876d7734dd5db3ebae99cfc9c5d7ccf 100644
--- a/library/Class/WebService/SIGB/Orphee/Service.php
+++ b/library/Class/WebService/SIGB/Orphee/Service.php
@@ -47,6 +47,11 @@ class Class_WebService_SIGB_Orphee_Service extends Class_WebService_SIGB_Abstrac
   }
 
 
+  public function getServerRoot() {
+    return $this->_wsdl;
+  }
+
+
   public function __destruct() {
     if ($this->isConnected())
       $this->disconnect();
diff --git a/library/Class/WebService/SIGB/PMB/Service.php b/library/Class/WebService/SIGB/PMB/Service.php
index 4c26f59c4d2927221ee844380da9b22fdeb58571..c0dbfd2e0f96481b5db6059fceaaaa3434d1d1cd 100644
--- a/library/Class/WebService/SIGB/PMB/Service.php
+++ b/library/Class/WebService/SIGB/PMB/Service.php
@@ -44,6 +44,11 @@ class Class_Webservice_SIGB_PMB_Service extends Class_WebService_SIGB_AbstractSe
   }
 
 
+  public function getServerRoot() {
+    return $this->_pmb_url;
+  }
+
+
   public function getJsonWebClient() {
     if(!$this->_json_web_client) {
       $this->_json_web_client = new JsonWebClient($this->_pmb_url);
diff --git a/library/Class/WebService/SIGB/Pergame/Service.php b/library/Class/WebService/SIGB/Pergame/Service.php
index 1630e8a7f07e04caade01eb2447d6b72ba3e7253..bf07d415e0233ac7a027ce1a4305b27f7490a081 100644
--- a/library/Class/WebService/SIGB/Pergame/Service.php
+++ b/library/Class/WebService/SIGB/Pergame/Service.php
@@ -38,6 +38,11 @@ class Class_WebService_SIGB_Pergame_Service extends Class_WebService_SIGB_Abstra
   }
 
 
+  public function getServerRoot() {
+    return 'pergame';
+  }
+
+
   public function setLegacyService($service) {
     $this->_legacy_service = $service;
   }
diff --git a/library/ZendAfi/View/Helper/Admin/CosmoStatus.php b/library/ZendAfi/View/Helper/Admin/CosmoStatus.php
index 8a5de250265bc5d9c928bb265dc94929799574be..4d595cd0bc0910ff58c70eeda554725d59f239cd 100644
--- a/library/ZendAfi/View/Helper/Admin/CosmoStatus.php
+++ b/library/ZendAfi/View/Helper/Admin/CosmoStatus.php
@@ -25,80 +25,41 @@ class ZendAfi_View_Helper_Admin_CosmoStatus extends ZendAfi_View_Helper_BaseHelp
 
   protected
     $_date_integration,
-    $_clef_traitement;
+    $_clef_traitement,
+    $_html;
 
   public function cosmoStatus() {
     if (!$this->canAccess())
       return '';
 
-    $this->_date_integration = Class_CosmoVar::getValueOf('integration_date');
-    $this->_clef_traitement = Class_CosmoVar::getValueOf('clef_traitements');
-
-    return $this->title()
-      . $this->lastRun()
-      . $this->currentRun()
-      . $this->lag()
-      . $this->tasksWaiting();
-  }
-
-
-  protected function title() {
-    return $this->_tag('h2', $this->_('Intégration des données : '));
-  }
-
-
-  protected function lastRun() {
-    return !$this->isRunning()
-      ? $this->info($this->_('Dernier traitement d\'intégration effectué le'),
-                    Class_Date::getHumanDate($this->_date_integration, 'd MMMM yyyy'))
-      : '';
-  }
+    $this->_html = $this->title();
+    (new Class_Systeme_Report_Cosmogramme())->acceptVisitor($this);
+    return $this->_html;
 
-
-  protected function currentRun() {
-    return $this->isRunning()
-      ? $this->info($this->_('Traitement en cours depuis le'),
-                    Class_Date::getHumanDate($this->_date_integration)
-                    . ' (' . Class_CosmoVar::getValueOf('traitement_phase') . ')')
-      : '';
-  }
-
-
-  protected function lag() {
-    if (!$this->_date_integration
-        || (!$frequence = (int)Class_CosmoVar::getValueOf('integration_frequence')))
-      return '';
-
-    $diff = $this->getTimeSource()->daysFrom(strtotime($this->_date_integration));
-    $late = $diff - $frequence;
-
-    return $frequence < $diff
-      ? $this->error($this->_('Traitements d\'intégration en retard de'),
-                     $this->_('%s jours', $late))
-      : '';
+    $this->_date_integration = Class_CosmoVar::getValueOf('integration_date');
   }
 
 
-  protected function tasksWaiting() {
-    $count = Class_Cosmogramme_Integration::countBy(['traite' => 'non']);
-
-    return $this->info($this->_('Fichier(s) en file d\'attente'),
-                       $count ? $count : $this->_('aucun'));
+  public function visitData($id, $label, $value) {
+    $this->_html .= $this->view->ligneInfos($label, $value);
   }
 
 
-  protected function error($label, $value) {
-    return $this->view->ligneInfos($label, $value, 'error');
+  public function visitDatetime($id, $label, $value) {
+    $this->visitData($id, $label, Class_Date::getHumanDate($value, 'd MMMM yyyy H:mm'));
   }
 
 
-  protected function info($label, $value) {
-    return $this->view->ligneInfos($label, $value);
+  protected function title() {
+    return $this->_tag('h2', $this->_('Intégration des données : '));
   }
 
 
-  protected function isRunning() {
-    return '1' == $this->_clef_traitement;
+  public function visitAlert($id, $label, $unit, $value) {
+    $unit_label = $unit == 'day' ? $this->_('jours') : $this->_('heures');
+    $this->_html .= $this->view->ligneInfos($label,
+                                            sprintf('%s %s', $value, $unit_label),
+                                            'error');
   }
 
 
diff --git a/library/ZendAfi/View/Helper/Admin/LigneInfos.php b/library/ZendAfi/View/Helper/Admin/LigneInfos.php
index fee4321128708a2a6f88e32f63a2f232b1986333..c2e5a6f1db484537d9fd1c9a493a51ab2df6160d 100644
--- a/library/ZendAfi/View/Helper/Admin/LigneInfos.php
+++ b/library/ZendAfi/View/Helper/Admin/LigneInfos.php
@@ -37,7 +37,7 @@ class ZendAfi_View_Helper_Admin_LigneInfos extends ZendAfi_View_Helper_BaseHelpe
 
 
   protected function value($value) {
-    return $value
+    return $value !== null
       ? $this->_tag('b', $value)
       : '';
   }
diff --git a/library/ZendAfi/View/Helper/Status/Abstract.php b/library/ZendAfi/View/Helper/Status/Abstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..5aea83504b7224fb4d25584636ba28d1b6466b21
--- /dev/null
+++ b/library/ZendAfi/View/Helper/Status/Abstract.php
@@ -0,0 +1,36 @@
+<?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 ZendAfi_View_Helper_Status_Abstract extends ZendAfi_View_Helper_BaseHelper {
+  use Trait_TimeSource;
+
+  abstract public function visitSection($id, $label, $section);
+  abstract public function visitData($id, $label, $value);
+  abstract public function visitDatetime($id, $label, $value);
+  abstract public function visitDataArray($id, $label, $values);
+  abstract public function visitAlert($id, $label, $unit, $value);
+  abstract public function visitCounter($id, $label, $count);
+  abstract public function visitRecordHeader($headers);
+  abstract public function visitRecordValues($values);
+
+}
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/Status/Html.php b/library/ZendAfi/View/Helper/Status/Html.php
new file mode 100644
index 0000000000000000000000000000000000000000..b227b7c223e32097c743b08335855efa4b3bfeff
--- /dev/null
+++ b/library/ZendAfi/View/Helper/Status/Html.php
@@ -0,0 +1,97 @@
+<?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_Status_Html extends ZendAfi_View_Helper_Status_Abstract {
+  protected
+    $_html,
+    $_current_section,
+    $_wrapper_tag;
+
+  public function status_Html() {
+    (new Class_Systeme_Report())->acceptVisitor($this);
+    return $this->_html;
+  }
+
+
+  public function visitSection($id, $title, $section) {
+    $this->_current_section = '';
+    $this->_wrapper_tag = 'dl';
+    $section->acceptVisitor($this);
+    $this->_html .= $this->_tag('section',
+                                $this->_tag('h2', $title)
+                                . $this->_tag($this->_wrapper_tag,
+                                              $this->_current_section));
+  }
+
+
+  public function visitData($id, $label, $value) {
+    if (is_array($value))
+      $value = implode(',',$value);
+    $this->_current_section .= $this->_tag('dt', $label) . $this->_tag('dd', $value);
+  }
+
+
+  public function visitDataArray($id, $label, $values) {
+    $this->visitData($id, $label, implode(', ', $values));
+  }
+
+
+  public function visitDatetime($id, $label, $value) {
+    $this->visitData($id, $label, Class_Date::humanDate($value));
+  }
+
+
+  public function visitAlert($id, $label, $unit, $value) {
+    $unit_label = $unit == 'day' ? $this->_('jours') : $this->_('heures');
+    $this->visitData($id, $label, sprintf('%s %s', $value, $unit_label));
+  }
+
+
+  public function visitCounter($id, $label, $count) {
+    $this->visitData($id, $label, $count);
+  }
+
+
+  public function visitRecordHeader($headers) {
+    $this->_headers = $headers;
+    $this->_wrapper_tag = 'table';
+    $this->_current_section .= $this->_tag('tr', '<th>' . implode('</th><th>', $headers) . '</th>');
+  }
+
+
+  public function visitRecordValues($values) {
+    $this->_current_section .= '<tr>';
+
+    foreach ($this->_headers as $key_header =>$label) {
+      $value = '';
+      if (isset($values[$key_header]))
+        $value = (is_array($values[$key_header]) ?
+                  implode(',', $values[$key_header]) :
+                  $values[$key_header]);
+
+      $this->_current_section .= $this->_tag('td',$value);
+    }
+    $this->_current_section .= '</tr>';
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/Status/Json.php b/library/ZendAfi/View/Helper/Status/Json.php
new file mode 100644
index 0000000000000000000000000000000000000000..89cb4ed67bddc99d0b3c291e6216d95fa918641c
--- /dev/null
+++ b/library/ZendAfi/View/Helper/Status/Json.php
@@ -0,0 +1,79 @@
+<?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_Status_Json extends ZendAfi_View_Helper_Status_Abstract {
+  protected
+    $_report = [],
+    $_current_section = '';
+
+  public function status_Json() {
+    (new Class_Systeme_Report())->acceptVisitor($this);
+    return json_encode($this->_report);
+  }
+
+
+  public function visitSection($id, $label, $section) {
+    $this->_current_section = $id;
+    $this->_report[$id] = [];
+    $section->acceptVisitor($this);
+  }
+
+
+  public function visitData($id, $label, $value) {
+    $this->_report[$this->_current_section][$id] = $value;
+  }
+
+
+  public function visitDatetime($id, $label, $value) {
+    $this->visitData($id, $label,  date('c', $value));
+  }
+
+
+  public function visitDataArray($id, $label, $values) {
+    $this->visitData($id, $label, $values);
+  }
+
+
+  public function visitAlert($id, $label, $unit, $value) {
+    if (!isset($this->_report[$this->_current_section]['alerts']))
+      $this->_report[$this->_current_section]['alerts'] = [];
+
+    $this->_report[$this->_current_section]['alerts'] []= ['type' => $id,
+                                                           'unit' => $unit,
+                                                           'value' => $value];
+  }
+
+
+  public function visitCounter($id, $label, $count) {
+    $this->_report[$this->_current_section] []= ['id' => $id,
+                                                 'label' => $label,
+                                                 'count' => $count];
+  }
+
+
+  public function visitRecordHeader($headers) {}
+
+  public function visitRecordValues($values) {
+    $this->_report[$this->_current_section] []= $values;
+  }
+}
+?>
\ No newline at end of file
diff --git a/public/admin/css/global.css b/public/admin/css/global.css
index 7798ffd444dbb2e01e1b3d6c385cc1167af3e40f..f947384a7928f8a6229014fdc2ad0b9f8cabee69 100644
--- a/public/admin/css/global.css
+++ b/public/admin/css/global.css
@@ -1427,6 +1427,13 @@ div#reader {
 }
 
 
+.digital_connectors div.enabled {
+    background-color: #59e625;
+    width: 200px;
+    padding: 5px;
+    text-align: center;
+}
+
 
 .ouvertures_index #menu_itemback {
     float: right;
diff --git a/public/admin/skins/bokeh74/global.css b/public/admin/skins/bokeh74/global.css
index 86646616e64da7fdbd8a666250721f7477697478..08bbd753ce71a5bacdeebe8afdf8c43ca22a7372 100755
--- a/public/admin/skins/bokeh74/global.css
+++ b/public/admin/skins/bokeh74/global.css
@@ -538,6 +538,15 @@ div.boutons .bouton {
     padding-left: 1em;
 }
 
+
+.modules .digital_connectors div.enabled {
+    background-color: #59e625;
+    width: 200px;
+    padding: 5px;
+    text-align: center;
+}
+
+
 td[id*="menu_item"] {
     background: none !important;
 }
@@ -798,3 +807,22 @@ form .droite {
 .modules .breadcrumb .actions {
     display: inline-block;
 }
+
+.systeme_status dt {
+    width: 400px;
+    text-align: right;
+    display: inline-block;
+}
+
+.systeme_status dd {
+    width: 200px;
+    text-align: right;
+    display: inline;
+    clear: left;
+    margin-left: 1em;
+}
+
+.systeme_status dd:after {
+    display: block;
+    content: '';
+}
diff --git a/public/admin/skins/retro/global.css b/public/admin/skins/retro/global.css
index 370e0addaa03307278b8de622c479ef79c1d5d77..1aeebbdd5213e8b7e64c8fbcd52bdc09a6d9d9ac 100755
--- a/public/admin/skins/retro/global.css
+++ b/public/admin/skins/retro/global.css
@@ -498,6 +498,15 @@ div.boutons .bouton {
     padding-left: 1em;
 }
 
+
+.modules .digital_connectors div.enabled {
+    background-color: #59e625;
+    width: 200px;
+    padding: 5px;
+    text-align: center;
+}
+
+
 .pager {
     text-align: center;
     margin-top: 5px;
diff --git a/public/opac/js/digital_connectors.js b/public/opac/js/digital_connectors.js
index 3fec0feb4e579e6144aec4e9240a80b972289b30..4dd4ec392dd33edb339cbe0fc0fe78730325c2f0 100644
--- a/public/opac/js/digital_connectors.js
+++ b/public/opac/js/digital_connectors.js
@@ -1,24 +1,27 @@
 {
   "ONEDTOUCH": {
     "label" : "1DTouch", 
+    "enabled": "isOneDTouchEnabled",
     "url" : "http://1dtouch.com/", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/1dtouch.png", 
     "desc": "1D touch développe au travers d’une société coopérative une autre plateforme de diffusion (streaming) centrée sur les contenus culturels indépendants.", 
     "features": ["HARVEST", "SSO"], 
     "sales_contact": {"mail": "hello@1dtouch.com", "name":"1D Lab", "url": "http://1dtouch.com/#contact"}
   },
-  "CITEMUSIQUE": {
+  "CITEDELAMUSIQUE": {
     "label" : "Cité de la musique", 
+    "enabled": "isCiteDeLaMusiqueEnabled",
     "url" : "http://media.citedelamusique.fr", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/cite_de_la_musique.png", 
     "desc": "L'offre Média de la Cité de la musique en intégralité.", 
-    "features": ["SSO"], 
+    "features": ["HARVEST", "SSO"], 
     "sales_contact": {"mail" : "yadelbost@media.citedelamusique.fr",
 		      "name" : "Yannis ADELBOST",
 		      "url" : "http://media.citedelamusique.fr/medias/medias.aspx?INSTANCE=EXTRANET&PORTAL_ID=portal_model_instance__presentation_de_l_offre_media_de_la_cite_de_la_musique.xml"}
   },
   "JAMENDO": {
     "label" : "Jamendo Music", 
+    "enabled": "isJamendoEnabled",
     "url" : "https://www.jamendo.com", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/jamendo_logo_200.png", 
     "desc": "Jamendo Music est un des plus grands services en ligne dédiée à la musique indépendante, fort d’une large communauté internationale de musiciens et de mélomanes.<br/>Grâce à Jamendo, n’importe qui peut profiter librement d’un catalogue de 500 000 titres mis en ligne par plus de 30 000 artistes venant du monde entier.", 
@@ -29,6 +32,7 @@
   },
   "SoundCloud": {
     "label" : "SoundCloud", 
+    "enabled": "isSoundCloudEnabled",
     "url" : "https://www.soundcloud.com", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/soundcloud_200.png", 
     "desc": "SoundCloud est une plateforme de distribution audio en ligne sur laquelle les utilisateurs peuvent collaborer, promouvoir et distribuer leurs projets musicaux.", 
@@ -39,6 +43,7 @@
   },
   "MUSICME": {
     "label" : "MusicMe", 
+    "enabled": "isMusicMeEnabled",
     "url" : "http://www.musicme.com/", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/musicMe.jpg", 
     "desc": "musicMe est un site d'écoute et de téléchargement de musique.", 
@@ -49,6 +54,7 @@
   },
   "ARTEVOD": {
     "label" : "ArteVOD", 
+    "enabled": "isArteVODEnabled",
     "url" : "http://www.mediatheque-numerique.com/", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/arte_vod.png", 
     "desc": "Le meilleur du catalogue d'ARTE (grands documentaires, collections emblématiques, spectacles, émissions phares, cinéma patrimonial et contemporain)", 
@@ -59,6 +65,7 @@
   },
   "BABELIO": {
     "label" : "Babelthèque", 
+    "enabled": "getBabelthequeId",
     "url" : "http://www.babelio.com", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/babeltheque.jpg", 
     "desc": "Babelthèque permet aux bibliothèques d’enrichir leurs OPAC et leurs sites Internet en important le contenu produit par les membres de la communauté de lecteurs Babelio.com : critiques, citations, nuages d’étiquettes etc...", 
@@ -69,6 +76,7 @@
   },
   "CYBERLIBRIS": {
     "label" : "Bibliovox", 
+    "enabled": "isCyberlibrisEnabled",
     "url" : "http://www.bibliovox.com/", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/bibliovox.jpg", 
     "desc": "La plateforme de livres numériques des bibliothèques municipales et départementales", 
@@ -79,16 +87,18 @@
   },
   "CVS": {
     "label" : "CVS", 
+    "enabled": "isCVSEnabled",
     "url" : "http://www.cvs-mediatheques.com/", 
     "image_url" : "http://www.cvs-mediatheques.com/res/cvs/css/default/habillage/logo.png", 
     "desc": "“ Spécialiste de la fourniture de produits audiovisuels aux collectivités depuis 1987. ”", 
-    "features": ["HARVEST","SSO"], 
+    "features": ["SSO"], 
     "sales_contact": {"mail" : "gerard@ruffin.fr",
 	      "name" : "Gérard Ruffin",
           "url" : "http://www.cvs-mediatheques.com/?lnk=cgv"} 
 },
   "EUROPRESSE": {
     "label" : "Europresse", 
+    "enabled": "PROVIDER",
     "url" : "http://www.europresse.com/", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/europresse.png", 
     "desc": "Solution en ligne d'information de presse conçue pour les bibliothèques publiques et le domaine de l'éducation. Elle offre un accès illimité à une importante banque de sources d'information canadiennes et européennes.", 
@@ -99,6 +109,7 @@
   },
   "KIDILANGUES": {
     "label" : "Kidilangue", 
+    "enabled": "isKidilanguesEnabled",
     "url" : "http://www.kidilangues.fr/", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/kidilangues.jpg", 
     "desc": "Kidilangues propose plus de 100 activités en français et dans plusieurs langues pour les 3 à 10 ans. Ils naviguent dans un espace sécurisé en toute autonomie.", 
@@ -109,6 +120,7 @@
   },
   "LECTURA": {
     "label" : "Lectura", 
+    "enabled": "isLecturaEnabled",
     "url" : "http://www.lectura.fr/", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/lectura.png", 
     "desc": "Le portail des bibliothèques des villes-centres de Rhône-Alpes.", 
@@ -119,6 +131,7 @@
   },
   "SOURISQUIRACONTE": {
     "label" : "La souris qui raconte", 
+    "enabled": "PROVIDER",
     "url" : "http://www.lasourisquiraconte.com/", 
     "image_url" : "http://www.lasourisquiraconte.com/img/la-souris-qui-raconte-logo-1427815138.jpg", 
     "desc": "Histoires et contes intéractifs pour enfants.", 
@@ -129,6 +142,7 @@
   },
   "LEKIOSK": {
     "label" : "LeKiosk", 
+    "enabled": "isLeKioskEnabled",
     "url" : "http://www.lekiosk.fr/", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/lekiosk.png", 
     "desc": "Lekiosk est une application qui propose des milliers de magazines et de bandes dessinées.", 
@@ -139,6 +153,7 @@
   },
   "MYCOW": {
     "label" : "MyCoW", 
+    "enabled": "isMyCowEnabled",
     "url" : "http://www.mycow.eu/", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/mycow.jpg", 
     "desc": "MyCOW est un service en ligne proposant d'apprendre et de pratiquer l'anglais.", 
@@ -149,6 +164,7 @@
   },
   "NAXOS": {
     "label" : "Naxos Music Library", 
+    "enabled": "PROVIDER",
     "url" : "http://www.naxos.com/naxos/countries/France/disco_naxos.asp", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/naxos.jpg", 
     "desc": "La Discothèque Naxos est une discothèque numérique en ligne, qui regroupe plus de 10 000 disques de musique classique, mais aussi de jazz, blues, world, folk, etc. <br/><br/>En plus de l’écoute de la musique, les abonnées de la Discothèque Naxos ont accès à des ressources documentaires exceptionnelles sur les compositeurs, les interprètes, les œuvres, etc.", 
@@ -159,6 +175,7 @@
   },
   "NUMERIQUEPREMIUM": {
     "label" : "Numérique premium", 
+    "enabled": "isNumeriquePremiumEnabled",
     "url" : "http://www.numeriquepremium.com", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/numeriquepremium.jpg", 
     "desc": "NUMERIQUE PREMIUM est une plateforme proposant des ebooks en Histoire et Sciences Humaines.<br/><br/>Plus de 1500 ouvrages en français, en partenariat avec une trentaine d'éditeurs, à consulter et lire 24h/24 et 7j/7 depuis votre bibliothèque et à distance.", 
@@ -169,6 +186,7 @@
   },
   "NUMILOG": {
     "label" : "Numilog", 
+    "enabled": "isNumilogEnabled",
     "url" : "http://www.numilog.fr", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/numilog.png", 
     "desc": "Numilog est un distributeur et diffuseur français de livres numériques.", 
@@ -179,6 +197,7 @@
   },
   "PLANETNEMO": {
     "label" : "PlanetNemo", 
+    "enabled": "isPlanetNemoEnabled",
     "url" : "http://www.planetnemo.com", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/planetnemo.png", 
     "desc": "Plateforme ludo-éducatif pour les enfants de 3 à 8 ans. En quelques clics, les enfants ont accès à plus de 200 jeux et activités ludo-éducatives en accès illimité, répartis en plus de 7 univers interactifs et enrichissants.", 
@@ -189,6 +208,7 @@
   },
     "PREMIERCHAPITRE": {
     "label" : "Premier Chapitre", 
+    "enabled": "isPremierChapitreEnabled",
     "url" : "http://www.premierchapitre.fr", 
     "image_url" : "http://www.premierchapitre.fr/img/splash/premier_chapitre.png", 
     "desc": "premierchapitre est le meilleur moyen pour découvrir tranquillement des extraits de livres qui viennent de paraître. C’est un service qui se glisse dans votre poche - ou plutôt dans votre smartphone ou votre tablette. ", 
@@ -199,6 +219,7 @@
   },
   "TOUTAPPRENDRE": {
     "label" : "toutapprendre.com", 
+    "enabled": "isToutApprendreEnabled",
     "url" : "http://www.toutapprendre.com", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/toutapprendre.png", 
     "desc": "toutapprendre.com, leader du e-Learning auprès du grand public, propose des centaines de cours en ligne pour le développement des compétences personnelles de chacun.", 
@@ -209,6 +230,7 @@
   },
   "VODECLIC": {
     "label" : "Vodeclic", 
+    "enabled": "isVodeclicEnabled",
     "url" : "http://www.vodeclic.com", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/vodeclic.png", 
     "desc": "Vodeclic est une solution de formation pour développer ses compétences bureautiques.", 
@@ -219,6 +241,7 @@
   },
   "ORTHODIDACTE": {
     "label" : "Orthodidacte", 
+    "enabled": "isOrthodidacteEnabled",
     "url" : "http://www.orthodidacte.com/", 
     "image_url" : "http://bokeh-library-portal.org/userfiles/media/ressources_numeriques/logo_orthodidacte_pastille.png", 
     "desc": "Orthodidacte constitue une nouvelle approche pour apprendre l’orthographe et la grammaire de la langue française en ligne.", 
@@ -229,6 +252,7 @@
   },
   "LESOCIAL": {
     "label" : "Le Social", 
+    "enabled": "isLeSocialEnabled",
     "url" : "http://lesocial.fr/", 
     "image_url" : "http://www.lesocial.fr/images/logo.gif", 
     "desc": "1er site du Social en fréquentation & activité.", 
@@ -236,5 +260,25 @@
     "sales_contact": {"mail" : "contact@lesocial.fr",
 		      "name" : "Frédéric GUIOT",
 		      "url" : "http://losocial.fr"}
+  },
+
+  "DILICOM": {
+    "label" : "Dilicom PNB", 
+    "enabled": "isDilicomPNBEnabled",
+    "url" : "https://pnb-dilicom.centprod.com/documentation/", 
+    "image_url" : "http://numeriklivres.info/wp-content/uploads/2016/03/logo-dilicom.jpg", 
+    "desc": "PNB (Prêt Numérique en Bibliothèque) est un ensemble de services destinés à faciliter les interconnexions entre les revendeurs, les collectivités et les distributeurs dans le cadre du prêt de ressources numériques.", 
+    "features": ["HARVEST", "SSO"], 
+    "sales_contact": {"mail": "technique@dilicom.com", "name":"Dilicom"}
+  },
+
+  "ORPHEA": {
+    "label" : "Orphea",
+    "enabled": "isOrpheaEnabled",
+    "url": "https://www.orphea.com/",
+    "image_url": "https://www.orphea.com/sites/all/themes/orphea/img/logo-orphea.png",
+    "desc": "Orphea Studio vous propose des offres de gestion de contenus multimédias adaptées à vos problématiques métiers",
+    "features": ["HARVEST", "SSO"], 
+    "sales_contact": {"url": "https://www.orphea.com/contact", "name":"Orphéa", "mail":"info@orphea.com"}
   }
 }
diff --git a/tests/application/modules/admin/controllers/BibnumControllerTest.php b/tests/application/modules/admin/controllers/BibnumControllerTest.php
index 143f7396044804a111545b99518b1fe599b8d538..3bf169440b6008748460ee777b381299e2b19c1f 100644
--- a/tests/application/modules/admin/controllers/BibnumControllerTest.php
+++ b/tests/application/modules/admin/controllers/BibnumControllerTest.php
@@ -22,6 +22,8 @@
 class Admin_BibnumControllerIndexTest extends Admin_AbstractControllerTestCase {
   public function setUp() {
     parent::setUp();
+    RessourcesNumeriquesFixtures::activate1Dtouch();
+    RessourcesNumeriquesFixtures::deactivateJamendo();
     $this->dispatch('/admin/bibnum', true);
   }
 
@@ -46,16 +48,36 @@ class Admin_BibnumControllerIndexTest extends Admin_AbstractControllerTestCase {
 
   /** @test */
   public function oneDTouchFeaturesShouldBePresent() {
-    $this->assertXPathContentContains('//table[@class="digital_connectors"]//tr[1]/td',
+    $this->assertXPathContentContains('//table[@class="digital_connectors"]//tr[@data-code="onedtouch"]/td',
                                       'Recherche fédérée, SSO');
   }
 
 
   /** @test */
   public function oneDTouchContactShouldBePresent() {
-    $this->assertXPathContentContains('//table[@class="digital_connectors"]//tr[1]/td',
+    $this->assertXPathContentContains('//table[@class="digital_connectors"]//tr[@data-code="onedtouch"]/td',
                                       '1D Lab');
   }
+
+
+  /** @test */
+  public function oneDTouchShouldBeEnabled() {
+    $this->assertXPathContentContains('//table[@class="digital_connectors"]//tr[@data-code="onedtouch"]/td//div[@class="enabled"]',
+                                      'Activé');
+  }
+
+
+  /** @test */
+  public function europresseShouldBeActivatedByProvider() {
+    $this->assertNotXPath('//table[@class="digital_connectors"]//tr[@data-code="europresse"]/td//div[@class="enabled"]');
+  }
+
+
+  /** @test */
+  public function jamendoShouldNotBeEnabled() {
+    $this->assertNotXPath('//table[@class="digital_connectors"]//tr[@data-code="jamendo"]/td//div[@class="enabled"]');
+  }
+
 }
 
 
diff --git a/tests/application/modules/admin/controllers/IndexControllerTest.php b/tests/application/modules/admin/controllers/IndexControllerTest.php
index 89140f340262310cf91dedf10e037f8c696309e7..458c86054f14628005f7e4504b8b087f5cb4f1e6 100644
--- a/tests/application/modules/admin/controllers/IndexControllerTest.php
+++ b/tests/application/modules/admin/controllers/IndexControllerTest.php
@@ -29,28 +29,13 @@ abstract class Admin_IndexControllerTestCase extends Admin_AbstractControllerTes
 
   public function setUp() {
     parent::setUp();
+    Class_CosmoVar::setValueOf('integration_date', '2016-10-25');
+    Class_CosmoVar::setValueOf('clef_traitements', 1);
+    Class_CosmoVar::setValueOf('traitement_phase', 'Execution des batchs programmés');
+    Class_CosmoVar::setValueOf('integration_frequence',7);
+    Class_CosmoVar::setValueOf('integration_alert_max_time',10);
 
-    $this->fixture('Class_CosmoVar',
-                   ['id' => 'integration_date',
-                    'clef' => 'integration_date',
-                    'valeur' => '2016-10-25 13:12:34']);
-
-    $this->fixture('Class_CosmoVar',
-                   ['id' => 'clef_traitements',
-                    'clef' => 'clef_traitements',
-                    'valeur' => '1']);
-
-    $this->fixture('Class_CosmoVar',
-                   ['id' => 'traitement_phase',
-                    'clef' => 'traitement_phase',
-                    'valeur' => 'Execution des batchs programmés']);
-
-    $this->fixture('Class_CosmoVar',
-                   ['id' => 'integration_frequence',
-                    'clef' => 'integration_frequence',
-                    'valeur' => '7']);
-
-    ZendAfi_View_Helper_Admin_CosmoStatus::setTimeSource(new TimeSourceForTest('2016-11-03 14:27:45'));
+    Class_Systeme_Report_Cosmogramme::setTimeSource(new TimeSourceForTest('2016-11-03 14:27:45'));
   }
 }
 
@@ -131,20 +116,31 @@ class Admin_IndexControllerTest extends Admin_IndexControllerTestCase {
 
   /** @test */
   public function integrationShouldBeRunningSince2016_10_25() {
-    $this->assertXPathContentContains('//b', '25 octobre 2016 13:12:34 (Execution des batchs programmés)',
+    $this->assertXPathContentContains('//b', '25 octobre 2016');
+  }
+
+
+  /** @test */
+  public function phaseShouldBatchExecution() {
+    $this->assertXPathContentContains('//b', 'Execution des batchs programmés',
                                       $this->_response->getBody());
   }
 
 
   /** @test */
-  public function lastIntegrationShouldBeLateFrom1Day() {
-    $this->assertXPathContentContains('//b', '1 jours', $this->_response->getBody());
+  public function lastIntegrationShouldBeLateFrom2Days() {
+    $this->assertXPathContentContains('//b', '2 jours', $this->_response->getBody());
   }
 
 
+  /** @test */
+  public function integrationEndShouldBeLateFrom227Hours() {
+    $this->assertXPathContentContains('//b', '227 heures', $this->_response->getBody());
+  }
+
   /** @test */
   public function integrationWaitingTasksShouldBePresent() {
-    $this->assertXPathContentContains('//div[contains(text(), "Fichier(s) en file d\'attente")]//b', 'aucun');
+    $this->assertXPath('//div[contains(text(), "Fichier(s) en file d\'attente")]//b[text()="0"]');
   }
 
 
diff --git a/tests/application/modules/admin/controllers/SystemeControllerTest.php b/tests/application/modules/admin/controllers/SystemeControllerTest.php
index 54f50c5a7db317decefec2618e8acff403edfd76..45f32baecdcf5eb7b0386581b4f478145cffc1ae 100644
--- a/tests/application/modules/admin/controllers/SystemeControllerTest.php
+++ b/tests/application/modules/admin/controllers/SystemeControllerTest.php
@@ -249,4 +249,33 @@ class Admin_SystemControllerTest extends Admin_AbstractControllerTestCase {
   public function libelleFacetteShouldBeNouveau() {
     $this->assertXPath('//form//input[contains(@name, "NNNN")][@value="nouveau"]');
   }
+}
+
+
+
+class Admin_SystemControllerStatusTest extends Admin_AbstractControllerTestCase {
+  protected $_storm_default_to_volatile = true;
+
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('/admin/systeme/status', true);
+  }
+
+
+  /** @test */
+  public function titleShouldBeBokehOverview() {
+    $this->assertXPathContentContains('//h1', 'Etat du système');
+  }
+
+  /** @test */
+  public function sectionShouldContainsH2WithPortal() {
+    $this->assertXPathContentContains('//section//h2', 'Portail');
+  }
+
+  /** @test */
+  public function pageShouldBeHtml5Valid() {
+    $this->assertHtml5();
+  }
+
+
 }
\ No newline at end of file
diff --git a/tests/library/Class/WebService/ArteVODTest.php b/tests/library/Class/WebService/ArteVODTest.php
index ca4ea38ba4f210ace9c81d0e2c2daa592e8580c5..5e0316328375ebeb8de6407392142839cc5c8c9e 100644
--- a/tests/library/Class/WebService/ArteVODTest.php
+++ b/tests/library/Class/WebService/ArteVODTest.php
@@ -86,12 +86,14 @@ class ArteVODHarverstingTwoFilmsInTwoPages extends ArteVODHarverstingTestCase {
       ->whenCalled('deleteBy')
       ->answers(true);
 
+
     $codif_type_doc=$this->fixture('Class_CodifTypeDoc', ['id' => Class_TypeDoc::ARTEVOD,
                                                           'famille_id' => Class_CodifTypeDoc::INCONNU,
                                                           'bibliotheques' => '1;8',
                                                           'annexes' => '10;12',
                                                           'sections' => '18;19']);
 
+
     $this->fixture('Class_TypeDoc', ['id' => Class_TypeDoc::ARTEVOD,
                                      'codif_type_doc' => $codif_type_doc,
                                      'label'=> 'Type doc']);
diff --git a/tests/library/Class/WebService/SIGB/KohaTest.php b/tests/library/Class/WebService/SIGB/KohaTest.php
index 7833429061fd4c382393e34cd3f7b7c6944febea..ee7903bf7f57a26c9e877bf462d33e6d149570b0 100644
--- a/tests/library/Class/WebService/SIGB/KohaTest.php
+++ b/tests/library/Class/WebService/SIGB/KohaTest.php
@@ -104,6 +104,45 @@ abstract class KohaTestCase extends ModelTestCase {
 }
 
 
+
+class KohaServiceTestCommunicationStatusTest extends KohaTestCase {
+  public function setUp() {
+    parent::setUp();
+    $this->mock_web_client
+      ->whenCalled('getHttpClient')->answers($this->mock_web_client);
+  }
+
+
+  /** @test */
+  public function withXmlResponseCommunicationStatusShouldAnswersOK() {
+    $this->mock_web_client
+      ->whenCalled('getLastRequest')->answers('something')
+      ->whenCalled('getLastResponse')->answers($this->mock()
+                                               ->whenCalled('getStatus')->answers('ok')
+                                               ->whenCalled('getMessage')->answers('a message')
+                                               ->whenCalled('getBody')->answers('<?xml version="1.0" encoding="UTF8">'));
+
+    $this->assertEquals('ok', $this->service->testCommunicationStatus());
+  }
+
+
+
+  /** @test */
+  public function withNoXmlResponseCommunicationStatusShouldAnswersError() {
+    $this->mock_web_client
+      ->whenCalled('getLastRequest')->answers('something')
+      ->whenCalled('getLastResponse')->answers($this->mock()
+                                               ->whenCalled('getStatus')->answers('error')
+                                               ->whenCalled('getMessage')->answers('horror')
+                                               ->whenCalled('getBody')->answers('plouf'));
+
+    $this->assertEquals('error', $this->service->testCommunicationStatus());
+  }
+}
+
+
+
+
 class KohaServiceGetNoticeJardinEnfantTest extends KohaTestCase {
   public function setUp() {
     parent::setUp();
diff --git a/tests/library/Class/WebService/SIGB/NanookTest.php b/tests/library/Class/WebService/SIGB/NanookTest.php
index 5066c82a149fa54cd187b12a7251e66a1ad9f0d1..b6570a191e85dccf7ec5f3b1b5d97d5823a767cb 100644
--- a/tests/library/Class/WebService/SIGB/NanookTest.php
+++ b/tests/library/Class/WebService/SIGB/NanookTest.php
@@ -105,6 +105,44 @@ abstract class NanookTestCase extends Storm_Test_ModelTestCase {
 
 
 
+class NanookServiceTestCommunicationStatusTest extends NanookTestCase {
+  public function setUp() {
+    parent::setUp();
+    $this->_mock_web_client
+      ->whenCalled('getHttpClient')->answers($this->_mock_web_client);
+  }
+
+
+  /** @test */
+  public function withXmlResponseCommunicationStatusShouldAnswersOK() {
+    $this->_mock_web_client
+      ->whenCalled('getLastRequest')->answers('something')
+      ->whenCalled('getLastResponse')->answers($this->mock()
+                                               ->whenCalled('getStatus')->answers('ok')
+                                               ->whenCalled('getMessage')->answers('a message')
+                                               ->whenCalled('getBody')->answers('<?xml version="1.0" encoding="UTF8">'));
+
+    $this->assertEquals('ok', $this->_service->testCommunicationStatus());
+  }
+
+
+
+  /** @test */
+  public function withNoXmlResponseCommunicationStatusShouldAnswersError() {
+    $this->_mock_web_client
+      ->whenCalled('getLastRequest')->answers('something')
+      ->whenCalled('getLastResponse')->answers($this->mock()
+                                               ->whenCalled('getStatus')->answers('error')
+                                               ->whenCalled('getMessage')->answers('horror')
+                                               ->whenCalled('getBody')->answers('plouf'));
+
+    $this->assertEquals('error', $this->_service->testCommunicationStatus());
+  }
+}
+
+
+
+
 abstract class NanookServiceErrorTestCase extends NanookTestCase {
   /** @test */
   public function reserverExemplaireShouldReturnFailure() {
diff --git a/tests/library/Class/WebService/SIGB/PergameTest.php b/tests/library/Class/WebService/SIGB/PergameTest.php
index 464ada2c6b77a48d9ec049540568794a788d759a..8ef8abd3dd1e0d15ea13bb68adf0220a7095fd6e 100644
--- a/tests/library/Class/WebService/SIGB/PergameTest.php
+++ b/tests/library/Class/WebService/SIGB/PergameTest.php
@@ -100,6 +100,17 @@ abstract class PergameTestCase extends Storm_Test_ModelTestCase {
 
 
 
+
+class PergameServiceCommunicationStatusTest extends PergameTestCase {
+  /** @test */
+  public function communicationStatusShouldAnswersNotAvailable() {
+    $this->assertEquals('na', $this->_service_cran->testCommunicationStatus());
+  }
+}
+
+
+
+
 class PergameServiceGetEmprunteurTest extends PergameTestCase {
   public function setUp() {
     parent::setUp();
diff --git a/tests/library/ZendAfi/Auth/Adapter/AuthCommSigbTest.php b/tests/library/ZendAfi/Auth/Adapter/AuthCommSigbTest.php
index baa6540765bb3050dc5a72c29a8690c988588b86..2ccc6fbabba7832426ec9d9a894fc4583c124c88 100644
--- a/tests/library/ZendAfi/Auth/Adapter/AuthCommSigbTest.php
+++ b/tests/library/ZendAfi/Auth/Adapter/AuthCommSigbTest.php
@@ -99,6 +99,14 @@ abstract class AuthCommSigbWithWebServicesAndAbonneZorkTestCase extends AuthComm
 
     return $this;
   }
+
+
+  public function tearDown() {
+    Class_WebService_SIGB_Nanook::setService(null);
+    Class_WebService_SIGB_Orphee::setService(null);
+    Class_WebService_SIGB_Opsys::setService(null);
+    parent::tearDown();
+  }
 }
 
 
diff --git a/tests/library/ZendAfi/View/Helper/Status/HtmlTest.php b/tests/library/ZendAfi/View/Helper/Status/HtmlTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..8f906a85ccda41724e0b8252f1ebc55f2147c905
--- /dev/null
+++ b/tests/library/ZendAfi/View/Helper/Status/HtmlTest.php
@@ -0,0 +1,177 @@
+<?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_Status_HtmlTest extends ZendAfi_View_Helper_Status_TestCase {
+  protected
+    $_html,
+    $_helper_class = 'ZendAfi_View_Helper_Status_Html';
+
+  public function setUp() {
+    parent::setUp();
+    $this->_html = utf8_decode($this->_helper->status_Html());
+  }
+
+
+  /** @test */
+  public function creationDateTimeShouldBeFiveDecemberRFC2822() {
+    $this->assertXPathContentContains($this->_html,
+                                      '//dl/dd[preceding-sibling::dt[text()="Généré le"]]',
+                                      '5 décembre 2016 11:00:00');
+  }
+
+
+  /** @test */
+  public function sectionShouldContainsH2WithPortal() {
+    $this->assertXPathContentContains($this->_html, '//section//h2', 'Portail');
+  }
+
+
+  /** @test */
+  public function versionNumberShouldBeCurrentVersion() {
+    $this->assertXPathContentContains($this->_html,
+                                      '//section/dl/dd[preceding-sibling::dt[text()="Version"]]',
+                                      BOKEH_RELEASE_NUMBER);
+  }
+
+
+  /** @test */
+  public function portalUrlShouldBeLibraryAnnecyDotFr() {
+    $this->assertXPathContentContains($this->_html,
+                       '//dd',
+                       'http://library.annecy.fr');
+  }
+
+
+  /** @test */
+  public function skinListShouldBeQuietLakeAndBeautiful() {
+    $this->assertXPathContentContains($this->_html,
+                                      '//dd[preceding-sibling::dt[text()="Thèmes utilisés"]]',
+                                      'quiet_lake, beautiful');
+  }
+
+
+  /** @test */
+  public function alertIntegrationTooLongShouldBeLateOf966Hours() {
+    $this->assertXPathContentContains($this->_html,
+                       '//dl/dd[preceding-sibling::dt[text()="Traitement non terminé depuis"]]',
+                       '966 heures');
+
+  }
+
+
+  /** @test */
+  public function alertIntegrationNotRunningFrom33Days() {
+    $this->assertXPathContentContains($this->_html,
+                       '//dl/dd[preceding-sibling::dt[text()="Traitements d\'intégration en retard de"]]',
+                       '33 jours');
+  }
+
+
+  /** @test */
+  public function sectionRecordsShouldContainsThreeRecordsForAll() {
+    $this->assertXPathContentContains($this->_html,
+                                      '//dl/dd[preceding-sibling::dt[text()="Tous"]]',
+                                      '3');
+  }
+
+
+    /** @test */
+  public function firstILSShouldBeKoha() {
+    $this->assertXPathContentContains($this->_html,
+                                      '//tr/td[following-sibling::td[text()="http://localhost/koha"]]',
+                                      'koha');
+  }
+
+
+  /** @test */
+  public function firstILSShouldBeKohaOnError() {
+    $this->assertXPathContentContains($this->_html,
+                                      '//tr/td[preceding-sibling::td[text()="http://localhost/koha"]]',
+                                      'error');
+
+  }
+
+
+
+  /** @test */
+  public function arteVodShouldBeActivated() {
+    $this->assertXPathContentContains($this->_html,
+                                      '//tr/td[preceding-sibling::td[text()="ArteVOD"]]',
+                                      '1');
+
+  }
+
+  /** @test */
+  public function libraryAnstaingShouldDisplayAdress() {
+    $this->assertXPathContentContains($this->_html,
+                                      '//tr/td[preceding-sibling::td[text()="Anstaing / Bibliothèque municipale"]]',
+                                      'Place Jules Guesde');
+  }
+
+  /** @test */
+  public function libraryAstaingShouldDisplayCPandCity() {
+    $this->assertXPathContentContains($this->_html,
+                                      '//tr/td[preceding-sibling::td[text()="59152"]]',
+                                      'Anstaing');
+  }
+
+
+  /** @test */
+  public function libraryAstaingShouldDisplayCoordinates() {
+    $this->assertXPathContentContains($this->_html,
+                                      '//tr/td[preceding-sibling::td[text()="Anstaing"]]',
+                                      '11111,22222');
+  }
+
+
+  /** @test */
+  public function variableOnOffBibnumShouldBeDisplayed() {
+     $this->assertXPathContentContains($this->_html,
+                                      '//dl/dd[preceding-sibling::dt[text()="BIBNUM"]]',
+                                      '1');
+  }
+
+
+  /** @test */
+  public function variableUnsettedFormationsShouldBeDisplayed() {
+     $this->assertXPath($this->_html,
+                        '//dl/dd[preceding-sibling::dt[text()="FORMATIONS"]][text()="0"]');
+  }
+
+
+  /** @test */
+  public function variablesStringShouldNotBeDisplayed() {
+     $this->assertNotXPathContentContains($this->_html,
+                                      '//dl/dd[preceding-sibling::dt[text()="ARTE_VOD_SSO_KEY"]]',
+                                      'secret');
+  }
+
+
+  /** @test */
+  public function variablesLanguesValuesShouldBeDisplayed() {
+    $this->assertXPathContentContains($this->_html,
+                                      '//dl/dd[preceding-sibling::dt[text()="LANGUES"]]',
+                                      'fr,en');
+  }
+
+}
+?>
\ No newline at end of file
diff --git a/tests/library/ZendAfi/View/Helper/Status/JsonTest.php b/tests/library/ZendAfi/View/Helper/Status/JsonTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3297ae7d558af001572331f5c7727d5836bdd9eb
--- /dev/null
+++ b/tests/library/ZendAfi/View/Helper/Status/JsonTest.php
@@ -0,0 +1,403 @@
+<?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_Status_JsonTest extends ZendAfi_View_Helper_Status_TestCase {
+  protected
+    $_report,
+    $_helper_class = 'ZendAfi_View_Helper_Status_Json';
+
+  public function setUp() {
+    parent::setUp();
+
+    $this->_report = json_decode($this->_helper->status_Json(),true);
+  }
+
+
+  /** @test */
+  public function creationDateTimeShould2016_12_05UTC_ISO8601() {
+    $this->assertEquals('2016-12-05T11:00:00+01:00', $this->_report['headers']['creation_datetime']);
+  }
+
+
+  /** @test */
+  public function portalUrlShouldBeLibraryAnnecyDotFr() {
+    $this->assertEquals('http://library.annecy.fr', $this->_report['portal']['url']);
+  }
+
+
+  /** @test */
+  public function headersVersionShouldBeCurrentVersion() {
+    $this->assertEquals(BOKEH_RELEASE_NUMBER, $this->_report['headers']['version']);
+  }
+
+
+  /** @test */
+  public function portalLabelShouldBeC2APortal() {
+    $this->assertEquals('C2A portal', $this->_report['portal']['label']);
+  }
+
+
+  /** @test */
+  public function portalSkinsShouldContainsBeautifulAndQuietLake() {
+    $this->assertEquals(['quiet_lake', 'beautiful'], $this->_report['portal']['skins']);
+  }
+
+
+  /** @test */
+  public function dataIntegrationsShouldContainAlertIntegrationLate() {
+    $this->assertEquals(['type' => 'integration_late',
+                         'value' => 33,
+                         'unit' => 'day'],
+                        $this->_report['data_integrations']['alerts'][1]);
+  }
+
+
+  /** @test */
+  public function dataIntegrationsShouldContainAlertIntegrationTooLong() {
+    $this->assertEquals(['type' => 'database_blocked',
+                         'value' => 966,
+                         'unit' => 'hour'],
+                        $this->_report['data_integrations']['alerts'][0]);
+  }
+
+
+  /** @test */
+  public function onCosmoIntegrationOKShouldNotIncludesAlerts() {
+    Class_CosmoVar::setValueOf('integration_date', '2016-12-05 08:12:00');
+    $this->_report = json_decode($this->_helper->status_Json(),true);
+    $this->assertFalse(isset($this->_report['data_integrations']['alerts']),
+                       print_r($this->_report['data_integrations'], true));
+  }
+
+
+  /** @test */
+  public function recordsAllShouldContainsThreeRecords() {
+    $this->assertEquals(['id' => 'all',
+                         'label' => 'Tous',
+                         'count' => 3],
+                        $this->_report['records'][0]);
+  }
+
+
+  /** @test */
+  public function recordsBookShouldContainsTwoRecords() {
+    $this->assertEquals(['id' => 1,
+                         'label' => 'Livres',
+                         'count' => 2],
+                        $this->_report['records'][1]);
+  }
+
+
+  /** @test */
+  public function allUsersCountShouldBeThree() {
+    $this->assertEquals(['id' => 'all',
+                         'label' => 'Tous',
+                         'count' => 3],
+                        $this->_report['users'][0]);
+  }
+
+
+  /** @test */
+  public function patronUsersCountShouldBeTwo() {
+    $this->assertEquals(['id' => 2,
+                         'label' => 'abonné identifié SIGB',
+                         'count' => 2],
+                        $this->_report['users'][2]);
+  }
+
+
+  /** @test */
+  public function firstILSShouldBeKohaOnError() {
+    $this->assertEquals(['type' => 'koha',
+                         'url' => 'http://localhost/koha',
+                         'communication_status' => 'error',
+                         ],
+                        $this->_report['ils'][0],
+                        Class_IntBib::find(5)->getSigbComm()->test());
+  }
+
+
+  /** @test */
+  public function sixILSShouldBeNanookOnError() {
+    $this->assertEquals(['type' => 'nanook',
+                         'url' => 'http://localhost/nanook/',
+                         'communication_status' => 'error',
+                         ],
+                        $this->_report['ils'][1]);
+  }
+
+
+  /** @test */
+  public function ArteVodShouldEnabled() {
+    $this->assertContains(["code" => "ARTEVOD",
+                           "label"  =>  "ArteVOD",
+                           "enabled" => true,
+                           "features" => ["HARVEST", "SSO"],
+                           "album_count" => 0 ],
+                        $this->_report['digital_connectors']);
+  }
+
+
+
+  /** @test */
+  public function MusicMeShouldEnabled() {
+    $this->assertContains(["code" => "MUSICME",
+                           "label"  =>  "MusicMe",
+                           "enabled" => true,
+                           "features" => ["SSO"]
+                           ],
+                          $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function ToutApprendreShouldEnabled() {
+    $this->assertContains(["code" => "TOUTAPPRENDRE",
+                           "label"  =>  "toutapprendre.com",
+                           "enabled" => true,
+                           "features" => ["HARVEST", "SSO"],
+                           "album_count" => 0
+                           ],
+                          $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function VodeclicShouldEnabled() {
+    $this->assertContains(["code" => "VODECLIC",
+                           "label"  =>  "Vodeclic",
+                           "enabled" => true,
+                           "features" => ["HARVEST", "SSO"],
+                           "album_count" => 0
+                           ],
+                          $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function NumilogShouldEnabled() {
+    $this->assertContains(["code" => "NUMILOG",
+                           "label"  =>  "Numilog",
+                           "enabled" => true,
+                           "features" => ["HARVEST", "SSO"],
+                           "album_count" => 0
+                           ],
+                          $this->_report['digital_connectors']);
+  }
+
+  /** @test */
+  public function CyberlibrisShouldEnabled() {
+    $this->assertContains(["code" => "CYBERLIBRIS",
+                           "label"  =>  "Bibliovox",
+                           "enabled" => true,
+                           "features" => ["HARVEST", "SSO"],
+                           "album_count" => 0
+                           ],
+                        $this->_report['digital_connectors']);
+  }
+
+  /** @test */
+  public function NumeriquePremiumShouldEnabled() {
+    $this->assertContains(["code" => "NUMERIQUEPREMIUM",
+                           "label"  =>  "Numérique premium",
+                           "enabled" => true,
+                           "features" => ["HARVEST", "SSO"],
+                           "album_count" => 0
+                           ],
+                          $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function CVSShouldEnabled() {
+    $this->assertContains(["code" => "CVS",
+                           "label"  =>  "CVS",
+                           "enabled" => true,
+                           "features" => ["SSO"],
+                           ],
+                          $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function LekioskShouldEnabled() {
+    $this->assertContains(["code" => "LEKIOSK",
+                         "label"  =>  "LeKiosk",
+                         "enabled" => true,
+                         "features" => ["SSO"],
+                         ],
+                        $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function OneDTouchShouldEnabled() {
+    $this->assertContains(["code" => "ONEDTOUCH",
+                         "label"  =>  "1DTouch",
+                         "enabled" => true,
+                         "features" => ["HARVEST","SSO"],
+                         "album_count" => 0
+                         ],
+                        $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function OrpheaShouldEnabled() {
+    $this->assertContains(["code" => "ORPHEA",
+                         "label"  =>  "Orphea",
+                         "enabled" => true,
+                           "features" => ["HARVEST", "SSO"],
+                         "album_count" => 0
+                         ],
+                        $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function MyCowShouldEnabled() {
+    $this->assertContains(["code" => "MYCOW",
+                           "label"  =>  "MyCoW",
+                           "enabled" => true,
+                           "features" => ["SSO"],
+                           ],
+                          $this->_report['digital_connectors']);
+  }
+
+  /** @test */
+  public function PlanetNemoShouldEnabled() {
+    $this->assertContains(["code" => "PLANETNEMO",
+                           "label"  =>  "PlanetNemo",
+                           "enabled" => true,
+                           "features" => ["SSO"],
+                           ],
+                          $this->_report['digital_connectors']);
+  }
+
+  /** @test */
+  public function KidilanguesShouldEnabled() {
+    $this->assertContains(["code" => "KIDILANGUES",
+                           "label"  =>  "Kidilangue",
+                           "enabled" => true,
+                           "features" => ["SSO"],
+                           ],
+                          $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function JamendoShouldEnabled() {
+    $this->assertContains(["code" => "JAMENDO",
+                           "label"  =>  "Jamendo Music",
+                           "enabled" => true,
+                           "features" => ["HARVEST"],
+                           "album_count" => 0
+                           ],
+                          $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function DilicomShouldEnabled() {
+    $this->assertContains(["code" => "DILICOM",
+                           "label"  =>  "Dilicom PNB",
+                           "features" => ['HARVEST', 'SSO'],
+                           "enabled" => true,
+                           "album_count" => 0
+                         ],
+                        $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function OrthodidacteShouldEnabled() {
+    $this->assertContains(["code" => "ORTHODIDACTE",
+                           "label"  =>  "Orthodidacte",
+                           "enabled" => true,
+                           "features" => ["CAS"],
+                           ],
+                          $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function LeSocialShouldEnabled() {
+    $this->assertContains(["code" => "LESOCIAL",
+                         "label"  =>  "Le Social",
+                         "enabled" => true,
+                         "features" => ["SSO"],
+                         ],
+                        $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function CiteDeLaMusiqueShouldEnabled() {
+    $this->assertContains(["code" => "CITEDELAMUSIQUE",
+                           "label"  =>  "Cité de la musique",
+                           "enabled" => true,
+                           "features" => ["HARVEST", "SSO"],
+                           "album_count" => 0
+                         ],
+                        $this->_report['digital_connectors']);
+  }
+
+
+
+  /** @test */
+  public function SoundCloudShouldDisabled() {
+    $this->assertContains(["code" => "SoundCloud",
+                           "label"  =>  "SoundCloud",
+                           "enabled" => false,
+                           "features" => ["HARVEST"],
+                           "album_count" => 0
+                         ],
+                        $this->_report['digital_connectors']);
+  }
+
+
+  /** @test */
+  public function librayAnstaingShouldDisplayAdressAndCoordinates() {
+    $this->assertContains(['label' => 'Anstaing / Bibliothèque municipale',
+                           'address' => "Place Jules Guesde",
+                           'postal_code' => "59152",
+                           "city" =>  "Anstaing",
+                           "coordinates" => [
+                                             "latitude"=> "11111",
+                                             "longitude"  => "22222"]
+                           ],
+                          $this->_report['libraries']);
+
+
+  }
+
+
+  /** @test */
+  public function booleanAndMultiplesVariablesShouldBeAvailable() {
+    $this->assertEquals(['BIBNUM' => '1',
+                         'LANGUES' => ['fr', 'en'],
+                         'FORMATIONS' => '0'],
+                        $this->_report['variables']);;
+
+  }
+}
+?>
\ No newline at end of file
diff --git a/tests/library/ZendAfi/View/Helper/Status/TestCase.php b/tests/library/ZendAfi/View/Helper/Status/TestCase.php
new file mode 100644
index 0000000000000000000000000000000000000000..3905d8f7745d8011921ec81c09fe00a92467d50f
--- /dev/null
+++ b/tests/library/ZendAfi/View/Helper/Status/TestCase.php
@@ -0,0 +1,184 @@
+<?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
+ */
+
+require_once 'tests/fixtures/KohaFixtures.php';
+abstract class ZendAfi_View_Helper_Status_TestCase extends ViewHelperTestCase {
+  protected
+    $_storm_default_to_volatile = true,
+    $_helper,
+    $_helper_class,
+    $service;
+
+
+  protected function _setupProfils() {
+    $this->fixture('Class_Profil',
+                   ['id' => 1,
+                    'libelle' => 'C2A portal',
+                    'parent_id' => null,
+                    'skin' => 'beautiful']);
+
+    $this->fixture('Class_Profil',
+                   ['id' => 34,
+                    'libelle' => 'Annecy',
+                    'parent_id' => null,
+                    'skin' => 'quiet_lake']);
+
+    $this->fixture('Class_Profil',
+                   ['id' => 35,
+                    'libelle' => 'Annecy-Le-Vieux',
+                    'parent_id' => null,
+                    'skin' => 'quiet_lake']);
+    return $this;
+  }
+
+
+  protected function _setupCosmogramme() {
+    Class_CosmoVar::setValueOf('integration_date', '2016-10-25 13:12:00');
+    Class_CosmoVar::setValueOf('clef_traitements', 1);
+    Class_CosmoVar::setValueOf('traitement_phase', 'Execution des batchs programmés');
+    Class_CosmoVar::setValueOf('integration_frequence',7);
+
+    Class_AdminVar::set('INTEGRATIONS_TOO_LONG_ALERT_THRESHOLD', 10);
+    return $this;
+  }
+
+
+  protected function _setupRecords() {
+    $this->fixture('Class_Notice',
+                   ['id' => 1,
+                    'type_doc' => Class_TypeDoc::LIVRE]);
+
+    $this->fixture('Class_Notice',
+                   ['id' => 2,
+                    'type_doc' => Class_TypeDoc::LIVRE]);
+
+    $this->fixture('Class_Notice',
+                   ['id' => 3,
+                    'type_doc' => Class_TypeDoc::DVD]);
+    return $this;
+  }
+
+
+  protected function _setupUsers() {
+    $this->fixture('Class_Users',
+                   ['id' => 2,
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
+                    'login' => 'toi',
+                    'password' => 'secret',
+                    'idabon' => 'abon',
+                    'id_site' => 1]);
+
+    $this->fixture('Class_Users',
+                   ['id' => 3,
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
+                    'login' => 'moi',
+                    'password' => 'secret',
+                    'idabon' => 'abon ?',
+                    'id_site' => 1]);
+
+    $this->fixture('Class_Users',
+                   ['id' => 4,
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL,
+                    'login' => 'supertoi',
+                    'password' => 'secret']);
+    return $this;
+  }
+
+
+  protected function _setupDigitalResources() {
+    RessourcesNumeriquesFixtures::activate();
+    return $this;
+
+  }
+
+
+  protected function _setupILS() {
+    $this->fixture('Class_IntBib',
+                   ['id' => 5,
+                    'comm_params' => ['url_serveur' => 'http://localhost/koha'],
+                    'comm_sigb' => Class_IntBib::COM_KOHA]);
+
+    $this->fixture('Class_IntBib',
+                   ['id' => 6,
+                    'comm_params' => ['url_serveur' => 'http://localhost/nanook'],
+                    'comm_sigb' => Class_IntBib::COM_NANOOK]);
+
+    $this->fixture('Class_Bib', ['id' => '73', 'libelle' => 'Chambery', 'visibilite' => 2]);
+    $anstaing = $this->fixture('Class_Lieu',
+                             ['id' => '4156465',
+                              'libelle' => 'Anstaing',
+                              'adresse' => 'Place Jules Guesde',
+                              'code_postal' => '59152',
+                              'latitude' => '11111',
+                              'longitude' => '22222'
+                             ]);
+
+    $this->fixture('Class_Bib', ['id' => '74', 'libelle' => 'Anstaing / Bibliothèque municipale',
+                                 'adresse' => 'Place Jules Guesde',
+                                 'cp' => '59152', 'ville' => 'Anstaing',
+                                 'lieu' => $anstaing,
+                                 'visibilite' => 2]);
+
+    Class_AdminVar::newInstanceWithId('KOHA_MULTI_SITES', ['valeur' => '' ]);
+    return $this;
+  }
+
+
+  protected function _setupBokeh() {
+    Class_AdminVar::set('NOM_DOMAINE', 'library.annecy.fr');
+    $this
+      ->_setupProfils()
+      ->_setupCosmogramme()
+      ->_setupRecords()
+      ->_setupUsers()
+      ->_setupILS()
+      ->_setupDigitalResources();
+  }
+
+  protected function _setupVars() {
+    Class_AdminVar::set('ARTE_VOD_SSO_KEY','secret');
+    Class_AdminVar::set('BIBNUM', '1');
+    Class_AdminVar::set('LANGUES', 'fr;en');
+    Class_AdminVar::set('FORMATIONS', '');
+  }
+
+
+  public function setUp() {
+    parent::setUp();
+    $view = new ZendAfi_Controller_Action_Helper_View();
+    $this->_helper = new $this->_helper_class();
+    $this->_helper->setView($view);
+
+    $this->_setupBokeh();
+    $this->_setupVars();
+    $time_source = new TimeSourceForTest('2016-12-05 11:00:00');
+    Class_Systeme_Report::setTimeSource($time_source);
+
+    $this->old_http_client = Zend_Registry::get('httpClient');
+    Zend_Registry::set('httpClient', $this->mock());
+  }
+
+
+  public function tearDown() {
+    Zend_Registry::set('httpClient', $this->old_http_client);
+    parent::tearDown();
+  }
+}
\ No newline at end of file