diff --git a/FEATURES/162559 b/FEATURES/162559
new file mode 100644
index 0000000000000000000000000000000000000000..d97101106c05f561d5fe6f8277d3bcca4a792597
--- /dev/null
+++ b/FEATURES/162559
@@ -0,0 +1,10 @@
+        '162559' =>
+        ['Label' => $this->_('CAFEYN: migration de l'API leKiosk vers Cafeyn'),
+             'Desc' =>  $this->_('Le module Lekiosk devient Cafeyn: SSO CAS et moissonage JSON'),
+             'Image' => '',
+             'Video' => '',
+             'Category' =>  $this->_('Ressources Numériques'),
+             'Right' => function($feature_description, $user) {return true;},
+             'Wiki' => 'https://wiki.bokeh-library-portal.org/index.php?title=Cafeyn',
+             'Test' => '',
+             'Date' => '2023-04-20'],
\ No newline at end of file
diff --git a/VERSIONS_WIP/162559 b/VERSIONS_WIP/162559
new file mode 100644
index 0000000000000000000000000000000000000000..42a3eb40194845853a652b4faa5b7f6e3aed21e5
--- /dev/null
+++ b/VERSIONS_WIP/162559
@@ -0,0 +1 @@
+- fonctionnalité #162559 : Ressources numériques: LeKiosk devient Cafeyn
\ No newline at end of file
diff --git a/cosmogramme/sql/patch/patch_321.php b/cosmogramme/sql/patch/patch_321.php
index 6a409e4589630bd1210998f5696173a7613b299a..62a2de0c86e67cd85333eb6effb08b9f6eea76f6 100644
--- a/cosmogramme/sql/patch/patch_321.php
+++ b/cosmogramme/sql/patch/patch_321.php
@@ -1,3 +1,3 @@
 <?php
-(new Class_Migration_DigitalResource_LeKiosk())->run();
-?>
\ No newline at end of file
+
+?>
diff --git a/cosmogramme/sql/patch/patch_448.php b/cosmogramme/sql/patch/patch_448.php
new file mode 100644
index 0000000000000000000000000000000000000000..f86f3e7b07bb92cec4956c7eb7ee434061d5a085
--- /dev/null
+++ b/cosmogramme/sql/patch/patch_448.php
@@ -0,0 +1,8 @@
+<?php
+try {
+  $adapter = Zend_Registry::get('sql');
+
+  $adapter->query("update bib_admin_var set valeur='https://partner-api.cafeyn.co' where clef='Lekiosk_HARVEST_URL'");
+}
+catch (Exception  $e) {}
+(new Class_Migration_DigitalResource_Cafeyn())->run();
diff --git a/library/Class/DigitalResource/Config.php b/library/Class/DigitalResource/Config.php
index 2ccaba51ee6c4e40530764144f596b478e093eef..75a2b848893202ce839c32ef90c380edbb89de47 100644
--- a/library/Class/DigitalResource/Config.php
+++ b/library/Class/DigitalResource/Config.php
@@ -345,7 +345,7 @@ class Class_DigitalResource_Config extends Class_Entity {
   }
 
 
-  public function renderHarvestDiagOn($view) {
+  public function renderHarvestDiagOn($view) : string{
     return '';
   }
 
diff --git a/library/Class/DigitalResource/Controller.php b/library/Class/DigitalResource/Controller.php
index f69b259739ec0212fbd3dd10d8a75befc8be9d87..ae3749841427742bc5100130f7f630149c4268ab 100644
--- a/library/Class/DigitalResource/Controller.php
+++ b/library/Class/DigitalResource/Controller.php
@@ -58,6 +58,11 @@ class Class_DigitalResource_Controller extends ZendAfi_Controller_Action {
   }
 
 
+  public function jsonHarvestAction() {
+    $this->_helper->json(json_decode($this->_config->getServiceInstance()->getHarvestPage(1)));
+  }
+
+
   public function trySsoAction() {
     if (!ZendAfi_Auth_Others::getInstance()->isSuperAdminLogged()) {
       $this->_helper->notify($this->_('Vous n\'avez pas les droits suffisants pour utiliser cette fonctionnalité.'));
@@ -69,7 +74,7 @@ class Class_DigitalResource_Controller extends ZendAfi_Controller_Action {
                      $this->_config->getTestUser());
 
     $this->_forward('sso');
-  }
+ }
 
 
   protected function _afterLoginRedirectTo($url, $message = null) {
diff --git a/library/Class/DigitalResource/Service.php b/library/Class/DigitalResource/Service.php
index 9f8bfff2d069b9a4ec3c57a7be4f1b45941c5acb..9b1c028668d90b12695cfaad66e66dd7d28a4a84 100644
--- a/library/Class/DigitalResource/Service.php
+++ b/library/Class/DigitalResource/Service.php
@@ -48,6 +48,11 @@ class Class_DigitalResource_Service extends Class_WebService_BibNumerique_Abstra
   }
 
 
+  public function getHarvestPage(int $page = 1) {
+    return $this;
+  }
+
+
   protected function _deleteNonHarvestedAlbums() {
     if (!$harvested_ids = $this->getHarvestedIds())
       return $this;
diff --git a/library/Class/Migration/DigitalResource/Abstract.php b/library/Class/Migration/DigitalResource/Abstract.php
index 52c5b1edf3377b32e0e42b136220fdd3564d5220..b217018160d246557af66b5ba29a7b2002475d2c 100644
--- a/library/Class/Migration/DigitalResource/Abstract.php
+++ b/library/Class/Migration/DigitalResource/Abstract.php
@@ -210,8 +210,9 @@ abstract class Class_Migration_DigitalResource_Abstract {
   protected function upgradeProfiles() {
     $top_profiles = Class_Profil::findTopProfils();
 
-    if (null !== ($_old_menu_name = $this->_getOldMenuName()))
-      $this->_renameMenusKeys($_old_menu_name, $top_profiles);
+    if (null !== ($menu_names = $this->_getOldMenuNames()))
+      foreach ( $menu_names as $menu_name)
+        $this->_renameMenusKeys($menu_name, $top_profiles);
 
     if (null != ($doc_type = (string) $this->_getOldDocTypeId())) {
       $this->_renameRecordsView($doc_type, $top_profiles);
@@ -336,6 +337,11 @@ abstract class Class_Migration_DigitalResource_Abstract {
   }
 
 
+  protected function _getOldMenuNames() :array {
+    return [$this->_getOldMenuName()];
+  }
+
+
   abstract protected function _getOldRightToken();
   abstract protected function _getAdminVarMapping();
   abstract protected function _getConfig();
diff --git a/library/Class/Migration/DigitalResource/Cafeyn.php b/library/Class/Migration/DigitalResource/Cafeyn.php
new file mode 100644
index 0000000000000000000000000000000000000000..a457aa57adddf41a8df95e14f65761c803338c67
--- /dev/null
+++ b/library/Class/Migration/DigitalResource/Cafeyn.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Copyright (c) 2012-2023, 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_Migration_DigitalResource_Cafeyn extends Class_Migration_DigitalResource_Abstract {
+
+  public function run(){
+    $this->_deleteLekioskCollection();
+    parent::run();
+  }
+
+
+  protected function _deleteLekioskCollection() {
+    while ($albums = Class_Album::findAllBy(['type_doc_id' => 'Lekiosk',
+                                             'limit' => 500])) {
+      array_map(function($album) { $album->delete();}, $albums);
+      Class_Album::clearCache();
+    }
+  }
+
+
+  protected function _getOldRightToken() {
+    return 21;
+  }
+
+
+  protected function replacePermission($group) {
+    parent::replacePermission( $group);
+
+    if (! $lekiosk_permission = Class_Permission::findFirstBy(['code'=>'Lekiosk']))
+      return $this;
+    if (!$group->hasPermission( $lekiosk_permission))
+      return $this;
+    $permission = $this->_getConfig()
+                       ->getPermission();
+    $permission->permitTo($group, new Class_Entity());
+    return $this;
+  }
+
+
+  protected function _getAdminVarMapping() {
+    return ['LEKIOSK_ID' => 'Cafeyn_ID',
+            'Lekiosk_ID' => 'Cafeyn_ID',
+            'Lekiosk_HTTP_LOGIN'=> 'Cafeyn_API_ID',
+            'Lekiosk_HTTP_PASSWORD'=> 'Cafeyn_API_PASSWORD',
+            'Lekiosk_HARVEST_URL' => 'Cafeyn_HARVEST_URL'];
+  }
+
+
+  protected function _getConfig() {
+    return Cafeyn_Config::getInstance();
+  }
+
+
+  protected function _getOldMenuName() {
+    return 'Lekiosk';
+  }
+
+
+  protected function _getOldMenuNames() :array{
+    return [ 'LEKIOSK' , 'Lekiosk'];
+  }
+
+
+  protected function _getOldBatchName() {
+    return 'Lekiosk';
+  }
+}
diff --git a/library/Class/Migration/DigitalResource/LeKiosk.php b/library/Class/Migration/DigitalResource/LeKiosk.php
deleted file mode 100644
index 5d3ec60c5b6f09d523e973ca6106b1589b58ad64..0000000000000000000000000000000000000000
--- a/library/Class/Migration/DigitalResource/LeKiosk.php
+++ /dev/null
@@ -1,49 +0,0 @@
-<?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_Migration_DigitalResource_LeKiosk extends Class_Migration_DigitalResource_Abstract {
-
-  protected function _getOldRightToken() {
-    return 21;
-  }
-
-
-  protected function _getAdminVarMapping() {
-    return ['LEKIOSK_ID' => 'Lekiosk_ID',
-            'LEKIOSK_SSO_MODE' => 'Lekiosk_SSO_MODE'];
-  }
-
-
-  protected function _getConfig() {
-    return Lekiosk_Config::getInstance();
-  }
-
-
-  protected function _getOldMenuName() {
-    return 'LEKIOSK';
-  }
-
-
-  protected function _getOldBatchName() {
-    return 'LEKIOSK';
-  }
-}
\ No newline at end of file
diff --git a/library/digital_resources/Lekiosk/Batch.php b/library/digital_resources/Cafeyn/Batch.php
similarity index 86%
rename from library/digital_resources/Lekiosk/Batch.php
rename to library/digital_resources/Cafeyn/Batch.php
index 785b5be18a011b2b41b0743b2fc329d0c0f64d1a..b5e67c5567b5b2eb2484c45aaf5ceb9fc62425cc 100644
--- a/library/digital_resources/Lekiosk/Batch.php
+++ b/library/digital_resources/Cafeyn/Batch.php
@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright (c) 2012-2014, Agence Française Informatique (AFI). All rights reserved.
+ * Copyright (c) 2012-2023, 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
@@ -20,4 +20,4 @@
  */
 
 
-class Lekiosk_Batch extends Class_DigitalResource_Batch {}
+class Cafeyn_Batch extends Class_DigitalResource_Batch {}
diff --git a/library/digital_resources/Lekiosk/CasLink.php b/library/digital_resources/Cafeyn/CasLink.php
similarity index 75%
rename from library/digital_resources/Lekiosk/CasLink.php
rename to library/digital_resources/Cafeyn/CasLink.php
index 8bc58d48b71adbe6cc25bbad5203b31ef33fba78..11221cb71687c73f38d86efd5f246d37ce2ddbb8 100644
--- a/library/digital_resources/Lekiosk/CasLink.php
+++ b/library/digital_resources/Cafeyn/CasLink.php
@@ -20,9 +20,16 @@
  */
 
 
-class Lekiosk_CasLink extends Lekiosk_LinkAbstract {
+class Cafeyn_CasLink {
+
+  protected function _getReturnURL(Class_Album $album) : string {
+    preg_match('|.*ReturnUrl=(.*)|i', $album->getExternalUri(), $matches);
+    return isset($matches[1]) ? $matches[1]: $album->getExternalUri();
+  }
+
+
   public function url(?Class_Album $album = null) : string {
-    $url = 'https://api.lekiosk.com/api/v1/externallogin/' . $this->_config()->getAdminVar('ID');
+    $url = 'https://www.cafeyn.co/fr/externallogin/' . Cafeyn_Config::getInstance()->getAdminVar('ID');
 
     return $album
       ? $url . '?' . http_build_query(['returnUrl' => $this->_getReturnURL($album)])
diff --git a/library/digital_resources/Cafeyn/Config.php b/library/digital_resources/Cafeyn/Config.php
new file mode 100644
index 0000000000000000000000000000000000000000..1cb7fe0b138aac1ebee444fbeb6bd47f042da51f
--- /dev/null
+++ b/library/digital_resources/Cafeyn/Config.php
@@ -0,0 +1,103 @@
+<?php
+/**
+ * Copyright (c) 2012-2023, 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 Cafeyn_Config extends Class_DigitalResource_Config {
+
+  protected function _getConfig() {
+    return [
+            'Introduction' => $this->_('Cafeyn : retrouvez vos magazines préférés en numérique parmi plus de 1600 titres. Un univers riche et varié, des dernières parutions aux anciens numéros.'),
+
+            'DocTypeLabel' => $this->_('Magazine numérique Cafeyn'),
+
+            'HelpLink' => 'http://wiki.bokeh-library-portal.org/index.php/Cafeyn',
+            'Url' => 'https://cafeyn.co/',
+            'Icon' => 'https://cdn1.lekiosk.com/Public/Cafeyn/images/logo/cafeyn.svg',
+
+            'PermissionLabel' => $this->_('Bibliothèque numérique: accéder à la ressource Cafeyn'),
+            'NotAllowedMessage' => $this->_('Votre abonnement ne permet pas l\'accès à cette ressource.'),
+            'SsoAction' => true,
+
+            'MenuLabel' => $this->_('Lien vers Cafeyn'),
+            'ModuleMenu' => $this->withNameSpace('ModuleMenu'),
+
+            'Service' => $this->withNameSpace('Service'),
+            'Batch' => $this->withNameSpace('Batch'),
+
+            'AdminVars' => [
+                            'ID' => Class_AdminVar_Meta::newDefault($this->_('Identifiant fourni par Cafeyn'))->bePrivate(),
+                            'API_ID' => Class_AdminVar_Meta::newDefault($this->_('Identifiant API fourni par Cafeyn'))->bePrivate(),
+                            'API_PASSWORD' => Class_AdminVar_Meta::newDefault($this->_('Mot de passe API fourni par Cafeyn'))->bePrivate(),
+                            'HARVEST_URL' => Class_AdminVar_Meta::newDefault($this->_('URL de moissonage de la ressource Cafeyn'))->bePrivate(),
+                            'SSO_URL' => Class_AdminVar_Meta::newDefault($this->_('URL SSO de la plateforme Cafeyn'),
+                                                                         ['value' => 'https://www.cafeyn.co/fr/externallogin'])->bePrivate(),
+            ]
+    ];
+  }
+
+
+  public function isEnabled() {
+    return 0 < $this->getAdminVar('ID');
+  }
+
+
+  public function getSsoUrl(Class_Users $user, ?Class_Album $album = null) : string{
+    if(!$user)
+      return '';
+
+    return (new Cafeyn_CasLink())->url($album);
+  }
+
+
+  public function getAlbumSsoUrl(Class_Users $user, Class_Album $album) : string{
+    if(!$album)
+      return '';
+    return (new Cafeyn_CasLink())->url($album);
+  }
+
+
+  public function getHarvestUrl(int $page = 1) : string {
+    return sprintf('%s/partner/publication/%s/flow',
+                   $this->getAdminVar('HARVEST_URL'),
+                   $this->getAdminVar('ID'));
+  }
+
+
+  public function getAuthorizationHeader() : string {
+    return  'Basic ' .
+      base64_encode( sprintf("%s:%s",
+                             $this->getAdminVar('API_ID'),
+                             $this->getAdminVar('API_PASSWORD')));
+  }
+
+
+  public function renderHarvestDiagOn( $view ) : string{
+    $html = [];
+    $html[] = $view->tag( 'h4','URL de moissonnage :');
+    $html[] = $view->tag( 'pre', $this->getHarvestUrl());
+    $html[] = $view->tag( 'p', 'avec les en-têtes:');
+    $html[] = $view->tag( 'pre', 'Authorization : ' . $this->getAuthorizationHeader());
+    $html[] = $view->button((new Class_Button)
+                                   ->setUrl($view->url(['action' => 'json-harvest']))
+                                   ->setText($this->_('Voir le JSON')));
+    return implode($html);
+  }
+}
diff --git a/library/digital_resources/Lekiosk/ModuleMenu.php b/library/digital_resources/Cafeyn/ModuleMenu.php
similarity index 85%
rename from library/digital_resources/Lekiosk/ModuleMenu.php
rename to library/digital_resources/Cafeyn/ModuleMenu.php
index 286b07f4657123c86287a90b8769ac75f671c391..091e4fca2dca3aba6df8ec2d80974315400daaf7 100644
--- a/library/digital_resources/Lekiosk/ModuleMenu.php
+++ b/library/digital_resources/Cafeyn/ModuleMenu.php
@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ * Copyright (c) 2012-2023, 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
@@ -20,5 +20,4 @@
  */
 
 
-class Lekiosk_ModuleMenu extends Class_DigitalResource_ModuleMenu {}
-?>
\ No newline at end of file
+class Cafeyn_ModuleMenu extends Class_DigitalResource_ModuleMenu {}
diff --git a/library/digital_resources/Cafeyn/Service.php b/library/digital_resources/Cafeyn/Service.php
new file mode 100644
index 0000000000000000000000000000000000000000..b24cd4dcec2373fae026cc89405196cc62a1a7d9
--- /dev/null
+++ b/library/digital_resources/Cafeyn/Service.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Copyright (c) 2012-2023, 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 Cafeyn_Service extends Class_DigitalResource_Service {
+
+  use Trait_StaticFileSystem;
+
+  protected Storm_Collection $_albums;
+
+  public function __construct($config) {
+    parent::__construct($config);
+    $this->_albums = new Storm_Collection();
+  }
+
+
+  protected function loadPage($page_number = 1) {
+    $json = $this->getHarvestPage($page_number);
+
+    if ($this->_parseJson($json))
+      $this->_albums = $this->_parser->getAlbums();
+
+    $this->_total_count = count($this->_albums);
+    $this->_page_number = 1;
+    $this->_page_count = 1;
+
+    return $this;
+  }
+
+
+  protected function _parseJson($json) : bool{
+    if(!$results = json_decode($json))
+      return false;
+    $this->_parser = new Cafeyn_Service_Parser( $results->result);
+    return true;
+  }
+
+
+  public function getPageCount() {
+    return 1;
+  }
+
+
+  public function getRessourcesNumeriques() {
+    return $this->_albums;
+  }
+
+
+  public function getHarvestPage(int  $page = 1) {
+    $url = $this->getCatalogUrl($page);
+
+    return $this->httpGet( $url,
+                           ['headers' =>
+                            ['Authorization' => $this->_config->getAuthorizationHeader()]]);
+  }
+
+
+  public function getCatalogUrl($page_number) {
+    return $this->_config->getHarvestUrl($page_number);
+  }
+}
diff --git a/library/digital_resources/Cafeyn/Service/Album.php b/library/digital_resources/Cafeyn/Service/Album.php
new file mode 100644
index 0000000000000000000000000000000000000000..06297bcd672b1c883631bc5320370a7145166c09
--- /dev/null
+++ b/library/digital_resources/Cafeyn/Service/Album.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Copyright (c) 2012-2023, 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 Cafeyn_Service_Album extends Class_WebService_BibNumerique_RessourceNumerique {
+
+  public function __construct($json) {
+
+    $year = explode('-', $json->releaseDate ?? '')[0];
+
+    $this->setId(sprintf( '%s:%s',
+                          $json->publicationId ?? '',
+                          $json->issueNumber ?? ''))
+         ->setTitle($this->_getTitle( $json))
+         ->setExternalUri($json->ssourl ?? '')
+         ->setDescription($json->publicationDescription ?? '')
+         ->addPoster($json->coverURL ?? '')
+         ->setEditeur($json->publisher ?? '')
+         ->addMatiere($json->category ?? '')
+         ->setYear($year);
+
+  }
+
+
+  public function getBaseUrl() {
+    return Cafeyn_Config::getInstance()->getUrl();
+  }
+
+
+  protected function getTypeDoc() {
+    return Cafeyn_Config::getInstance()->getDocType();
+  }
+
+
+  public function fillAlbum(Class_Album $album) : Class_WebService_BibNumerique_RessourceNumerique{
+    $album
+      ->setTypeDocId($this->getTypeDoc());
+
+    return $this;
+  }
+
+
+  public function getRessourceCategorieLibelle() {
+    return Cafeyn_Config::getInstance()->getName();
+  }
+
+
+  protected function _getTitle($json) {
+    $date = strtotime($json->releaseDate ?? '');
+    $date = $date ? ' : ' . strftime('%e %B %Y', $date) : '';
+
+    return sprintf('%s n°%s%s',
+                   $json->issueTitle ?? '',
+                   $json->issueNumber ?? '',
+                   $date);
+  }
+}
diff --git a/library/digital_resources/Lekiosk/LinkAbstract.php b/library/digital_resources/Cafeyn/Service/Parser.php
similarity index 62%
rename from library/digital_resources/Lekiosk/LinkAbstract.php
rename to library/digital_resources/Cafeyn/Service/Parser.php
index 45acd8a6f26bd7c229335e50e62efccd22008878..4aaedb16799aeaae4f9d8c2eb5d37b85b1f843d7 100644
--- a/library/digital_resources/Lekiosk/LinkAbstract.php
+++ b/library/digital_resources/Cafeyn/Service/Parser.php
@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright (c) 2012-2014, Agence Française Informatique (AFI). All rights reserved.
+ * Copyright (c) 2012-2023, 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
@@ -20,19 +20,21 @@
  */
 
 
-abstract class Lekiosk_LinkAbstract {
-  protected Lekiosk_Config $_config;
+class Cafeyn_Service_Parser extends Class_WebService_BibNumerique_RessourceNumerique {
 
-  protected function _config() : Lekiosk_Config {
-    return $this->_config = $this->_config ?? Lekiosk_Config::getInstance();
-  }
+  protected
+    Storm_Collection $_albums;
 
+  public function __construct($results) {
+    $this->_albums = new Storm_Collection();
 
-  protected function _getReturnURL(Class_Album $album) : string {
-    preg_match('|.*ReturnUrl=(.*)|i', $album->getExternalUri(), $matches);
-    return $matches[1];
+    foreach ( $results as $result) {
+      $this->_albums->append(new Cafeyn_Service_Album( $result));
+    }
   }
 
 
-  abstract public function url(?Class_Album $album = null) : string;
+  public function getAlbums() :Storm_Collection{
+    return $this->_albums;
+  }
 }
diff --git a/library/digital_resources/Lekiosk/Service/Album.php b/library/digital_resources/Cafeyn/View/Helper/Album.php
similarity index 60%
rename from library/digital_resources/Lekiosk/Service/Album.php
rename to library/digital_resources/Cafeyn/View/Helper/Album.php
index 693a0aad1c8e13a60172b18b2bb2a5494e41a12b..4982319a52e1e436243ef4bb009c583e2ae8e0f8 100644
--- a/library/digital_resources/Lekiosk/Service/Album.php
+++ b/library/digital_resources/Cafeyn/View/Helper/Album.php
@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ * Copyright (c) 2012-2023, 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
@@ -20,21 +20,10 @@
  */
 
 
-class Lekiosk_Service_Album extends Class_WebService_BibNumerique_RessourceNumerique {
-  public function fillAlbum(Class_Album $album) : self {
-    $album
-      ->setTypeDocId(Lekiosk_Config::getInstance()->getDocType())
-      ->addEditor($this->getEditeur());
-    return $this;
-  }
-
-  public function getBaseUrl() {
-    return Lekiosk_Config::getInstance()->getUrl();
+class Cafeyn_View_Helper_Album extends Class_DigitalResource_AlbumViewHelper {
+  protected function _getTextAccessButton(Class_Album $album) : string{
+    return $this->_('Accéder au magazine "%s" ', $album->getTitre());
   }
 
 
-  public function getRessourceCategorieLibelle() {
-    return Lekiosk_Config::getInstance()->getName();
-  }
 }
-?>
diff --git a/library/digital_resources/Lekiosk/controllers/IndexController.php b/library/digital_resources/Cafeyn/controllers/IndexController.php
similarity index 84%
rename from library/digital_resources/Lekiosk/controllers/IndexController.php
rename to library/digital_resources/Cafeyn/controllers/IndexController.php
index 125bc8eb5be336eed156eb5d6ca36d4edb5f713d..7c870c2cb1717737eb99837cbaef7bcc8132c7c7 100644
--- a/library/digital_resources/Lekiosk/controllers/IndexController.php
+++ b/library/digital_resources/Cafeyn/controllers/IndexController.php
@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright (c) 2012-2014, Agence Française Informatique (AFI). All rights reserved.
+ * Copyright (c) 2012-2023, 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
@@ -20,5 +20,4 @@
  */
 
 
-class Lekiosk_Plugin_IndexController extends Class_DigitalResource_Controller {}
-?>
\ No newline at end of file
+class Cafeyn_Plugin_IndexController extends Class_DigitalResource_Controller {}
diff --git a/library/digital_resources/Lekiosk/images/icon.png b/library/digital_resources/Cafeyn/images/icon.png
similarity index 100%
rename from library/digital_resources/Lekiosk/images/icon.png
rename to library/digital_resources/Cafeyn/images/icon.png
diff --git a/library/digital_resources/Cafeyn/tests/CafeynTest.php b/library/digital_resources/Cafeyn/tests/CafeynTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cc4b09cfd7d1d749d1090f7e7e301c9c542c803b
--- /dev/null
+++ b/library/digital_resources/Cafeyn/tests/CafeynTest.php
@@ -0,0 +1,302 @@
+<?php
+/**
+ * Copyright (c) 2012-2023, 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 CafeynAdminVars {
+
+  public static function activate() {
+    Class_AdminVar::set('Cafeyn_ID', '66');
+    Class_AdminVar::set('Cafeyn_SSO_URL', 'https://cafeyn-sso-url');
+    Class_AdminVar::set('Cafeyn_API_PASSWORD', 'POIS');
+    Class_AdminVar::set('Cafeyn_API_ID', 'mybib');
+    Class_AdminVar::set('Cafeyn_HARVEST_URL', 'https://harvest-cafeyn');
+  }
+
+
+  public static function deactivate() {
+    Class_AdminVar::set('Cafeyn_ID', '');
+    Class_AdminVar::set('Cafeyn_SSO_URL', '');
+    Class_AdminVar::set('Cafeyn_API_PASSWORD', '');
+  }
+}
+
+
+
+abstract class CafeynActivatedTestCase extends AbstractControllerTestCase {
+  protected
+    $_storm_default_to_volatile = true,
+    $_user;
+
+  public function setUp() {
+    parent::setUp();
+    CafeynAdminVars::activate();
+
+    $group = $this->fixture('Class_UserGroup',
+                            ['id' => 1,
+                             'libelle' => 'Digital resources']);
+
+    $this->_user = $this->fixture('Class_Users',
+                                  ['id' => 1,
+                                   'login' => 'Tom',
+                                   'password' => 'pwd'])
+                        ->setUserGroups([$group]);
+
+    $this->fixture('Class_Permission',
+                   ['id' => 1,
+                    'code' => 'Cafeyn'])
+         ->permitTo($group,  new Class_Entity());
+  }
+}
+
+
+
+
+class CafeynSsoTest extends CafeynActivatedTestCase {
+
+  public function setUp() {
+    parent::setUp();
+    ZendAfi_Auth::getInstance()->logUser($this->_user);
+  }
+
+
+  /** @test */
+  public function shouldRedirectToResource() {
+    $this->dispatch('/opac/modules/' . Class_DigitalResource::getInstance()->getSsoActionForPlugin('Cafeyn'), true);
+
+    $this->assertXPathContentContains('//script' , 'document.location.href="https://www.cafeyn.co/fr/externallogin/66"');
+  }
+
+
+  /** @test */
+  public function withoutLoginShouldRedirectToLogin() {
+    $url = Class_Url::absolute('/auth/login?redirect='.urlencode(Class_Url::absolute('/modules/cafeyn')));
+
+    ZendAfi_Auth::getInstance()->clearIdentity();
+    $this->dispatch('/opac/modules/cafeyn');
+    $this->assertredirectTo($url);
+  }
+
+
+  /** @test */
+  public function withNoGroupShouldDisplayNoAccessMessage() {
+    $no_lekiosk = $this->fixture(Class_Users::class,
+                                 ['id' => 56,
+                                  'login' => 'no lekiosk',
+                                  'password' => 'no']);
+
+    ZendAfi_Auth::getInstance()->logUser($no_lekiosk);
+
+    $this->dispatch('/opac/modules/cafeyn');
+    $this->assertFlashMessengerContentContains('Votre abonnement ne permet pas');
+  }
+
+
+  /** @test */
+  public function groupWithNoRightsShouldDisplayNoAccessMessage() {
+    $group = $this->fixture(Class_UserGroup::class, ['id' => 2, 'protected' => false]);
+    Class_Users::getIdentity()
+      ->beAbonneSIGB()
+      ->setUserGroups([$group]);
+
+    $this->dispatch('/opac/modules/cafeyn');
+    $this->assertFlashMessengerContentContains('Votre abonnement ne permet pas');
+  }
+
+
+  /** @test */
+  public function dynamicGroupWithRightsShouldAccessCafeyn() {
+    $group = $this->fixture(Class_UserGroup::class,
+                            ['id' => 2,
+                             'filters' => json_encode(['search_role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE,
+                                                       'search_valid_subscription' => 1])]);
+
+    $group->beDynamic()->assertSave();
+
+    $cafeyn_permission_id = Cafeyn_Config::getInstance()->getPermission()->getId();
+
+    $this->fixture(Class_UserGroup_Permission::class,
+                   ['id' => 1,
+                    'id_group' => 1,
+                    'id_permission' => $cafeyn_permission_id,
+                    'id_model' => null,
+                    'model_class' => null
+                   ]);
+
+    Class_Users::getIdentity()
+      ->bePortalBorrowerForDays(30);
+
+    $this->dispatch('/opac/modules/cafeyn');
+    $this->assertXPathContentContains('//script' , 'document.location.href="https://www.cafeyn.co/fr/externallogin/66"');
+  }
+}
+
+
+
+
+class CafeynDashboardUnactivatedTest extends Admin_AbstractControllerTestCase {
+  protected $_storm_default_to_volatile = true;
+
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('/Cafeyn_Plugin', true);
+  }
+
+
+  /** @test */
+  public function shouldDisplayDeactivated() {
+    $this->assertXPathContentContains('//button', 'Désactivé');
+  }
+
+
+  /** @test */
+  public function ssoUrlShoudlBeDisplay() {
+    $this->assertXPathContentContains('//table', 'Cafeyn_SSO_URL');
+  }
+}
+
+
+abstract class CafeynServiceTestCase extends AbstractControllerTestCase {
+
+  protected
+    $_album,
+    $_service;
+
+  public function setUp() {
+    parent::setUp();
+
+    CafeynAdminVars::activate();
+
+    $json = file_get_contents(__DIR__. '/cafeyn.json');
+    $key = base64_encode(sprintf('%s:%s',
+                                 Class_AdminVar::get('Cafeyn_API_ID'),
+                                 Class_AdminVar::get('Cafeyn_API_PASSWORD')));
+
+    $http_client = $this->mock()
+                        ->whenCalled('open_url')
+                        ->with('https://harvest-cafeyn/partner/publication/66/flow',
+                               ['headers' => ['Authorization' =>
+                                              'Basic '. $key ]])
+                        ->answers( $json);
+
+    $config = Cafeyn_Config::getInstance();
+    $config->setTimeSource(new TimeSourceForTest('2017-02-06 10:00:00'));
+
+    $this->_service = new Cafeyn_Service($config);
+    Cafeyn_Service::setDefaultHttpClient($http_client);
+    $this->_service->harvest();
+    Class_Album::clearCache();
+    $this->_album = Class_Album::find(1);
+  }
+}
+
+
+
+
+class CafeynHarvest extends CafeynServiceTestCase {
+  public function getAlbumAttribs() {
+    return [
+            ['getTitre','Le quotidien du sport n°7 :  3 avril 2023'],
+            ['getIdOrigine', '21896447:7'],
+            ['getCategoryLabel', 'Cafeyn'],
+            ['getUrlOrigine', 'https://cafeyn.co/'],
+            ['getExternalUri',
+             'https://www.cafeyn.co/externallogin/2170?returnUrl=/fr/publication/21896447/21916581'],
+            ['getPoster',
+             'https://assets.cafeyn.co/Public/Publications/21896447/21916581/Images/Detail.jpg'],
+            ['getTypeDocId' , 'Cafeyn'],
+            ['getAnnee', '2023'],
+            ['getDescription',
+             '« Le quotidien du sport » vous permettra de découvrir ou de retrouver tous les héros et les champions du sport.'
+            ]
+    ];
+  }
+
+
+  /**
+   * @test
+   * @dataProvider getAlbumAttribs
+   */
+  public function albumAttribsShouldMatch($key, $value) {
+    $this->assertEquals($value, call_user_func([$this->_album, $key]));
+  }
+
+
+  /** @test */
+  public function album3ShouldHaveCategory(){
+    $news = Class_CodifMatiere::find( Class_Album::find(3)->getMatiere());
+    $this->assertEquals( 'Actualité', $news->getLibelle());
+  }
+
+
+  /** @test */
+  public function albumEditorShouldBeRLafont() {
+    $this->assertEquals('RLafont', $this->_album->getEditors()[0]);
+  }
+
+
+  /** @test */
+  public function albumDoctypeShouldBeNumericSerialCafein() {
+    $this->assertEquals('Magazine numérique Cafeyn', $this->_album->getTypeDoc()->getLabel());
+  }
+}
+
+
+
+
+class CafeynDashboardActivatedTest extends CafeynActivatedTestCase {
+  protected $_storm_default_to_volatile = true;
+
+  public function setUp() {
+    parent::setUp();
+
+    $album = $this->fixture('Class_Album',
+                            ['id' => 20,
+                             'titre' => '10 moutons',
+                             'type_doc_id' => 'Cafeyn'
+                            ]);
+
+    ZendAfi_Auth::getInstance()->logUser($this->fixture('Class_Users',
+                                                        ['id' => 2,
+                                                         'login' => 'admin',
+                                                         'password' => 'admin',
+                                                         'role_level' => ZendAfi_Acl_AdminControllerRoles::SUPER_ADMIN]));
+    $this->dispatch('/Cafeyn_Plugin', true);
+  }
+
+
+  /** @test */
+  public function shouldDisplayActivated() {
+    $this->assertXPathContentContains('//button', 'Activé');
+  }
+
+
+  /** @test */
+  public function urlSsoTitleBeDisplay() {
+    $this->assertXPathContentContains('//h4', 'URL SSO générée par /modules/cafeyn pour l\'utilisateur "Cafeyn_test_user"');
+  }
+
+
+  /** @test */
+  public function urlJsonHarvestBeDisplay() {
+    $this->assertXPathContentContains('//h4', 'URL de moissonnage');
+    $this->assertXPathContentContains('//pre', 'https://harvest-cafeyn/partner/publication/66/flow', $this->_response->getBody());
+  }
+
+
+}
diff --git a/library/digital_resources/Cafeyn/tests/cafeyn.json b/library/digital_resources/Cafeyn/tests/cafeyn.json
new file mode 100644
index 0000000000000000000000000000000000000000..b9d515ae4ee08c1ada28a0ad8f1933c47b58f7c7
--- /dev/null
+++ b/library/digital_resources/Cafeyn/tests/cafeyn.json
@@ -0,0 +1,75 @@
+{
+  "result": [
+    {
+      "idIssue": 21916581,
+      "issueTitle": "Le quotidien du sport",
+      "issueNumber": 7,
+      "pageCount": 24,
+      "partnerId": "2170",
+      "issueUrl": "https://www.cafeyn.co/fr/publication/21896447/21916581/",
+      "coverURL": "https://assets.cafeyn.co/Public/Publications/21896447/21916581/Images/Detail.jpg",
+      "ssourl": "https://www.cafeyn.co/externallogin/2170?returnUrl=/fr/publication/21896447/21916581",
+      "releaseDate": "2023-04-03T00:00:00",
+      "publicationId": 21896447,
+      "publisher": "RLafont",
+      "publicationDescription": "« Le quotidien du sport » vous permettra de découvrir ou de retrouver tous les héros et les champions du sport.",
+      "frequency": "Bimestriel",
+      "isAdult": false,
+      "loginUrl": "https://www.cafeyn.co/fr/authentication"
+    },
+    {
+      "idIssue": 21652500,
+      "issueTitle": "The Week",
+      "issueNumber": 1262,
+      "pageCount": 64,
+      "partnerId": "2170",
+      "issueUrl": "https://www.cafeyn.co/fr/publication/2024877/21652500/",
+      "coverURL": "https://assets.cafeyn.co/Public/Publications/2024877/21652500/Images/Detail.jpg",
+      "ssourl": "https://www.cafeyn.co/externallogin/2170?returnUrl=/fr/publication/2024877/21652500",
+      "releaseDate": "2020-10-17T00:00:00",
+      "publicationId": 2024877,
+      "publisher": "Dennis Publishing FR",
+      "publicationDescription": "The Week couvre le meilleur des médias britanniques et étrangers. Avec ses reportages non partisans, The Week donne aux lecteurs un aperçu de toutes les actualités, people, arts, théâtre, ... et comment les médias internationaux l'ont rapporté.",
+      "frequency": "Hebdomadaire",
+      "isAdult": false,
+      "loginUrl": "https://www.cafeyn.co/fr/authentication"
+    },
+    {
+      "idIssue": 21916753,
+      "issueTitle": "TroisCouleurs",
+      "issueNumber": 196,
+      "pageCount": 96,
+      "partnerId": "2170",
+      "issueUrl": "https://www.cafeyn.co/fr/publication/1853874/21916753/",
+      "coverURL": "https://assets.cafeyn.co/Public/Publications/1853874/21916753/Images/Detail.jpg",
+      "ssourl": "https://www.cafeyn.co/externallogin/2170?returnUrl=/fr/publication/1853874/21916753",
+      "releaseDate": "2023-03-24T00:00:00",
+      "publicationId": 1853874,
+      "category": "Actualité",
+      "publisher": "TroisCouleurs",
+      "publicationDescription": "Chaque mois explorez gratuitement \"le monde à l'écran\" avec des enquêtes, interview et reportages qui décryptent l'actualité du cinéma. Et aussi toutes les chroniques des films, albums, livres, expos, spectacles et autres sorties culturelles du mois.",
+      "frequency": "Mensuel",
+      "isAdult": false,
+      "loginUrl": "https://www.cafeyn.co/fr/authentication"
+    },
+    {
+      "idissue": 3777,
+      "issuetitle": "BadIssue",
+      "issuenumber": 196,
+      "pagecount": 96,
+      "partnerid": "2170",
+      "issueurl": "https://www.cafeyn.co/fr/publication/1853874/21916753/",
+      "coverurl": "https://assets.cafeyn.co/Public/Publications/1853874/21916753/Images/Detail.jpg",
+      "SSOURL": "https://www.cafeyn.co/externallogin/2170?returnUrl=/fr/publication/1853874/21916753",
+      "releasedate": "2023-03-24T00:00:00",
+      "publicationid": 1853874,
+      "CATEGORY": "Actualité",
+      "PUBLISHER": "TroisCouleurs",
+      "PUBLICATIONDESCRIPTION": "Chaque mois explorez gratuitement \"le monde à l'écran\" avec des enquêtes, interview et reportages qui décryptent l'actualité du cinéma. Et aussi toutes les chroniques des films, albums, livres, expos, spectacles et autres sorties culturelles du mois.",
+      "frequency": "Mensuel",
+      "isAdult": false,
+      "loginUrl": "https://www.cafeyn.co/fr/authentication"
+    }
+  ]
+}
+	   
diff --git a/library/digital_resources/Lekiosk/Config.php b/library/digital_resources/Lekiosk/Config.php
deleted file mode 100644
index 9e55038184e9120af7972b9262496753d733136d..0000000000000000000000000000000000000000
--- a/library/digital_resources/Lekiosk/Config.php
+++ /dev/null
@@ -1,144 +0,0 @@
-<?php
-/**
- * Copyright (c) 2012-2016, 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 Lekiosk_Config extends Class_DigitalResource_Config {
-
-  protected function _getConfig() {
-    return [
-            'DocTypeLabel' => $this->_('Magazine numérique Cafeyn'),
-            'PermissionLabel' => $this->_('Bibliothèque numérique: accéder à Cafeyn'),
-            'MenuLabel' => $this->_('Lien vers Cafeyn'),
-            'Introduction' => $this->_('Retrouvez vos magazines préférés en numérique parmi plus de 1600 titres. Un univers riche et varié, des dernières parutions aux anciens numéros.'),
-            'NotAllowedMessage' => $this->_('Votre abonnement ne permet pas l\'accès à cette ressource.'),
-
-            'HelpLink' => 'http://wiki.bokeh-library-portal.org/index.php/Cafeyn',
-            'Url' => 'http://www.lekiosk.com/',
-            'Icon' => 'https://cdn1.lekiosk.com/Public/Cafeyn/images/logo/cafeyn.svg',
-
-            'MailUrl' => 'http://get.lekiosk.com/pro/?utm_source=LK&utm_campaign=B2B&utm_medium=footer',
-
-            'AdminVars' => [
-                            'ID' => Class_AdminVar_Meta::newDefault($this->_('Identifiant fourni par Cafeyn'))->bePrivate(),
-                            'SSO_MODE' => Class_AdminVar_Meta::newCombo($this->_('Type de SSO cafeyn.co'),
-                                                                        ['options' => ['selectOptions' => ['label' => $this->_('Mode d\'authentification'),
-                                                                                                           'multioptions' => ['' => 'Lien',
-                                                                                                                              'CAS' => 'CAS']]]])->bePrivate(),
-                            'FTP_LOGIN' => Class_AdminVar_Meta::newDefault($this->_('Identifiant du compte FTP fourni par Cafeyn (déprécié)'))->bePrivate(),
-                            'FTP_PASSWORD' => Class_AdminVar_Meta::newDefault($this->_('Mot de passe du compte FTP fourni par Cafeyn (déprécié)'))->bePrivate(),
-                            'HTTP_LOGIN' => Class_AdminVar_Meta::newDefault($this->_('Identifiant du compte HTTP fourni par Cafeyn'))->bePrivate(),
-                            'HTTP_PASSWORD' => Class_AdminVar_Meta::newDefault($this->_('Mot de passe du compte HTTP fourni par Cafeyn'))->bePrivate(),
-                            'HARVEST_URL' => Class_AdminVar_Meta::newDefault($this->_('URL de moissonage de la ressource Cafeyn'))->bePrivate(),
-                            'AES_KEY' => Class_AdminVar_Meta::newDefault($this->_('Clé de cryptage/AES des mails fourni par Cafeyn'))->bePrivate(),
-                            'SHA1_KEY' => Class_AdminVar_Meta::newDefault($this->_('Clé de cryptage/SHA1 des accès fourni par Cafeyn'))->bePrivate(),
-            ],
-
-            'SsoAction' => true,
-            'Batch' => 'Lekiosk_Batch',
-            'Service' => 'Lekiosk_Service',
-            'ModuleMenu' => 'Lekiosk_ModuleMenu',
-    ];
-  }
-
-
-  public function getSsoUrl(Class_Users $user, ?Class_Album $album = null) : string {
-    $link = $this->isLeKioskCas()
-      ? new Lekiosk_CasLink()
-      : new Lekiosk_Link($user->getMail());
-    return $link->url($album);
-  }
-
-
-  public function isLeKioskCas() {
-    return $this->isEnabled()
-      && 'CAS' == $this->getAdminVar('SSO_MODE');
-  }
-
-
-  public function isEnabled() {
-    return 0 < $this->getAdminVar('ID');
-  }
-
-
-  public function getHarvestUrl(int $page = 1) : string {
-    return $this->isHttpApiEnabled()
-      ? $this->_httpHarvestUrl($page)
-      : $this->_ftpHarvestUrl($page);
-  }
-
-
-  protected function _httpHarvestUrl($page) {
-    return $this->getAdminVar('HARVEST_URL') . '/publications/flow';
-  }
-
-
-  protected function _ftpHarvestUrl($page) {
-    $date = date('dmY', $this->getCurrentTime());
-    return sprintf('ftp://%s:%s@ftp.lekiosk.com/lekiosque_%s.xml',
-                $this->getAdminVar('FTP_LOGIN'),
-                $this->getAdminVar('FTP_PASSWORD'),
-                $date);
-  }
-
-
-  public function isHttpApiEnabled() {
-    return $this->getAdminVar('HTTP_LOGIN')
-      && $this->getAdminVar('HTTP_PASSWORD')
-      && $this->getAdminVar('HARVEST_URL');
-  }
-
-
-  public function renderHarvestDiagOn($view) {
-    if (!$this->isHttpApiEnabled())
-      return '';
-
-    $service = $this->getServiceInstance();
-    $token_url = $service->getTokenUrl();
-    $catalogue_url = $service->getCatalogUrl(1);
-    $raw_token_response = $service->getTokenResponse();
-    $token_response = $view->escape($raw_token_response);
-    $token = $view->escape($service->getTokenFrom($raw_token_response));
-    $xml = $token
-      ? $view->escape($service->getXmlWithToken($token))
-      : '';
-
-    $html = [$view->tag('p', $this->_('Ce moissonnage se compose de deux étapes:')),
-             $view->tag('h4', $this->_('Première étape: La récupération du token JWT avec le login et password fourni à l\'adresse:')),
-             $view->tag('pre', $token_url),
-             $view->tag('p', $this->_('Réponse reçue à la demande de token :')),
-             $view->tag('pre', $token_response)];
-
-    if (!$token) {
-      $html [] = $view->tagError($this->_('La réponse reçue ne permet pas de récupérer le "token". Il est donc impossible de récupérer le catalogue. Veuillez vérifier les variables liées au moissonnage. Si le problème persiste, contacter le prestataire en lui fournissant le paramétrage ainsi que le rapport du diagnostique de moissonnage.'));
-      return implode($html);
-    }
-
-    $html = array_merge($html,
-                        [$view->tag('p', $this->_('Token reçu :')),
-                         $view->tag('pre', $token),
-                         $view->tag('h4', $this->_('Deuxième étape: La récupération du catalogue avec le token reçu à l\'adresse:')),
-                         $view->tag('pre', $catalogue_url),
-                         $view->tag('p', $this->_('Réponse reçue à la demande du catalogue:')),
-                         $view->tag('pre', $xml),
-                        ]);
-
-    return implode($html);
-  }
-}
diff --git a/library/digital_resources/Lekiosk/Link.php b/library/digital_resources/Lekiosk/Link.php
deleted file mode 100644
index f75f65b9e0b8929c48513350748b63d6551a2c6c..0000000000000000000000000000000000000000
--- a/library/digital_resources/Lekiosk/Link.php
+++ /dev/null
@@ -1,67 +0,0 @@
-<?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 Lekiosk_Link extends Lekiosk_LinkAbstract {
-  const ROOT_URL = 'https://pros.lekiosk.com';
-  const BASE_URL = '/login/accesshash?';
-
-  protected ?string $_mail;
-  protected ?string $_base_url;
-
-
-  public function __construct(?string $mail) {
-    $this->_mail = ($mail)
-      ? $mail
-      : Class_Profil::getPortail()->getMailSiteOrPortail();
-  }
-
-
-  public function url(?Class_Album $album = null) : string {
-    $url = static::ROOT_URL . $this->_baseUrl() . '&AccessHash=' . $this->_accessHash();
-
-    if (!$album)
-      return $url;
-
-    return $url . '&ReturnUrl=' . urlencode($this->_getReturnURL($album));
-  }
-
-
-  protected function _accessHash() : string {
-    return sha1($this->_baseUrl() . $this->_config()->getAdminVar('SHA1_KEY'));
-  }
-
-
-  protected function _baseUrl() : string {
-    return $this->_base_url = $this->_base_url ?? (static::BASE_URL
-                                                   . 'email=' . $this->_cryptedMail()
-                                                   . '&id=' . $this->_config()->getAdminVar('ID'));
-  }
-
-
-  protected function _cryptedMail() : string {
-    return bin2hex(openssl_encrypt($this->_mail,
-                                   'aes-128-cbc',
-                                   $this->_config()->getAdminVar('AES_KEY'),
-                                   true,
-                                   $this->_config()->getAdminVar('AES_KEY')));
-  }
-}
diff --git a/library/digital_resources/Lekiosk/Service.php b/library/digital_resources/Lekiosk/Service.php
deleted file mode 100644
index 6411ddacd73382c464bdce812162ef1a54d14cc9..0000000000000000000000000000000000000000
--- a/library/digital_resources/Lekiosk/Service.php
+++ /dev/null
@@ -1,129 +0,0 @@
-<?php
-/**
- * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved.
- *
- * BOKEH is free software; you can redistribute it and/or modify
- * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
- * the Free Software Foundation.
- *
- * There are special exceptions to the terms and conditions of the AGPL as it
- * is applied to this software (see README file).
- *
- * BOKEH is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
- * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-class Lekiosk_Service extends Class_DigitalResource_Service {
-  use Trait_StaticFileSystem;
-
-
-  protected $_albums;
-
-  public function __construct($config) {
-    parent::__construct($config);
-    $this->_albums = new Storm_Collection();
-  }
-
-
-  protected function loadPage($page_number = 1) {
-    $url = $this->getCatalogUrl($page_number);
-    $xml = $this->_getXML($url);
-
-    $this->_parser = new Lekiosk_Service_Parser();
-    $this->_parser->parseXML($xml);
-
-    $this->_albums = $this->_parser->getAlbums();
-
-    $this->_total_count = count($this->_albums);
-    $this->_page_number = 1;
-    $this->_page_count = 1;
-
-    return $this;
-  }
-
-
-  public function getPageCount() {
-    return 1;
-  }
-
-
-  public function getRessourcesNumeriques() {
-    return $this->_albums;
-  }
-
-
-  protected function _getXML($url) {
-    if(!$this->_config->isHttpApiEnabled())
-      return $this->getFileSystem()->file_get_contents($url);
-
-    if(!$token = $this->_getToken())
-      return '';
-
-    return $this->httpGet($url,
-                          ['headers' => ['Authorization' => 'JWT '.$token]]);
-  }
-
-
-  public function getXmlWithToken($token) {
-    return $this->httpGet($this->getCatalogUrl(1),
-                          ['headers' => ['Authorization' => 'JWT '.$token]]);
-  }
-
-
-  public function getTokenUrl() {
-    return $this->_config->getAdminVar('HARVEST_URL') . '/login';
-  }
-
-
-  public function getCatalogUrl($page_number) {
-    return $this->_config->getHarvestUrl($page_number);
-  }
-
-
-  public function getTokenResponse() {
-    if(!$params = json_encode(['username' => $this->_config->getAdminVar('HTTP_LOGIN'),
-                               'userpwd' => $this->_config->getAdminVar('HTTP_PASSWORD')]))
-      return;
-
-    $http_client = $this->getHttpClient();
-    return $http_client->postRawData($this->getTokenUrl(),
-                                     $params,
-                                     'application/json');
-  }
-
-
-  protected function _getToken() {
-    return $this->getTokenFrom($this->getTokenResponse());
-  }
-
-
-  public function getTokenFrom($response) {
-    if(!$response)
-      return;
-
-    if(!$json = json_decode($response, true))
-      return;
-
-    if(!array_key_exists('result', $json))
-      return;
-
-    if(!$result = $json['result'])
-      return;
-
-    return array_key_exists('token', $result)
-      ? $result['token']
-      : null;
-  }
-
-
-  protected function _deleteNonHarvested() {
-    return $this->_deleteNonHarvestedAlbums();
-  }
-
-}
\ No newline at end of file
diff --git a/library/digital_resources/Lekiosk/Service/Parser.php b/library/digital_resources/Lekiosk/Service/Parser.php
deleted file mode 100644
index fe897441a5047864f07d4c0f7e2cf398a3af5ab9..0000000000000000000000000000000000000000
--- a/library/digital_resources/Lekiosk/Service/Parser.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-/**
- * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
- *
- * BOKEH is free software; you can redistribute it and/or modify
- * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
- * the Free Software Foundation.
- *
- * There are special exceptions to the terms and conditions of the AGPL as it
- * is applied to this software (see README file).
- *
- * BOKEH is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
- * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-
-class Lekiosk_Service_Parser {
-
-  public function parseXML($xml) {
-    $this->_albums = new Storm_Collection();
-    $this->_parser = new Class_WebService_XMLParser();
-    $this->_parser->setElementHandler($this);
-    $this->_parser->parse($xml);
-
-    return $this;
-  }
-
-
-  public function startData($attribs) {
-    $year = Lekiosk_Config::getInstance()->isHttpApiEnabled()
-      ? explode(' ', $attribs['RELEASEDATE'])[3]
-      : explode('-', $attribs['RELEASEDATE'])[0];
-
-    $album =  new Lekiosk_Service_Album();
-    $album
-      ->setId($attribs['PUBLICATIONID'].':'.$attribs['ISSUENUMBER'])
-      ->setTitle($this->_getTitle($attribs))
-      ->setExternalUri($attribs['SSOURL'])
-      ->setDescription($attribs['ISSUEDESCRIPTION'])
-      ->addPoster($attribs['COVERURL'])
-      ->setEditeur($attribs['EDITEUR'])
-      ->addMatiere($attribs['CATEGORIES'])
-      ->setYear($year);
-
-    $this->_albums->append($album);
-  }
-
-
-  protected function _getTitle($attribs) {
-    $date = strtotime($attribs['RELEASEDATE']);
-    $date = $date ? ' : ' . strftime('%e %B %Y', $date) : '';
-
-    return sprintf('%s n°%s%s',
-                   (Lekiosk_Config::getInstance()->isHttpApiEnabled()
-                    ? $attribs['ISSUETITLE']
-                    : $attribs['PUBLICATIONTITLE']),
-                   $attribs['ISSUENUMBER'],
-                   $date);
-  }
-
-
-  public function getAlbums() {
-    return $this->_albums;
-  }
-}
diff --git a/library/digital_resources/Lekiosk/View/Helper/Album.php b/library/digital_resources/Lekiosk/View/Helper/Album.php
deleted file mode 100644
index f538cecfef303968cb7cbf08e099b3c05a451b23..0000000000000000000000000000000000000000
--- a/library/digital_resources/Lekiosk/View/Helper/Album.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-/**
- * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved.
- *
- * BOKEH is free software; you can redistribute it and/or modify
- * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
- * the Free Software Foundation.
- *
- * There are special exceptions to the terms and conditions of the AGPL as it
- * is applied to this software (see README file).
- *
- * BOKEH is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
- * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-class Lekiosk_View_Helper_Album extends ZendAfi_View_Helper_TagRessourceNumerique {
-  protected $_config, $_album;
-
-  public function album($album) {
-    $this->_album = $album;
-    $this->_config = Lekiosk_Config::getInstance();
-
-    $link = $this->canAccessRessourceNumerique()
-      ? $this->_renderAccessLink()
-      : $this->_renderNoAccessLink();
-
-    return $this->_tag('p', $link);
-  }
-
-
-  protected function _renderNoAccessLink() {
-    return $this->view
-      ->tagAnchor($this->view->url(['module' => 'opac',
-                                    'controller' => 'modules',
-                                    'action' => 'lekiosk',
-                                    'album_id' => $this->_album->getId()],
-                                   null, true),
-                  $this->_('Vous devez être connecté sous un compte avec abonnement valide pour lire le magazine'),
-                  ['class' => 'bouton']);
-  }
-
-
-  protected function _renderAccessLink() {
-    return $this->view
-      ->tagAnchor($this->_config->getSsoUrl(Class_Users::getIdentity(), $this->_album),
-                  $this->_('Lire le magazine %s sur le site Cafeyn',
-                           $this->_album->getTitre()),
-                  ['target' => '_blank',
-                   'class' => 'bouton']);
-  }
-
-
-  protected function hasRightAccesRessourcesNumeriques($user) {
-    return $this->_config->hasRightAccess($user);
-  }
-}
\ No newline at end of file
diff --git a/library/digital_resources/Lekiosk/tests/LekioskTest.php b/library/digital_resources/Lekiosk/tests/LekioskTest.php
deleted file mode 100644
index 3ad63de9fdbd3be903d2d1b199c65195f7f5d381..0000000000000000000000000000000000000000
--- a/library/digital_resources/Lekiosk/tests/LekioskTest.php
+++ /dev/null
@@ -1,862 +0,0 @@
-<?php
-/**
- * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
- *
- * BOKEH is free software; you can redistribute it and/or modify
- * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
- * the Free Software Foundation.
- *
- * There are special exceptions to the terms and conditions of the AGPL as it
- * is applied to this software (see README file).
- *
- * BOKEH is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
- * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-
-class LekioskAdminVars {
-
-  public static function activate() {
-    Class_AdminVar::set('Lekiosk_ID', '66');
-    Class_AdminVar::set('Lekiosk_FTP_LOGIN', 'POIS');
-    Class_AdminVar::set('Lekiosk_FTP_PASSWORD', 'PWD');
-    Class_AdminVar::set('Lekiosk_AES_KEY', '12FA88sE3V5UKr3K');
-    Class_AdminVar::set('Lekiosk_SHA1_KEY', '976ABWQo231');
-  }
-
-
-  public static function deactivate() {
-    Class_AdminVar::set('Lekiosk_ID', '');
-    Class_AdminVar::set('Lekiosk_FTP_LOGIN', '');
-    Class_AdminVar::set('Lekiosk_FTP_PASSWORD', '');
-    Class_AdminVar::set('Lekiosk_AES_KEY', '');
-    Class_AdminVar::set('Lekiosk_SHA1_KEY', '');
-  }
-}
-
-
-
-
-abstract class LekioskLinkModeLinkTestCase extends ModelTestCase {
-
-  public function setUp() {
-    parent::setUp();
-
-    $this->fixture(Class_Profil::class,
-                   ['id' => 1,
-                    'libelle' => 'portail',
-                    'mail_site' => '']);
-
-    LekioskAdminVars::activate();
-  }
-}
-
-
-
-
-class LekioskLinkModeLinkTest extends LekioskLinkModeLinkTestCase {
-
-  /** @test */
-  public function urlForMyemailAtLekioskDotComShouldContainsEncryptedEmail() {
-    $expected = 'https://pros.lekiosk.com/login/accesshash?email=a9be7374efd20f652cc1206da2d721f58420bf24f5b6febd143643d402f0cf39&id=66&AccessHash=6750ec2389df54aff5ae952b7e03a521e3f2a5d5';
-    $this->assertEquals($expected,
-                        (new Lekiosk_Link('myemail@lekiosk.com'))->url()
-    );
-  }
-
-
-  /** @test */
-  public function withoutMailShouldBeNotContainsEmailKey() {
-    $expected = 'https://pros.lekiosk.com/login/accesshash?email=a0dc2568ae735ff737ffc8b9bf2e4fb8&id=66&AccessHash=92a485f29b5000e908fef0815c00487b1aa759a1';
-    $this->assertEquals($expected, (new Lekiosk_Link(''))->url());
-  }
-
-
-  /** @test */
-  public function withEmptyUserMailShouldGetSiteOrProfileMail() {
-    Class_Profil::getPortail()->setMailSite('toto@example.com');
-    $expected = 'https://pros.lekiosk.com/login/accesshash?email=bd612092eb8f12afc609f161d641ba9a4ac6b6e45bfae616f4994f9205f50a7d&id=66&AccessHash=4c09021c872852de07b4e5e89a9fc1659a3c293c';
-    $this->assertEquals($expected, (new Lekiosk_Link(''))->url());
-  }
-}
-
-
-
-
-class LekioskLinkModeSSOTest extends LekioskLinkModeLinkTestCase {
-
-  public function setUp() {
-    parent::setUp();
-
-    $_SERVER['HTTP_REFERER'] = 'http://localhost/view/notice';
-    Class_Url::setBaseUrl('/bokeh');
-    Zend_Controller_Front::getInstance()
-      ->getRouter()
-      ->route(new Zend_Controller_Request_Http('http://localhost/'));
-    Class_AdminVar::set('Lekiosk_SSO_MODE', 'CAS');
-  }
-
-
-  /** @test */
-  public function linkShouldBeCasUrlWithLekioskId() {
-    $url = 'https://api.lekiosk.com/api/v1/externallogin/66';
-
-    $this->assertEquals($url,
-                        (new Lekiosk_CasLink(''))->url());
-  }
-}
-
-
-
-
-
-class LekioskModulesControllerUserWithGroupWithRightTest
-  extends AbstractControllerTestCase {
-
-  public function setUp() {
-    parent::setUp();
-    LekioskAdminVars::activate();
-
-    $user = Class_Users::getIdentity()->beAbonneSIGB();
-    $group = $this->fixture(Class_UserGroup::class,
-                            ['id' => 1, 'protected' => false]);
-
-    $lekiosk_permission_id = Lekiosk_Config::getInstance()->getPermission()->getId();
-
-    $this->fixture(Class_UserGroup_Permission::class,
-                   ['id' => 1,
-                    'id_group' => 1,
-                    'id_permission' => $lekiosk_permission_id,
-                    'id_model' => null,
-                    'model_class' => null
-                   ]);
-
-    $user->setUserGroups([$group]);
-  }
-
-
-  /** @test */
-  public function shouldHaveAccessToLekioskCas() {
-    Class_AdminVar::set('Lekiosk_SSO_MODE', 'CAS');
-    $this->dispatch('/opac/modules/lekiosk');
-    $this->assertContains('https://api.lekiosk.com/api/v1/externallogin/66',
-                          $this->_response->getBody());
-  }
-
-
-  /** @test */
-  public function shouldHaveAccessToLekiosk() {
-    $this->dispatch('/opac/modules/lekiosk');
-    $this->assertContains('https://pros.lekiosk.com/login/accesshash',
-                          $this->_response->getBody());
-  }
-}
-
-
-
-class LekioskModulesControllerUserWithGroupWithRightInPhoneTest
-  extends LekioskModulesControllerUserWithGroupWithRightTest {
-
-  public function setUp() {
-    parent::setUp();
-
-    $_SERVER['HTTP_USER_AGENT'] = 'iPhone';
-    Class_Profil::getCurrentProfil()
-      ->beTelephone()
-      ->assertSave();
-  }
-
-
-  public function tearDown() {
-    unset($_SERVER['HTTP_USER_AGENT']);
-    parent::tearDown();
-  }
-}
-
-
-
-
-class LekioskModulesControllerTest extends AbstractControllerTestCase {
-
-  protected $_expected_login_redirect;
-
-  public function setUp() {
-    parent::setUp();
-
-    $this->_expected_login_redirect = Class_Url::absolute('/auth/login?redirect='.urlencode(Class_Url::absolute('/modules/lekiosk')));
-    LekioskAdminVars::activate();
-  }
-
-
-  /** @test */
-  public function withoutLoginShouldRedirectToLogin() {
-    ZendAfi_Auth::getInstance()->clearIdentity();
-    $this->dispatch('/opac/modules/lekiosk');
-    $this->assertredirectTo($this->_expected_login_redirect);
-  }
-
-
-  /** @test */
-  public function withCasEnabledAndNotUserConnectedshouldRedirectToLogin() {
-    Class_AdminVar::set('Lekiosk_SSO_MODE', 'CAS');
-    ZendAfi_Auth::getInstance()->clearIdentity();
-
-    $this->dispatch('/opac/modules/lekiosk');
-    $this->assertredirectTo($this->_expected_login_redirect);
-  }
-
-
-  /** @test */
-  public function withNoGroupShouldDisplayNoAccessMessage() {
-    $no_lekiosk = $this->fixture(Class_Users::class,
-                                 ['id' => 56,
-                                  'login' => 'no lekiosk',
-                                  'password' => 'no']);
-
-    ZendAfi_Auth::getInstance()->logUser($no_lekiosk);
-
-    $this->dispatch('/opac/modules/lekiosk');
-    $this->assertFlashMessengerContentContains('Votre abonnement ne permet pas');
-  }
-
-
-  /** @test */
-  public function groupWithNoRightsShouldDisplayNoAccessMessage() {
-    $group = $this->fixture(Class_UserGroup::class, ['id' => 1, 'protected' => false]);
-    Class_Users::getIdentity()
-      ->beAbonneSIGB()
-      ->setUserGroups([$group]);
-
-    $this->dispatch('/opac/modules/lekiosk');
-    $this->assertFlashMessengerContentContains('Votre abonnement ne permet pas');
-  }
-
-
-  /** @test */
-  public function dynamicGroupWithRightsShouldAccessLekiosk() {
-    $group = $this->fixture(Class_UserGroup::class,
-                            ['id' => 1,
-                             'filters' => json_encode(['search_role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE,
-                                                       'search_valid_subscription' => 1])]);
-
-    $group->beDynamic()->assertSave();
-
-    $lekiosk_permission_id = Lekiosk_Config::getInstance()->getPermission()->getId();
-
-    $this->fixture(Class_UserGroup_Permission::class,
-                   ['id' => 1,
-                    'id_group' => 1,
-                    'id_permission' => $lekiosk_permission_id,
-                    'id_model' => null,
-                    'model_class' => null
-                   ]);
-
-    Class_Users::getIdentity()
-      ->bePortalBorrowerForDays(30);
-
-    $this->dispatch('/opac/modules/lekiosk');
-    $this->assertContains('https://pros.lekiosk.com/login/accesshash',
-                          $this->_response->getBody());
-  }
-}
-
-
-
-
-abstract class LekioskServiceTestCase extends AbstractControllerTestCase {
-
-  protected
-    $_10_national_sport,
-    $_service;
-
-  public function setUp() {
-    parent::setUp();
-
-    LekioskAdminVars::activate();
-
-    $catalogue_xml = file_get_contents(__DIR__. '/catalogue.xml');
-
-    $file_system = $this->mock()
-                        ->whenCalled('file_get_contents')
-                        ->with('ftp://POIS:PWD@ftp.lekiosk.com/lekiosque_06022017.xml')
-                        ->answers($catalogue_xml);
-
-    $http_client = $this->mock()
-                        ->whenCalled('open_url')
-                        ->answers(null);
-
-    $config = Lekiosk_Config::getInstance();
-    $config->setTimeSource(new TimeSourceForTest('2017-02-06 10:00:00'));
-
-    $this->_service = new Lekiosk_Service($config);
-    Lekiosk_Service::setDefaultHttpClient($http_client);
-    $this->_service->setFileSystem($file_system);
-    $this->_service->harvest();
-    Class_Album::clearCache();
-    $this->_10_national_sport = Class_Album::find(1);
-  }
-}
-
-
-
-
-class LekioskServiceHarvestTest extends LekioskServiceTestCase {
-
-  /** @test */
-  public function nameShouldBeLekiosk() {
-    $this->assertEquals('Lekiosk', $this->_service->getName());
-  }
-
-
-  /** @test */
-  public function shouldBeEnabled() {
-    $this->assertTrue($this->_service->isEnabled());
-  }
-
-
-  /** @test */
-  public function shouldHaveSaved5Albums() {
-    $this->assertCount(5, Class_Album::findAll());
-  }
-
-
-  /** @test */
-  public function categoryLekioskShouldBeCreated() {
-    $this->assertEquals('Lekiosk', $this->_10_national_sport->getCategoryLabel());
-  }
-
-
-  /** @test */
-  public function nationalSportShoulBeFound() {
-    $this->assertNotNull($this->_10_national_sport);
-  }
-
-
-  /** @test */
-  public function nationalSportIdShouldBe851749419() {
-    $this->assertEquals('851749:419', $this->_10_national_sport->getIdOrigine());
-  }
-
-  /** @test */
-  public function nationalSportIdShouldHaveUrlOrigine() {
-    $this->assertEquals('http://www.lekiosk.com/', $this->_10_national_sport->getUrlOrigine());
-  }
-
-
-  /** @test */
-  public function nationalSportTitleShouldBe10NationalSport() {
-    $this->assertEquals('Le 10 Sport National n°419 : 12 janvier 2017', $this->_10_national_sport->getTitre());
-  }
-
-
-  /** @test */
-  public function nationalSportEditionYearShouldBe2017() {
-    $this->assertEquals('2017', $this->_10_national_sport->getAnnee());
-  }
-
-
-  /** @test */
-  public function nationalSportSSOUrlShouldBeLekioskDotCom() {
-    $this->assertEquals('https://pro.lekiosk.com/lekiosque.sso.aspx?ReturnUrl=Le-10-Sport-National-z1962566.aspx', $this->_10_national_sport->getExternalUri());
-  }
-
-
-  /** @test */
-  public function nationalSportDescriptionShouldContainsSeriesDecatedToSport() {
-    $this->assertEquals('Le 10 Sport National est le mensuel entièrement dédié au sport. Vous y trouverez les infos foot, tennis ou encore basket du moment...', $this->_10_national_sport->getDescription());
-  }
-
-
-  /** @test */
-  public function nationalSportDoctypeShouldBeNumericSerialLekiosk() {
-    $this->assertEquals('Magazine numérique Cafeyn', $this->_10_national_sport->getTypeDoc()->getLabel());
-  }
-
-
-  /** @test */
-  public function nationalSportPosterUriShouldBeLekioskDotComDetailDotJpg() {
-    $this->assertEquals('http://cdn2.lekiosk.com/Public/Publications/851749/1962566/Images/Detail.jpg', $this->_10_national_sport->getPoster());
-  }
-
-
-  /** @test */
-  public function nationalSportEditorShouldBe10Medias() {
-    $this->assertEquals('10 Medias', $this->_10_national_sport->getEditors()[0]);
-  }
-
-
-  /** @test */
-  public function nationalSportSubjectShouldBeSport() {
-    $sport = Class_CodifMatiere::find($this->_10_national_sport->getMatiere());
-    $this->assertEquals('Sport', $sport->getLibelle());
-  }
-}
-
-
-
-
-class LekioskRenderAlbumFromRecordTest extends LekioskServiceTestCase {
-
-  public function setUp() {
-    parent::setUp();
-
-    Class_AdminVar::set('Lekiosk_SSO_MODE', 'CAS');
-    $user = Class_Users::getIdentity()
-      ->beAbonneSIGB()
-      ->setDateFin('9999-01-01');
-    $group = $this->fixture(Class_UserGroup::class,
-                            ['id' => 1, 'protected' => false]);
-
-    $lekiosk_permission_id = Lekiosk_Config::getInstance()->getPermission()->getId();
-
-    $this->fixture(Class_UserGroup_Permission::class,
-                   ['id' => 1,
-                    'id_group' => 1,
-                    'id_permission' => $lekiosk_permission_id,
-                    'id_model' => null,
-                    'model_class' => null
-                   ]);
-
-    $user->setUserGroups([$group]);
-
-    $this->fixture(Class_CodifThesaurus::class,
-                   ['id' => 1,
-                    'libelle' => 'Editeur',
-                    'id_thesaurus' => 'EDIT',
-                    'id_origine' => null,
-                    'code' => Class_CodifThesaurusFixed::CODE_UNIMARC_FACET,
-                    'rule_list_zone' => ['210','214'],
-                    'rule_list_label_field' => ['c','c'],
-                    'rule_list_label_start_pos' => [1,1],
-                    'rule_list_label_length' => [0,0]
-                   ]);
-
-    $this->_10_national_sport->index();
-  }
-
-
-  protected function _dispatchAlbum() {
-    $this->dispatch('/noticeajax/resnumeriques/id/'
-                    . $this->_10_national_sport->getNotice()->getId());
-  }
-
-
-  /** @test */
-  public function withoutRightsShouldDisplayErrorMessage() {
-    ZendAfi_Auth::getInstance()->clearIdentity();
-    $this->_dispatchAlbum();
-    $this->assertXPathContentContains('//a[contains(@href, "/modules/lekiosk/album_id/1")]',
-                                      utf8_encode('Vous devez être connecté'));
-  }
-
-
-  /** @test */
-  public function linkCasShouldContainsAlbumSSOUrl() {
-    $this->_dispatchAlbum();
-    $url = 'https://api.lekiosk.com/api/v1/externallogin/66?'
-      .'returnUrl=Le-10-Sport-National-z1962566.aspx';
-
-    $this->assertXPath('//a[@href="' . $url . '"]', $this->_response->getBody());
-  }
-
-
-  /** @test */
-  public function linkSSONoCASShouldContainsLekioskSSo() {
-    Class_AdminVar::set('Lekiosk_SSO_MODE', '');
-    $this->_dispatchAlbum();
-    $url = 'https://pros.lekiosk.com/login/accesshash?'
-      . 'email=a0dc2568ae735ff737ffc8b9bf2e4fb8'
-      . '&id=66'
-      . '&AccessHash=92a485f29b5000e908fef0815c00487b1aa759a1'
-      . '&ReturnUrl=Le-10-Sport-National-z1962566.aspx';
-    $this->assertXPath('//a[@href="' . $url . '"]', $this->_response->getBody());
-  }
-
-
-  /** @test */
-  public function recordFromAlbumFacettesShouldContainsHEDIT() {
-    $this->assertContains('HEDIT0001', $this->_10_national_sport->getNotice()->getFacettes());
-  }
-}
-
-
-
-class LekioskAdminUserGroupControllerRessourcesNumeriquesTest
-  extends Admin_AbstractControllerTestCase {
-
-  public function setUp() {
-    parent::setUp();
-
-    $this->fixture(Class_Bib::class,
-                   ['id' => 9,
-                    'libelle' => 'Annecy']);
-
-    $this->fixture(Class_UserGroup::class,
-                   ['id' => 6,
-                    'libelle'=> 'Modérateurs bib',
-                    'protected' => false,
-                    'group_type' => Class_UserGroup::TYPE_DYNAMIC,
-                    'users' => [],
-                    'rights' => [],
-                    'filters' => json_encode(['search_role_level' => ZendAfi_Acl_AdminControllerRoles::MODO_BIB,
-                                              'search_id_site' => 9])]);
-  }
-
-
-  /** @test */
-  public function ressourceActivatedShouldBeVisible() {
-    LekioskAdminVars::activate();
-    $this->dispatch('admin/usergroup/edit/id/6');
-    $this->assertXPathContentContains('//label', 'Bibliothèque numérique: accéder à Cafeyn');
-      }
-
-
-  /** @test  */
-  public function ressourceDeactivatedShouldNotBeVisible() {
-    LekioskAdminVars::deactivate();
-    $this->dispatch('admin/usergroup/edit/id/6');
-    $this->assertNotXPathContentContains('//label', 'Lekiosk');
-  }
-}
-
-
-
-
-class LekioskBatchIndexTest extends Admin_AbstractControllerTestCase {
-
-  /** @test */
-  public function whenActiveLekioskBatchShouldBePresent() {
-    LekioskAdminVars::activate();
-    $this->dispatch('/admin/batch');
-    $this->assertXPathContentContains('//td',
-                                      'Moissonner catalogue Lekiosk');
-  }
-
-
-  /** @test */
-  public function whenNotActiveLekioskBatchShouldNotBePresent() {
-    LekioskAdminVars::deactivate();
-    $this->dispatch('/admin/batch');
-    $this->assertNotXPathContentContains('//td',
-                                         'Moissonner catalogue Lekiosk');
-  }
-}
-
-
-
-
-class LekioskJsonReport extends ZendAfi_View_Helper_Status_TestCase {
-
-  protected
-    $_report,
-    $_helper_class = 'ZendAfi_View_Helper_Status_Json';
-
-  public function setUp() {
-    parent::setUp();
-
-    LekioskAdminVars::activate();
-    $this->_report = json_decode($this->_helper->status_Json(), true);
-  }
-
-
-  /** @test */
-  public function LekioskShouldEnabled() {
-    $this->assertContains(["code" => "Lekiosk",
-                           "label"  =>  "Lekiosk",
-                           "enabled" => "1",
-                           "features" => ["HARVEST",
-                                          "SSO"],
-                           "album_count" => 0
-                           ],
-                          $this->_report['digital_connectors']);
-  }
-}
-
-
-
-
-abstract class LekioskServiceHttpHarvestingTestCase extends AbstractControllerTestCase {
-
-  public function setUp() {
-    parent::setUp();
-
-    Class_AdminVar::set('Lekiosk_ID', '66');
-    Class_AdminVar::set('Lekiosk_HTTP_LOGIN', 'POIS');
-    Class_AdminVar::set('Lekiosk_HTTP_PASSWORD', 'PWD');
-    Class_AdminVar::set('Lekiosk_HARVEST_URL', 'https://apipros.lekiosk.com');
-    Class_AdminVar::set('Lekiosk_AES_KEY', '12FA88sE3V5UKr3K');
-    Class_AdminVar::set('Lekiosk_SHA1_KEY', '976ABWQo231');
-
-    $token_json = file_get_contents(__DIR__. '/token.json');
-    $catalogue_xml = file_get_contents(__DIR__. '/catalogue_from_http.xml');
-
-    $http_client = $this->mock()
-                        ->whenCalled('postRawData')
-                        ->with('https://apipros.lekiosk.com/login',
-                               '{"username":"POIS","userpwd":"PWD"}','application/json')
-                        ->answers($token_json)
-
-                        ->whenCalled('open_url')
-                        ->with('https://apipros.lekiosk.com/publications/flow',
-                               ['headers' => ['Authorization' => 'JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MjY2MjAxNiwibmFtZSI6Illvbm5lQGdtYWlsLmNvbSIsImV4cCI6MTUxNzM5OTE0M30.qZuwpsrZmk95LU0XYKPBFqpJJ4wxOVyZnJ_Gt3panxw']])
-                        ->answers($catalogue_xml)
-
-                        ->whenCalled('open_url')
-                        ->answers(null);
-
-    Lekiosk_Service::setDefaultHttpClient($http_client);
-
-    $config = Lekiosk_Config::getInstance();
-    $config->setTimeSource(new TimeSourceForTest('2017-02-06 10:00:00'));
-
-    $service = new Lekiosk_Service($config);
-    $service->harvest();
-    Class_Album::clearCache();
-  }
-}
-
-
-
-
-class LekioskServiceHttpUpdateHarvestingTest extends LekioskServiceHttpHarvestingTestCase {
-
-  public function setUp() {
-    parent::setUp();
-
-    $token_json = file_get_contents(__DIR__. '/token.json');
-    $http_client = $this->mock()
-                        ->whenCalled('postRawData')
-                        ->with('https://apipros.lekiosk.com/login',
-                               '{"username":"POIS","userpwd":"PWD"}','application/json')
-                        ->answers($token_json)
-
-                        ->whenCalled('open_url')
-                        ->with('https://apipros.lekiosk.com/publications/flow',
-                               ['headers' => ['Authorization' => 'JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MjY2MjAxNiwibmFtZSI6Illvbm5lQGdtYWlsLmNvbSIsImV4cCI6MTUxNzM5OTE0M30.qZuwpsrZmk95LU0XYKPBFqpJJ4wxOVyZnJ_Gt3panxw']])
-                        ->answers(file_get_contents(__DIR__. '/updated_catalogue_from_http.xml'))
-                        ->whenCalled('open_url')
-                        ->answers(null);
-    Lekiosk_Service::setDefaultHttpClient($http_client);
-    $config = Lekiosk_Config::getInstance();
-    $config->setTimeSource(new TimeSourceForTest('2019-02-06 10:00:00'));
-
-    $service = new Lekiosk_Service($config);
-    $service->harvest();
-    Class_Album::clearCache();
-  }
-
-
-  /** @test */
-  public function allPreviousAlbumShouldBeDeleted() {
-    $this->assertCount(2, Class_Album::findAll());
-  }
-
-
-  /** @test */
-  public function oneAlbumTitleShouldBe10NationalSport() {
-    $this->assertEquals('Le 10 Sport National n°440 :  6 décembre 2018', Class_Album::find(4)->getTitre());
-  }
-}
-
-
-
-
-
-class LekioskServiceHttpHarvestingTest extends LekioskServiceHttpHarvestingTestCase {
-
-  /** @test */
-  public function contextShouldExpectation() {
-    $this->assertEquals(3, Class_Album::countBy(['type_doc_id' => 'Lekiosk']));
-  }
-
-
-  /** @test */
-  public function firstAlbumYearShouldBe2018() {
-    $this->assertEquals('2018', Class_Album::find(1)->getAnnee());
-  }
-
-
-  /** @test */
-  public function firstAlbumTitleShouldBe10NationalSport() {
-    $this->assertEquals('Le 10 Sport National n°431 : 11 janvier 2018', Class_Album::find(1)->getTitre());
-  }
-}
-
-
-
-
-class LekioskServiceHttpHarvestingNoticeAjaxTest extends LekioskServiceHttpHarvestingTestCase {
-
-  public function setUp() {
-    parent::setUp();
-
-    Class_AdminVar::set('Lekiosk_SSO_MODE', 'CAS');
-
-    $user = Class_Users::getIdentity()
-      ->beAbonneSIGB()
-      ->setDateFin('9999-01-01');
-    $group = $this->fixture(Class_UserGroup::class,
-                            ['id' => 1, 'protected' => false]);
-
-    $lekiosk_permission_id = Lekiosk_Config::getInstance()->getPermission()->getId();
-
-    $this->fixture(Class_UserGroup_Permission::class,
-                   ['id' => 1,
-                    'id_group' => 1,
-                    'id_permission' => $lekiosk_permission_id,
-                    'id_model' => null,
-                    'model_class' => null
-                   ]);
-
-    $user->setUserGroups([$group]);
-
-    Class_Album::find(1)->index();
-  }
-
-
-  protected function _dispatchAlbum() {
-    $this->dispatch('/noticeajax/resnumeriques/id/1');
-  }
-
-
-  /** @test */
-  public function withoutRightsShouldDisplayErrorMessage() {
-    ZendAfi_Auth::getInstance()->clearIdentity();
-    $this->_dispatchAlbum();
-    $this->assertXPathContentContains('//a[contains(@href, "/modules/lekiosk/album_id/1")]',
-                                      utf8_encode('Vous devez être connecté'));
-  }
-
-
-  /** @test */
-  public function linkCasShouldContainsAlbumSSOUrl() {
-    $this->_dispatchAlbum();
-    $url = 'https://api.lekiosk.com/api/v1/externallogin/66?'
-      .'returnUrl='. urlencode('/fr/pageproduct/851749/2052615');
-
-    $this->assertXPath('//a[@href="' . $url . '"]', $this->_response->getBody());
-  }
-
-
-  /** @test */
-  public function linkSSONoCASShouldContainsLekioskSSo() {
-    Class_AdminVar::set('Lekiosk_SSO_MODE', '');
-    $this->_dispatchAlbum();
-    $url = 'https://pros.lekiosk.com/login/accesshash?'
-      . 'email=a0dc2568ae735ff737ffc8b9bf2e4fb8'
-      . '&id=66'
-      . '&AccessHash=92a485f29b5000e908fef0815c00487b1aa759a1'
-      . '&ReturnUrl='.urlencode('/fr/pageproduct/851749/2052615');
-    $this->assertXPath('//a[@href="' . $url . '"]', $this->_response->getBody());
-  }
-}
-
-
-
-
-class LekioskPluginTest extends Admin_AbstractControllerTestCase {
-
-  public function setUp() {
-    parent::setUp();
-
-    Class_AdminVar::set('Lekiosk_ID', '66');
-
-    Class_AdminVar::set('Lekiosk_HARVEST_URL', 'http://lekiosk.org/oai');
-    Class_AdminVar::set('Lekiosk_HTTP_LOGIN', 'lekiosk');
-    Class_AdminVar::set('Lekiosk_HTTP_PASSWORD', 'PWD+456');
-    Class_AdminVar::set('Lekiosk_AES_KEY', '12FA88sE3V5UKr3K');
-    Class_AdminVar::set('Lekiosk_SHA1_KEY', '976ABWQo231');
-
-    $group = $this->fixture(Class_UserGroup::class,
-                            ['id' => 1,
-                             'protected' => false,
-                             'libelle' => 'group']);
-
-    $user = $this->fixture(Class_Users::class,
-                           ['id' => 1,
-                            'login' => 'Tom',
-                            'password' => 'pwd']);
-    $user
-      ->beAbonneSIGB()
-      ->setDateFin('9999-01-01')
-      ->setIdabon('2345')
-      ->setBib($this->fixture(Class_Bib::class,
-                              ['id' => 2,
-                               'libelle' => 'Annecy']))
-      ->setUserGroups([$group])
-      ->save();
-
-    ZendAfi_Auth::getInstance()->logUser($user);
-
-    $this->fixture(Class_Permission::class,
-                   ['id' => 1,
-                    'code' => 'Lekiosk'])
-         ->permitTo($group,  new Class_Entity());
-
-    $this->fixture(Class_Batch::class,
-                   ['id' => 1,
-                    'type' => 'Lekiosk_Batch'
-                   ]);
-
-    $this->dispatch('/Lekiosk_Plugin');
-  }
-
-
-  /** @test */
-  public function httpPasswordShouldBeDisplayedWithPlus() {
-    $this->assertXPathContentContains('//table', 'PWD+456');
-  }
-
-
-  /** @test */
-  public function noTokenErrorMessageShouldBePresent() {
-    $this->assertXPathContentContains('//div', 'La réponse reçue ne permet pas de récupérer le "token". Il est donc impossible de récupérer le catalogue. Veuillez vérifier les variables liées au moissonnage. Si le problème persiste, contacter le prestataire en lui fournissant le paramétrage ainsi que le rapport du diagnostique de moissonnage.');
-  }
-}
-
-
-
-
-/* hotline : https://forge.afi-sa.net/issues/167096 */
-class LekioskServiceReleasedateTest extends AbstractControllerTestCase {
-
-  public function setUp() {
-    parent::setUp();
-
-    LekioskAdminVars::activate();
-
-    $catalogue_xml = file_get_contents(__DIR__ . '/new_releasedate_format.xml');
-
-    $file_system = $this->mock()
-                        ->whenCalled('file_get_contents')
-                        ->with('ftp://POIS:PWD@ftp.lekiosk.com/lekiosque_06022017.xml')
-                        ->answers($catalogue_xml);
-
-    $http_client = $this->mock()
-                        ->whenCalled('open_url')
-                        ->answers(null);
-
-    $config = Lekiosk_Config::getInstance();
-    $config->setTimeSource(new TimeSourceForTest('2017-02-06 10:00:00'));
-
-    $service = new Lekiosk_Service($config);
-    Lekiosk_Service::setDefaultHttpClient($http_client);
-    $service->setFileSystem($file_system);
-    $service->harvest();
-
-    Class_Album::clearCache();
-  }
-
-
-  /** @test */
-  public function withNewFormatReleasedateShouldReturnTitleWithoutDate() {
-    $this->assertEquals('Le 10 Sport National n°419',
-                        Class_Album::find(1)->getLibelle());
-  }
-}
diff --git a/library/digital_resources/Lekiosk/tests/catalogue.xml b/library/digital_resources/Lekiosk/tests/catalogue.xml
deleted file mode 100644
index 2d331aa78de7606f736cdbeda0d05382f68ed020..0000000000000000000000000000000000000000
Binary files a/library/digital_resources/Lekiosk/tests/catalogue.xml and /dev/null differ
diff --git a/library/digital_resources/Lekiosk/tests/catalogue_from_http.xml b/library/digital_resources/Lekiosk/tests/catalogue_from_http.xml
deleted file mode 100644
index 139996aebc5e03bc3181325c714abe4ffc08c53a..0000000000000000000000000000000000000000
Binary files a/library/digital_resources/Lekiosk/tests/catalogue_from_http.xml and /dev/null differ
diff --git a/library/digital_resources/Lekiosk/tests/new_releasedate_format.xml b/library/digital_resources/Lekiosk/tests/new_releasedate_format.xml
deleted file mode 100644
index 643f478f466f564faec732887378a9b0f7797ee6..0000000000000000000000000000000000000000
Binary files a/library/digital_resources/Lekiosk/tests/new_releasedate_format.xml and /dev/null differ
diff --git a/library/digital_resources/Lekiosk/tests/token.json b/library/digital_resources/Lekiosk/tests/token.json
deleted file mode 100644
index 53c53a4850f8c1e9caf8c69a6d98302ecb4cb212..0000000000000000000000000000000000000000
--- a/library/digital_resources/Lekiosk/tests/token.json
+++ /dev/null
@@ -1,2 +0,0 @@
-{"success":true,"result":{"username":"test@test.com","token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MjY2MjAxNiwibmFtZSI6Illvbm5lQGdtYWlsLmNvbSIsImV4cCI6MTUxNzM5OTE0M30.qZuwpsrZmk95LU0XYKPBFqpJJ4wxOVyZnJ_Gt3panxw","authenticationType":3,"infos":{"userId":1661016,"userIdinscription":11132,"userName":"test@test.com","bibliothequeIp":888,"bibliothequeAccount":"account@bib.fr","idBouquet":2136,"storeId":1,"credits":4994,"creditsPerUser":5000}}}
-
diff --git a/library/digital_resources/Lekiosk/tests/updated_catalogue_from_http.xml b/library/digital_resources/Lekiosk/tests/updated_catalogue_from_http.xml
deleted file mode 100644
index f5f17c236f16b3cd67bc511c22333336dd350175..0000000000000000000000000000000000000000
Binary files a/library/digital_resources/Lekiosk/tests/updated_catalogue_from_http.xml and /dev/null differ
diff --git a/library/digital_resources/Skilleos/Config.php b/library/digital_resources/Skilleos/Config.php
index 99ee2e14216614be7c08c9c61a18683360915eff..945bf32faa44af5d275f251d97a9581a1ad058b9 100644
--- a/library/digital_resources/Skilleos/Config.php
+++ b/library/digital_resources/Skilleos/Config.php
@@ -79,7 +79,7 @@ class Skilleos_Config extends Class_DigitalResource_Config {
   }
 
 
-  public function renderHarvestDiagOn($view) {
+  public function renderHarvestDiagOn($view) : string{
     $service = $this->getServiceInstance();
 
     $token_url = $service->getTokenUrl();
diff --git a/tests/application/modules/admin/controllers/AdminIndexControllerTest.php b/tests/application/modules/admin/controllers/AdminIndexControllerTest.php
index 4e5cf71a55d0edcc10a30742ab53fc88ce15b7ce..c7e3ea8ecd78efa10f930ed1af8e8f31c1ed12cf 100644
--- a/tests/application/modules/admin/controllers/AdminIndexControllerTest.php
+++ b/tests/application/modules/admin/controllers/AdminIndexControllerTest.php
@@ -133,12 +133,6 @@ class AdminIndexControllerAdminVarActionTest extends Admin_AbstractControllerTes
   }
 
 
-  /** @test */
-  public function leKioskSSOModeShouldBePresent() {
-    $this->assertXpathContentContains('//td', 'Lekiosk_SSO_MODE');
-  }
-
-
   /** @test */
   public function boitePanierAutoKeyShouldBePresent() {
     $this->assertXpathContentContains('//td', 'BOITE_PANIER_AUTO');
diff --git a/tests/db/UpgradeDBTest.php b/tests/db/UpgradeDBTest.php
index 9d0a873efb8b829b38b956bd7a2e8ab40a9ca089..cdc4f2c46f49f10f4ebb003b1d06cef66ffa0eea 100644
--- a/tests/db/UpgradeDBTest.php
+++ b/tests/db/UpgradeDBTest.php
@@ -5170,3 +5170,24 @@ class UpgradeDB_447_Test extends UpgradeDBTestCase {
     $this->assertFieldNotNullable($table_name, $field_name);
   }
 }
+
+
+
+
+class UpgradeDB_448_Test extends UpgradeDBTestCase {
+
+  public function prepare() {
+    $this->silentQuery("delete from bib_admin_var where clef='Cafeyn_HARVEST_URL'");
+    $this->query('INSERT INTO bib_admin_var (clef, valeur) VALUES ("Lekiosk_HARVEST_URL", "https://apipros.lekiosk.com")');
+    Class_AdminVar::clearCache();
+  }
+
+
+  /** @test */
+  public function harvestUrlShouldHaveBeenModified(){
+    $row = $this->query('select valeur from bib_admin_var where clef="Cafeyn_HARVEST_URL"')
+                ->fetch();
+
+    $this->assertEquals('https://partner-api.cafeyn.co', $row['valeur'] ?? '');
+  }
+}
diff --git a/tests/library/Class/Migration/DigitalResource/CafeynTest.php b/tests/library/Class/Migration/DigitalResource/CafeynTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ee307f85e0cbfe6a45ef5a846cd7c79370131087
--- /dev/null
+++ b/tests/library/Class/Migration/DigitalResource/CafeynTest.php
@@ -0,0 +1,153 @@
+<?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_Migration_DigitialResource_CafeynTest extends ModelTestCase {
+  protected
+    $_storm_default_to_volatile = true,
+    $_migration;
+
+  public function setUp() {
+    parent::setUp();
+    Class_DigitalResource::resetInstance();
+
+    $cfg_menus = ['H' => ['libelle' => 'Menu horizontal',
+                          'picto' => 'vide.gif',
+                          'menus' => [
+                                      ['type_menu' => 'MENU',
+                                       'libelle' => 'Pratique',
+                                       'picto' => 'bookmark.png',
+                                       'preferences' => [],
+                                       'sous_menus' => [
+                                                        ['type_menu' => 'ACCUEIL',
+                                                         'libelle' => 'Accueil',
+                                                         'picto' => 'vide.gif',
+                                                         'preferences' => [],
+                                                         'sous_menus' => ''],
+
+                                                        ['type_menu' => 'Lekiosk',
+                                                         'libelle' => 'Lien vers LeKiosk',
+                                                         'preferences' => [],
+                                                         'picto' => 'vide.gif'] ]]]]];
+
+    $cfg_menus_without_lekiosk = ['H' => ['libelle' => 'Menu horizontal',
+                                          'picto' => 'vide.gif',
+                                          'menus' => [
+                                                      ['type_menu' => 'MENU',
+                                                       'libelle' => 'Pratique',
+                                                       'picto' => 'bookmark.png',
+                                                       'preferences' => [],
+                                                       'sous_menus' => [
+                                                                        ['type_menu' => 'ACCUEIL',
+                                                                         'libelle' => 'Accueil',
+                                                                         'picto' => 'vide.gif',
+                                                                         'preferences' => [],
+                                                                         'sous_menus' => ''] ]]]]];
+
+
+    $profil_adulte = $this->fixture('Class_Profil',
+                                    ['id' => 22,
+                                     'parent_id' => null])
+                          ->setBrowser('opac')
+                          ->setLibelle('Profil Adulte')
+                          ->setCfgMenus($cfg_menus);
+
+    $profil_without_lekiosk = $this->fixture('Class_Profil',
+                                             ['id' => 23,
+                                              'rewrite_url' => 'adulte'])
+                                   ->setBrowser('opac')
+                                   ->setLibelle('Profil Adulte')
+                                   ->setCfgMenus($cfg_menus_without_lekiosk);
+
+
+    Class_Profil::setCurrentProfil($profil_adulte);
+    $permission = Class_Permission::findOrCreateByCode('Lekiosk');
+    $permission->permitTo( $this->fixture('Class_UserGroup',
+                                          ['id' => 2,
+                                           'libelle' => 'team ONE',
+                                          ]), new Class_Entity())->save();
+    $this->fixture(Class_Album::class,
+               ['id' => 10,
+                'type_doc_id' => 'Lekiosk',
+                 'titre'=> 'Le kiosk'
+               ]);
+    $this->fixture('Class_AdminVar',
+                   ['id' => 'Lekiosk_ID',
+                    'valeur' => 1]);
+    $this->fixture('Class_AdminVar',
+                   ['id' => 'Lekiosk_HTTP_LOGIN',
+                    'valeur' => 'login']);
+
+    $this->fixture('Class_AdminVar',
+                   ['id' => 'Lekiosk_HTTP_PASSWORD',
+                    'valeur' => 'password']);
+
+
+    $this->_migration = (new Class_Migration_DigitalResource_Cafeyn())
+      ->setMemoryCleaner(function(){})
+      ->run();
+  }
+
+
+  public function tearDown() {
+    Class_DigitalResource::resetInstance();
+    parent::tearDown();
+  }
+
+
+ /** @test */
+  public function albumLeKioskShouldBeDeleted() {
+    $this->assertNull(Class_Album::find(10));
+  }
+
+
+  /** @test */
+  public function adminVarLeKioskIdShoudBeUpdated() {
+    $this->assertNotNull(Class_AdminVar::findFirstBy(['clef' => 'Cafeyn_ID',
+                                                      'valeur' => 1]));
+  }
+
+
+  /** @test */
+  public function adminVarCafeynAPIIdShouldBeUpdated(){
+    $this->assertEquals('login', Class_AdminVar::get( 'Cafeyn_API_ID'));
+  }
+
+
+  /** @test */
+    public function adminVarCafeynAPIPasswordShouldBeUpdated(){
+      $this->assertEquals('password', Class_AdminVar::get( 'Cafeyn_API_PASSWORD'));
+    }
+
+
+  /** @test */
+  public function profilMenuWithAssimilShouldContainsCafeyn() {
+    $this->assertEquals('Cafeyn', Class_Profil::find(22)->getCfgMenusAsArray()['H']['menus'][0]['sous_menus'][1]['type_menu']);
+
+  }
+
+
+  /** @test */
+   public function groupShouldHaveCafeynPermission(){
+     $this->assertTrue(Class_UserGroup::find(2)->hasPermission(Class_Permission::findOrCreateByCode('Cafeyn')));
+  }
+
+}
diff --git a/tests/library/Class/Migration/DigitalResource/LeKioskTest.php b/tests/library/Class/Migration/DigitalResource/LeKioskTest.php
index 180ca3d7eabf0fd4f20d6081f46c414a566aa23e..15282cb5e2bca482d79102c6375a97ad7a61a57d 100644
--- a/tests/library/Class/Migration/DigitalResource/LeKioskTest.php
+++ b/tests/library/Class/Migration/DigitalResource/LeKioskTest.php
@@ -93,7 +93,7 @@ class Class_Migration_DigitialResource_LeKioskTest extends ModelTestCase {
                    ['id' => 'LEKIOSK_SSO_MODE',
                     'valeur' => 'cas']);
 
-    $this->_migration = (new Class_Migration_DigitalResource_LeKiosk())
+    $this->_migration = (new Class_Migration_DigitalResource_Cafeyn())
       ->setMemoryCleaner(function(){})
       ->run();
   }
@@ -107,21 +107,14 @@ class Class_Migration_DigitialResource_LeKioskTest extends ModelTestCase {
 
   /** @test */
   public function adminVarLeKioskIdShoudBeUpdated() {
-    $this->assertNotNull(Class_AdminVar::findFirstBy(['clef' => 'Lekiosk_ID',
+    $this->assertNotNull(Class_AdminVar::findFirstBy(['clef' => 'Cafeyn_ID',
                                                       'valeur' => 1]));
   }
 
 
   /** @test */
-  public function adminVarLeKioskSsoModeShoudBeUpdated() {
-    $this->assertNotNull(Class_AdminVar::findFirstBy(['clef' => 'Lekiosk_SSO_MODE',
-                                                      'valeur' => 'cas']));
-  }
-
-
-  /** @test */
-  public function profilMenuWithAssimilShouldContainsLekiosk() {
-    $this->assertEquals('Lekiosk', Class_Profil::find(22)->getCfgMenusAsArray()['H']['menus'][0]['sous_menus'][1]['type_menu']);
+  public function profilMenuWithAssimilShouldContainsCafeyn() {
+    $this->assertEquals('Cafeyn', Class_Profil::find(22)->getCfgMenusAsArray()['H']['menus'][0]['sous_menus'][1]['type_menu']);
   }
 
 
@@ -129,7 +122,7 @@ class Class_Migration_DigitialResource_LeKioskTest extends ModelTestCase {
   public function teamOneShouldHavePermissionOnLekiosk() {
     if (!$permissions = Class_UserGroup::find(2)->getPermissions())
       return $this->fail();
-    $this->assertEquals('Lekiosk', array_shift($permissions)->getCode());
+    $this->assertEquals('Cafeyn', array_shift($permissions)->getCode());
   }
 
 
diff --git a/tests/library/Class/MoteurRechercheTest.php b/tests/library/Class/MoteurRechercheTest.php
index e7234bdc2796924c59f26e4c9ec572d1a9013112..6b7aa5b03f1d4a17ccfd55ffd9632b2325361f06 100644
--- a/tests/library/Class/MoteurRechercheTest.php
+++ b/tests/library/Class/MoteurRechercheTest.php
@@ -404,12 +404,12 @@ class MoteurRechercheSimpleTest extends MoteurRechercheTestCase {
             [['expressionRecherche' => '',
               'digital_lib' => '1'],
              'nb_mots'=> 0,
-             'req_liste' => $this->listSqlWith("(type_doc in ('100','101','102','103','105','109','110','111','112','113','115','116','117','119','Arkhenum','ArteCampus','ArteVod','Artips','Assimil','Bacon','Cvs','Cyberlibris','DiMusic','Kidilangues','LaSourisQuiRaconte','Lekiosk','LesYeuxDoc','MaPetiteMediatheque','Mobidys','Musicme','Numilog','Omeka','Skilleos','StoryPlayR','ToutApprendre','Whisperies'))")],
+             'req_liste' => $this->listSqlWith("(type_doc in ('100','101','102','103','105','109','110','111','112','113','115','116','117','119','Arkhenum','ArteCampus','ArteVod','Artips','Assimil','Bacon','Cafeyn','Cvs','Cyberlibris','DiMusic','Kidilangues','LaSourisQuiRaconte','LesYeuxDoc','MaPetiteMediatheque','Mobidys','Musicme','Numilog','Omeka','Skilleos','StoryPlayR','ToutApprendre','Whisperies'))")],
 
             [['expressionRecherche' => 'logo',
               'digital_lib' => '1'],
              'nb_mots'=> 1,
-             'req_liste' => $this->listSqlWith($match_axes . " AGAINST('+(LOGO LOGOS)' IN BOOLEAN MODE) and (type_doc in ('100','101','102','103','105','109','110','111','112','113','115','116','117','119','Arkhenum','ArteCampus','ArteVod','Artips','Assimil','Bacon','Cvs','Cyberlibris','DiMusic','Kidilangues','LaSourisQuiRaconte','Lekiosk','LesYeuxDoc','MaPetiteMediatheque','Mobidys','Musicme','Numilog','Omeka','Skilleos','StoryPlayR','ToutApprendre','Whisperies'))",
+             'req_liste' => $this->listSqlWith($match_axes . " AGAINST('+(LOGO LOGOS)' IN BOOLEAN MODE) and (type_doc in ('100','101','102','103','105','109','110','111','112','113','115','116','117','119','Arkhenum','ArteCampus','ArteVod','Artips','Assimil','Bacon','Cafeyn','Cvs','Cyberlibris','DiMusic','Kidilangues','LaSourisQuiRaconte','LesYeuxDoc','MaPetiteMediatheque','Mobidys','Musicme','Numilog','Omeka','Skilleos','StoryPlayR','ToutApprendre','Whisperies'))",
                                                "MATCH(auteurs) AGAINST('P_LOGO') desc, MATCH(titres) AGAINST('P_LOGO') desc, MATCH(titres) AGAINST('LOGO') desc, MATCH(auteurs) AGAINST('LOGO') desc, date_creation desc")],
 
             [['expressionRecherche' => '',