diff --git a/cosmogramme/VERSIONS_HOTLINE/133561 b/cosmogramme/VERSIONS_HOTLINE/133561
new file mode 100644
index 0000000000000000000000000000000000000000..08410a83e008a45d2e645612f6add5522b7e04d4
--- /dev/null
+++ b/cosmogramme/VERSIONS_HOTLINE/133561
@@ -0,0 +1 @@
+ - ticket #133561 : Cosmogramme : Ajout de la possibilité de lancer certains traitements uniquement
\ No newline at end of file
diff --git a/cosmogramme/php/classes/classe_notice_integration.php b/cosmogramme/php/classes/classe_notice_integration.php
index 20a3e8c116e35aa4e9c8d8201a9dce447a1c6eb2..4b7414f96f7fa0ab6e6386f6e0eeffe1eb19cc1c 100644
--- a/cosmogramme/php/classes/classe_notice_integration.php
+++ b/cosmogramme/php/classes/classe_notice_integration.php
@@ -28,6 +28,8 @@ require_once 'classe_profil_donnees.php';
 require_once 'classe_communication.php';
 
 class notice_integration {
+  use Trait_CodifProviderAware;
+
   const
     RECORD_REJECT = 0,
     RECORD_INSERT = 1,
@@ -75,8 +77,6 @@ class notice_integration {
   /** @category testing */
   protected $_service_runner;
 
-  protected $_codif_provider;
-
   protected $_raw_data;
 
 
@@ -594,7 +594,7 @@ class notice_integration {
   protected function _getCodifAuteurRenvois() {
     $see_also = [];
     foreach($this->notice['auteurs'] as $author) {
-      if (($codif = $this->_getCodifAuteur($author))
+      if (($codif = $this->_getCodifAuthorFor($author))
           && $codif->hasMotsRenvois())
         $see_also[] = $codif->getMotsRenvois();
     }
@@ -617,7 +617,7 @@ class notice_integration {
     $see_also = [];
 
     foreach($this->notice['matieres'] as $subject) {
-      if (($codif = $this->_getCodifSubject($subject))
+      if (($codif = $this->_getCodifSubjectFor($subject))
           && $codif->hasMotsRenvois())
         $see_also[] = $codif->getMotsRenvois();
     }
@@ -950,7 +950,7 @@ class notice_integration {
     // Matieres
     if($this->notice["matieres"])  {
       foreach($this->notice["matieres"] as $matiere)  {
-        if (!$codif_matiere = $this->_getCodifSubject($matiere)) continue;
+        if (!$codif_matiere = $this->_getCodifSubjectFor($matiere)) continue;
         $facettes[]="M".$codif_matiere->getId();
       }
     }
@@ -1016,22 +1016,12 @@ class notice_integration {
 
 
   public function getFacetteAuteur($auteur) {
-    return ($codif = $this->_getCodifAuteur($auteur))
+    return ($codif = $this->_getCodifAuthorFor($auteur))
       ? $codif->asFacet()
       : '';
   }
 
 
-  protected function _getCodifAuteur($auteur) {
-    return $this->getCodifProvider()->getAuthor($auteur);
-  }
-
-
-  protected function _getCodifSubject($subject) {
-    return $this->getCodifProvider()->getSubject($subject);
-  }
-
-
   protected function ecrireArticlePeriodique() {
     if( 1 == $this->notice["statut"])
       return $this->deleteRecordArticles();
@@ -1458,32 +1448,17 @@ class notice_integration {
   }
 
 
-
   public function getStatut() {
     return $this->statut;
   }
 
 
-  protected function getCodifProvider() {
-    if (null == $this->_codif_provider)
-      $this->_codif_provider = (new Class_Cosmogramme_Integration_CodifProvider)
-        ->setIndexation($this->indexation);
-
-    return $this->_codif_provider;
-  }
-
-
   protected function _isIncremental() {
     return Class_Cosmogramme_Integration::TYPE_OPERATION_INCREMENT == $this->type_operation;
   }
+}
 
 
-  /** @category testing */
-  public function setCodifProvider($provider) {
-    $this->_codif_provider = $provider;
-    return $this;
-  }
-}
 
 
 class Service_Runner {
diff --git a/cosmogramme/php/integration/periodiques.php b/cosmogramme/php/integration/periodiques.php
deleted file mode 100644
index 5f978ce67f58e8f1a673f415a2698f00f54510bb..0000000000000000000000000000000000000000
--- a/cosmogramme/php/integration/periodiques.php
+++ /dev/null
@@ -1,173 +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 
- */
-/////////////////////////////////////////////////////////////////////////
-// INDEXATION DES PERIODIQUES
-/////////////////////////////////////////////////////////////////////////
-
-require_once("classe_notice_integration.php");
-require_once("classe_indexation.php");
-$notice=new notice_integration();
-$ix = new indexation();
-$notice->setParamsIntegration(0,0,1,"");
-
-$titre="Indexation des articles de périodiques";
-setVariable("traitement_phase",$titre);
-if($phase=="PERIODIQUES_0")
-{
-	$log->log("<h4>$titre</h4>");
-	$chrono100notices->start();
-	unset($phase_data);
-	$phase_data["nombre"]=0;
-	$phase_data["not_found"]=0;
-	$phase_data["timeStart"]=time();
-	$phase_data["pointeur_article"]="0";
-	$phase = "PERIODIQUES_1";
-}
-
-if($phase == "PERIODIQUES_1")
-{
-	$start_periodiques=date("Y-m-d H:i:s",$phase_data["timeStart"]);
-	if(!$mode_cron and $phase_data["nombre"]>0) print("<h4>$titre</h4>");
-	$req="select * from notices_articles"
-		." Where id_article>".	$phase_data["pointeur_article"]
-		." and date_maj >='".date("Y-m-d",$timeStart)."'"
-		." and clef_chapeau > ''"
-		." and unimarc > ''"
-		." order by id_article";
-	$resultat=$sql->prepareListe($req);
-
-	// Parser les articles
-	while($enreg=$sql->fetchNext($resultat))
-	{
-		if(!$mode_cron and $chrono->tempsPasse() > $timeout) sauveContexte();
-
-		// données article
-		$data=$notice->getDataArticlePeriodique($enreg["unimarc"]);
-
-		// lire la notice du numero
-		$numero=$sql->fetchEnreg("select id_notice,facettes,titres,auteurs,matieres,date_maj from notices where clef_chapeau='".$enreg["clef_chapeau"]."' and tome_alpha='".$enreg["clef_numero"]."'");
-		if($numero["id_notice"])
-		{
-			$new_enreg=array();
-			$facettes=$numero["facettes"];
-
-			// reset facettes
-			if($numero["date_maj"]<$start_periodiques)
-			{
-				$facettes="";
-				$controle=explode(" ",$numero["facettes"]);
-				for($i=0; $i < count($controle); $i++)
-				{
-					$tp=substr($controle[$i],0,1);
-					if($tp !="A" and $tp!="M") $facettes.=" ".$controle[$i];
-				}
-			}
-
-			// Facettes Auteurs
-			if($data["auteurs"])
-			{
-				foreach($data["auteurs"] as $auteur)
-				{
-					$code_alpha=$ix->alphaMaj($auteur);
-					$code_alpha=str_replace(" ","x",$code_alpha);
-					if(!$code_alpha) continue;
-					$enreg_auteur=$sql->fetchEnreg("Select * from codif_auteur where MATCH(formes) AGAINST('\"".$code_alpha."\"' IN BOOLEAN MODE) ");
-					if(!$enreg_auteur["id_auteur"])
-					{
-						$pos=strscan($auteur,"|");
-						$nom_prenom = trim(substr($auteur,($pos+1))." ".substr($auteur,0,$pos));
-						$id_auteur=$sql->insert("codif_auteur",array("libelle" => $nom_prenom,"formes" => $code_alpha));
-					}
-					else $id_auteur=$enreg_auteur["id_auteur"];
-					$facette=" A".$id_auteur;
-					if(strpos($facettes." ",$facette." ")===false) $facettes.=$facette;
-				}
-			}
-
-			// Facettes Matieres
-			if($data["matieres"])
-			{
-				foreach($data["matieres"] as $matiere)
-				{
-					$code_alpha=$ix->alphaMaj($matiere);
-					if(!$code_alpha) continue;
-					$enreg_matiere=$sql->fetchEnreg("Select * from codif_matiere where code_alpha='$code_alpha'");
-					if(!$enreg_matiere["id_matiere"]) $id_matiere=$sql->insert("codif_matiere",array("libelle" => $matiere,"code_alpha" => $code_alpha));
-					else $id_matiere=$enreg_matiere["id_matiere"];
-					$facette=" M".$id_matiere;
-					if(strpos($facettes." ",$facette." ")===false) $facettes.=$facette;
-				}
-			}
-
-			// index fulltext
-			$data["titres"][]=$numero["titres"];
-			$new_enreg["titres"]=$ix->getFulltext($data["titres"]);
-
-			$data["auteurs"][]=$numero["auteurs"];
-			$new_enreg["auteurs"]=$ix->getFulltext($data["auteurs"]);
-
-			$data["matieres"][]=$numero["matieres"];
-			$new_enreg["matieres"]=$ix->getFulltext($data["matieres"]);
-
-			// maj enreg
-			$new_enreg["date_maj"]=$start_periodiques;
-			$new_enreg["facettes"]=trim($facettes);
-			$req="update notices set @SET@ where id_notice=".$numero["id_notice"];
-			$sql->update($req,$new_enreg);
-		}
-		else
-		{
-			$phase_data["not_found"]++;
-		}
-
-		// Pointeur d'avancement et trace
-		$phase_data["pointeur_article"]=$enreg["id_article"];
-		$phase_data["nombre"]++;
-		traceTraitementPeriodique();
-	}
-
-	// recap
-	if($phase_data["nombre"]==0) $log->log(BR.'<span class="vert">Aucun article à traiter</span><br>');
-	else
-	{
-		$log->log(BR.'<span class="vert">'.$phase_data["nombre"].' articles(s) traité(s)</span>'.BR);
-		$chrono->timeStart=$phase_data["timeStart"];
-		$log->log('<span class="vert">Temps de traitement : '.$chrono->end()." (".$chrono->moyenne($phase_data["nombre"],"articles").")</span>".BR);
-	}
-	if($phase_data["not_found"]) $log->log('<span class="violet">Notices orphelines : '.$phase_data["not_found"].'</span>'.BR);
-}
-
-// ----------------------------------------------------------------
-// Ecriture logs et affichage écran
-// ----------------------------------------------------------------
-function traceTraitementPeriodique()
-{
-	global $log,$phase_data,$chrono100notices;
-
-	// Affichage toutes les 100
-	if($phase_data["nombre"] % 100 == 0)
-	{
-		$log->log("article ".$phase_data["nombre"]." (" .$chrono100notices->tempsPasse()." secondes)<br>");
-		$chrono100notices->start();
-	}
-
-}
-?>
diff --git a/cosmogramme/php/integration/pseudo_notices.php b/cosmogramme/php/integration/pseudo_notices.php
deleted file mode 100644
index ab67cab00684c6bdbc3c6a2cff5624ddb46b43d4..0000000000000000000000000000000000000000
--- a/cosmogramme/php/integration/pseudo_notices.php
+++ /dev/null
@@ -1,25 +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
- */
-
-startIntegrationPhase('PseudoRecordCms');
-startIntegrationPhase('PseudoRecordRss');
-startIntegrationPhase('PseudoRecordSitotheque');
-startIntegrationPhase('PseudoRecordAlbum');
\ No newline at end of file
diff --git a/cosmogramme/php/integre_traite_main.php b/cosmogramme/php/integre_traite_main.php
index 7d5ffb80649f8eeed5e3615560361c179209bdf6..074e8fe610f9796948e9fd77f462b2057b29fde4 100644
--- a/cosmogramme/php/integre_traite_main.php
+++ b/cosmogramme/php/integre_traite_main.php
@@ -198,7 +198,10 @@ if (!$should_skip_records) {
   // PSEUDO-NOTICES - cms rss sitotheque et albums (phase 0.1 a 0.6)
   // ----------------------------------------------------------------
   if ($phase > 0.1 and $phase < 1) {
-    include('integration/pseudo_notices.php');
+    startIntegrationPhase('PseudoRecordCms');
+    startIntegrationPhase('PseudoRecordRss');
+    startIntegrationPhase('PseudoRecordSitotheque');
+    startIntegrationPhase('PseudoRecordAlbum');
     $phase = 1;
   }
 
@@ -215,16 +218,11 @@ if (!$should_skip_records) {
   setVariable("traitement_phase", "Suppression des notices sans exemplaire");
   startIntegrationPhase('DeleteRecordWithoutItem');
 
-  if ($phase == 2) $phase = "PERIODIQUES_0";
-
   // ----------------------------------------------------------------
   // INDEXATION DES ARTICLES DE PERIODIQUES
   // ----------------------------------------------------------------
-  if (substr($phase, 0, 11) == "PERIODIQUES")
-    {
-      include("integration/periodiques.php");
-      $phase = 2;
-    }
+  if ($phase == 2)
+    startIntegrationPhase('SerialArticlesIndex');
 
 
   // ----------------------------------------------------------------
diff --git a/cosmogramme/tests/php/classes/NanookRecordsIntegrationTest.php b/cosmogramme/tests/php/classes/NanookRecordsIntegrationTest.php
index 6b4a7f607a0d8b7f8b5f6eed3b846ed39663819f..c4431e70b003fae25e0afe5345970efd4e45b315 100644
--- a/cosmogramme/tests/php/classes/NanookRecordsIntegrationTest.php
+++ b/cosmogramme/tests/php/classes/NanookRecordsIntegrationTest.php
@@ -196,7 +196,7 @@ class NanookRecordsIntegrationInterestEsperluetteTest extends NanookRecordsInteg
 
   /** @test */
   public function deweyShouldContainsEsperluette() {
-    $this->assertEquals('80993352  ESPERLUETTE ESPERLUET 2014', $this->notice->getDewey());
+    $this->assertEquals('80993352 ESPERLUETTE ESPERLUET 2014', $this->notice->getDewey());
   }
 }
 
diff --git a/cosmogramme/tests/php/classes/NoticeIntegrationTest.php b/cosmogramme/tests/php/classes/NoticeIntegrationTest.php
index 9dc927120c59e4c3df7bed2afc483e2e60ab4eae..75ce412ec17eaac86d99df95937302a9f1dd1d7d 100644
--- a/cosmogramme/tests/php/classes/NoticeIntegrationTest.php
+++ b/cosmogramme/tests/php/classes/NoticeIntegrationTest.php
@@ -719,7 +719,7 @@ class NoticeIntegrationBearsBeerMicrobibTest extends NoticeIntegrationTestCase {
 
   /** @test */
   public function auteursShouldContainsBEAULIEUJIMMY() {
-    $this->assertEquals('BEAULIEU BOLI JIMMY JIMI APOSTOLIDES APOSTOLID JEAN JAN MARIE MARI BOSSE BOS SIMON BOUCHARD BOUCHAR GREGOIRE GREGOIR PIERRE PIER BROERSMA MATTHEW MATEW DELPORTE DELPORT JULIE JULI DOYON DOION RIVEST RIVES EKEBOM EKEBON TERHI TERI FORSYTHE FORSIT GENEST CATHERINE KATERIN GIARD JIAR LUC  GIRARD JIRAR PASCAL PASKAL GOLDBERG GOLDBER ELEONORE ELEONOR HUBER UB MARKUS MARKU IRIS IRI JOLY JOLI BENOIT BENOI LEMAY LEMAI SYLVAIN SILVIN MUSTURI TOMMI TOMI NYLSO NILSO OBOM OBON PISHIER PICHI RICCI RIKSI STEFANO SAMSON JACQUES JAK DIECK DIEK MARTIN TOM TRAHAN TRAN SEBASTIEN SEBASTIN TURGEON TURJON DAVID DAVI VAYRYNEN VAIRINAN MIKKO MIKO VIAU VIO MICHEL WARD OIR BARNABY BARNABI WIGGERT OUIJER GREGOR ZVIANE ZVIAN',
+    $this->assertEquals('BEAULIEU BOLI JIMMY JIMI APOSTOLIDES APOSTOLID JEAN JAN MARIE MARI BOSSE BOS SIMON BOUCHARD BOUCHAR GREGOIRE GREGOIR PIERRE PIER BROERSMA MATTHEW MATEW DELPORTE DELPORT JULIE JULI DOYON DOION RIVEST RIVES EKEBOM EKEBON TERHI TERI FORSYTHE FORSIT GENEST CATHERINE KATERIN GIARD JIAR LUC GIRARD JIRAR PASCAL PASKAL GOLDBERG GOLDBER ELEONORE ELEONOR HUBER UB MARKUS MARKU IRIS IRI JOLY JOLI BENOIT BENOI LEMAY LEMAI SYLVAIN SILVIN MUSTURI TOMMI TOMI NYLSO NILSO OBOM OBON PISHIER PICHI RICCI RIKSI STEFANO SAMSON JACQUES JAK DIECK DIEK MARTIN TOM TRAHAN TRAN SEBASTIEN SEBASTIN TURGEON TURJON DAVID DAVI VAYRYNEN VAIRINAN MIKKO MIKO VIAU VIO MICHEL WARD OIR BARNABY BARNABI WIGGERT OUIJER GREGOR ZVIANE ZVIAN',
                         $this->notice_integration->noticeToDBEnreg($this->notice_data)['auteurs']);
   }
 
@@ -1205,7 +1205,7 @@ class NoticeIntegrationArchivesAlsaceTest extends NoticeIntegrationTestCase {
 
   /** @test */
   public function matieresShouldAlsaceDescriptions() {
-    $this->assertEquals('ALSACE ALSAS FRANCE FRANS DESCRIPTIONS DESKRIPSION VOYAGES VOIAJ VUES VU 1870  1914 OUVRAGES OUVRAJ ILLUSTRES ILUSTR 1871 1918 PERIODE PERIOD ALLEMANDE ALEMAND',
+    $this->assertEquals('ALSACE ALSAS FRANCE FRANS DESCRIPTIONS DESKRIPSION VOYAGES VOIAJ VUES VU 1870 1914 OUVRAGES OUVRAJ ILLUSTRES ILUSTR 1871 1918 PERIODE PERIOD ALLEMANDE ALEMAND',
                         Class_Notice::find(1)->getMatieres());
   }
 
diff --git a/library/Class/Cosmogramme/Integration/Chronometre.php b/library/Class/Cosmogramme/Integration/Chronometre.php
index 369a1b4c1a20ea0dbd779c8cb43b3325a0c86c04..01ab883f196c6c627fae7e990f41b0ee28c09981 100644
--- a/library/Class/Cosmogramme/Integration/Chronometre.php
+++ b/library/Class/Cosmogramme/Integration/Chronometre.php
@@ -56,6 +56,11 @@ class Class_Cosmogramme_Integration_Chronometre {
   }
 
 
+  public function mainStartDate() {
+    return date('Y-m-d', $this->_main->getStart());
+  }
+
+
   public function setOnFile($chrono) {
     $this->_on_file = $chrono;
     return $this;
diff --git a/library/Class/Cosmogramme/Integration/CodifProvider.php b/library/Class/Cosmogramme/Integration/CodifProvider.php
index 4bf5db29a7d8bd41a9c52f044ed67ac1e691a057..d0bb3d9c7e8f7176b24a47fb944c99d45fc5c4ca 100644
--- a/library/Class/Cosmogramme/Integration/CodifProvider.php
+++ b/library/Class/Cosmogramme/Integration/CodifProvider.php
@@ -21,8 +21,6 @@
 
 
 class Class_Cosmogramme_Integration_CodifProvider {
-  use Trait_TimeSource;
-
   protected $_indexation;
 
 
@@ -35,7 +33,7 @@ class Class_Cosmogramme_Integration_CodifProvider {
   public function getAuthor($label) {
     return $this->_getFrom($label,
                            str_replace(' ', 'x', $this->_indexation->alphaMaj($label)),
-                           'Class_CodifAuteur');
+                           Class_CodifAuteur::class);
   }
 
 
@@ -47,17 +45,14 @@ class Class_Cosmogramme_Integration_CodifProvider {
   public function getOrCreateSubject($label) {
     // limit to the maximum size of code_alpha column in db to avoid duplicates
     $code = substr($this->_indexation->alphaMaj($label), 0, 255);
-    return $this->_getFrom($label, $code, 'Class_CodifMatiere');
+    return $this->_getFrom($label, $code, Class_CodifMatiere::class);
   }
 
 
   protected function _getFrom($value, $code, $model_class) {
-    if (!$code)
-      return;
-
-    $model = call_user_func_array([$model_class, 'findOrCreate'],
-                                  [$code, $value]);
-
-    return $model;
+    return $code
+      ? call_user_func_array([$model_class, 'findOrCreate'],
+                             [$code, $value])
+      : null;
   }
 }
\ No newline at end of file
diff --git a/library/Class/Cosmogramme/Integration/PhaseSerialArticlesIndex.php b/library/Class/Cosmogramme/Integration/PhaseSerialArticlesIndex.php
new file mode 100644
index 0000000000000000000000000000000000000000..66d940957ec3e06346a10de9b3cc6d59f0efc514
--- /dev/null
+++ b/library/Class/Cosmogramme/Integration/PhaseSerialArticlesIndex.php
@@ -0,0 +1,209 @@
+<?php
+/**
+ * Copyright (c) 2012-2021, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Class_Cosmogramme_Integration_PhaseSerialArticlesIndex
+  extends Class_Cosmogramme_Integration_PhaseAbstract {
+  use Trait_CodifProviderAware;
+
+  const MY_ID = 2;
+
+  protected
+    $_indexation,
+    $_seen_ids = [];
+
+  public function __construct($phase, $log, $chrono) {
+    parent::__construct($phase, $log, $chrono);
+    $this->_label = $this->_('Indexation des articles de périodiques');
+    $this->_indexation = Class_Indexation::getInstance();
+  }
+
+
+  /** @return array **/
+  protected function _previousPhaseIds() {
+    return [2];
+  }
+
+
+  public function _init($phase) {
+    $phase
+      ->resetDatas()
+      ->setData('nombre', 0)
+      ->setData('not_found', 0)
+      ->setData('start_date', static::getCurrentDate())
+      ->setData('start_date_time', static::getCurrentDateTime())
+      ->setData('pointeur_article', 0);
+
+    $this->_chrono
+        ->startOnFile()
+        ->startOnRecords();
+
+    return $this;
+  }
+
+
+  public function _execute() {
+    $this->_seen_ids = [];
+
+    while ($articles = $this->_findPage())
+      $this
+        ->_runPage($articles)
+        ->_cleanMemory();
+
+    if (!$this->_log)
+      return;
+
+    $this->_log
+      ->success($this->_('%s articles traités', $this->_getData('nombre')))
+      ->success($this->_('Temps de traitement : %s (%s)',
+                         $this->_chrono->endFile(),
+                         $this->_chrono->meanOnFile($this->_getData('nombre'),
+                                                    $this->_('articles'))));
+
+    if ($not_found = $this->_getData('not_found'))
+      $this->_log->info($this->_('Notices orphelines : %s', $not_found));
+  }
+
+
+  protected function _findPage() {
+    $params = ['where' => sprintf('date_maj >= "%s" and id_article > %s',
+                                  $this->_chrono->mainStartDate(),
+                                  $this->_getData('pointeur_article')),
+               'clef_chapeau not' => '',
+               'unimarc not' => '',
+               'order' => 'id_article',
+               'limit' => 100];
+
+    return Class_Notice_SerialArticles::findAllBy($params);
+  }
+
+
+  protected function _runPage($articles) {
+    if ($this->_log && (0 == ($this->_getData('nombre') % 100))) {
+      $this->_log->success($this->_('article %s (%s secondes)',
+                                    $this->_getData('nombre'),
+                                    $this->_chrono->elapsedOnRecords()));
+      $this->_chrono->startOnRecords();
+    }
+
+    foreach($articles as $article)
+      $this->_runOne($article);
+
+    return $this;
+  }
+
+
+  protected function _runOne($article) {
+    $this
+      ->_incrementData('nombre')
+      ->_setData('pointeur_article', $article->getId());
+
+    if (!$issue = $article->getIssueRecord()) {
+      $this->_incrementData('not_found');
+      return;
+    }
+
+    $record = $article->getMarcRecord();
+
+    $facets = $this->_issueFacets($issue);
+    $this->_handleAuthors($record, $issue, $facets)
+         ->_handleSubjects($record, $issue, $facets)
+         ->_handleTitles($record, $issue);
+
+    $issue
+      ->setDateMaj($this->_getData('start_date_time'))
+      ->setFacettes(implode(' ', $facets->getArrayCopy()))
+      ->save();
+  }
+
+
+  protected function _handleAuthors($record, $issue, $facets) {
+    $authors = $record->getAuteursUnimarc();
+    foreach($authors as $author)
+      $this->_injectCodifFacetIn($author, '_getCodifAuthorFor', $facets);
+
+    $authors[] = $issue->getAuteurs();
+    $issue->setAuteurs($this->_indexation->getFulltext($authors));
+
+    return $this;
+  }
+
+
+  protected function _handleSubjects($record, $issue, $facets) {
+    $subjects = $record->getMatieresLabels();
+    foreach($subjects as $subject)
+      $this->_injectCodifFacetIn($subject, '_getCodifSubjectFor', $facets);
+
+    $subjects[] = $issue->getMatieres();
+    $issue->setMatieres($this->_indexation->getFulltext($subjects));
+
+    return $this;
+  }
+
+
+  protected function _handleTitles($record, $issue) {
+    $titles = $record->getZonesTitre();
+    $titles[] = $issue->getTitres();
+    $issue->setTitres($this->_indexation->getFulltext($titles));
+
+    return $this;
+  }
+
+
+  protected function _injectCodifFacetIn($label, $method, $facets) {
+    if (!$codif = call_user_func([$this, $method], $label))
+      return $this;
+
+    $facet = $codif->asFacet();
+    if (!$facets->includes($facet))
+      $facets->add($facet);
+
+    return $this;
+  }
+
+
+  protected function _issueFacets($issue) {
+    $facets = new Storm_Collection(array_filter(explode(' ', $issue->getFacettes())));
+    if ($this->_hasAlreadySeen($issue))
+      return $facets;
+
+    $this->_setSeen($issue);
+
+    return $facets
+      ->select(function($facet)
+               {
+                 return !in_array(substr($facet, 0, 1),
+                                  [Class_CodifAuteur::CODE_FACETTE,
+                                   Class_CodifMatiere::CODE_FACETTE]);
+               });
+  }
+
+
+  protected function _hasAlreadySeen($issue) {
+    return in_array($issue->getId(), $this->_seen_ids);
+  }
+
+
+  protected function _setSeen($issue) {
+    $this->_seen_ids[] = $issue->getId();
+    return $this;
+  }
+}
diff --git a/library/Class/Cosmogramme/Integration/Record/Authority.php b/library/Class/Cosmogramme/Integration/Record/Authority.php
index 0ac248b9808504cea7d3032ffeabc91dfe060c14..0b402bead213ba630bb2aeb6dfee9f351e0ab7ea 100644
--- a/library/Class/Cosmogramme/Integration/Record/Authority.php
+++ b/library/Class/Cosmogramme/Integration/Record/Authority.php
@@ -21,13 +21,12 @@
 
 
 class Class_Cosmogramme_Integration_Record_Authority {
-  use Trait_TimeSource, Trait_Translator;
+  use Trait_TimeSource, Trait_Translator, Trait_CodifProviderAware;
 
   protected
     $_reader,
     $_integration,
-    $_authority_type,
-    $_codif_provider;
+    $_authority_type;
 
   public function __construct($integration) {
     $this->_integration = $integration;
@@ -149,7 +148,7 @@ class Class_Cosmogramme_Integration_Record_Authority {
 
   protected function _saveCodifFor($type, $label) {
     if (Class_Notice_AuthorityType::SUBJECT == $type)
-      $this->getCodifProvider()->getOrCreateSubject($label);
+      $this->_getCodifProvider()->getOrCreateSubject($label);
   }
 
 
@@ -212,20 +211,4 @@ class Class_Cosmogramme_Integration_Record_Authority {
     $prefs = $this->_integration->getProfilDonnees()->getIndexSystemsPrefs();
     return Class_Notice_AuthorityIndexSystem::collectionFromPrefs($prefs);
   }
-
-
-  protected function getCodifProvider() {
-    if (null == $this->_codif_provider)
-      $this->_codif_provider = (new Class_Cosmogramme_Integration_CodifProvider)
-        ->setIndexation($this->_indexation);
-
-    return $this->_codif_provider;
-  }
-
-
-  /** @category testing */
-  public function setCodifProvider($provider) {
-    $this->_codif_provider = $provider;
-    return $this;
-  }
 }
diff --git a/library/Class/Indexation.php b/library/Class/Indexation.php
index f2832c9e9599e24736b98bc037100b4f76401aa2..608484c00badea03cf1b1747764a01361b05e58b 100644
--- a/library/Class/Indexation.php
+++ b/library/Class/Indexation.php
@@ -248,30 +248,13 @@ class Class_Indexation {
     return $new;
   }
 
-// Rend une chaine de mots dedoublonnes et filtres
-  public function getFulltext($data) {
-    if (gettype($data) != 'array')
-      $data=array($data);
 
-    $new=' ';
-    foreach($data as $chaine)
-      {
-        $mots=$this->getMots($chaine);
-        foreach($mots as $mot)
-          {
-            $mot=' '.$mot.' ';
-            if(strpos($new,$mot) === false )
-              {
-                $new.=trim($mot).' ';
-                $phonem=' '.$this->phonetix(trim($mot)).' ';
-                if($phonem and strpos($new,$phonem) === false ) $new.=trim($phonem).' ';
-              }
-          }
-      }
-    return trim($new);
+  public function getFulltext($data) {
+    return (new Class_Indexation_Fulltext($this))->fromDatas($data);
   }
 
-// Rend le mot au singulier et au pluriel
+
+  // Rend le mot au singulier et au pluriel
   public function getPluriel( $mot )
   {
     if( strToUpper($mot) != $mot ) $mot=$this->alphaMaj($mot);
@@ -625,4 +608,3 @@ class Class_Indexation {
     else return '';
   }
 }
-?>
\ No newline at end of file
diff --git a/library/Class/Indexation/Fulltext.php b/library/Class/Indexation/Fulltext.php
new file mode 100644
index 0000000000000000000000000000000000000000..9a5648cca2ef57dc0f6c48ad27cd1f0f9c12e467
--- /dev/null
+++ b/library/Class/Indexation/Fulltext.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Copyright (c) 2012-2021, 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_Indexation_Fulltext {
+  protected
+    $_indexation,
+    $_terms;
+
+  public function __construct($indexation) {
+    $this->_indexation = $indexation;
+  }
+
+
+  public function fromDatas($datas) {
+    if (!is_array($datas))
+      $datas = [$datas];
+
+    $this->_terms = new Storm_Collection;
+
+    foreach($datas as $data)
+      $this->_handleString($data);
+
+    return implode(' ',
+                   $this->_terms
+                   ->select(function($term) { return '' != $term; })
+                   ->getArrayCopy());
+  }
+
+
+  protected function _handleString($value) {
+    if (!$value || !$words = array_filter($this->_wordsFrom($value)))
+      return $this;
+
+    foreach($words as $word)
+      $this->_handleWord($word);
+
+    return $this;
+  }
+
+
+  protected function _wordsFrom($value) {
+    return $this->_indexation->getMots($value);
+  }
+
+
+  protected function _handleWord($word) {
+    if (!$word || $this->_terms->includes($word))
+      return $this;
+
+    $this->_terms->add($word);
+
+    foreach(array_filter(explode(' ', $this->_phonetix($word))) as $phonem)
+      if (!$this->_terms->includes($phonem))
+        $this->_terms->add($phonem);
+
+    return $this;
+  }
+
+
+  protected function _phonetix($word) {
+    return $this->_indexation->phonetix($word);
+  }
+}
\ No newline at end of file
diff --git a/library/Class/Notice.php b/library/Class/Notice.php
index f297433a4b082103946ac88b9856e41cb6fedcc5..8acfd210d80531187425af3a776e839360723021 100644
--- a/library/Class/Notice.php
+++ b/library/Class/Notice.php
@@ -716,9 +716,7 @@ class Class_Notice extends Storm_Model_Abstract {
     foreach ($datas as $enreg) {
       if (!$enreg->getUnimarc()) continue;
 
-      $serial_article = new Class_Notice;
-      $serial_article->getNoticeUnimarc()->setNotice($enreg->getUnimarc(), 0);
-
+      $serial_article = $enreg->getMarcRecord();
       $article = ["titre" => $serial_article->getTitrePrincipal()];
       if ($complement = $serial_article->getComplementTitre())
         $article["titre"] .= " : " . $complement;
diff --git a/library/Class/Notice/SerialArticles.php b/library/Class/Notice/SerialArticles.php
index 48e4fcd502441203f108a20bec9236cf2164dea3..2a4254aa26d4d62fbeee826bd19f617d076f1d17 100644
--- a/library/Class/Notice/SerialArticles.php
+++ b/library/Class/Notice/SerialArticles.php
@@ -91,4 +91,15 @@ class Class_Notice_SerialArticles extends Storm_Model_Abstract {
     if (!$this->getClefNumero())
       $this->addError('Clé numero requise');
   }
+
+
+  public function getIssueRecord() {
+    return Class_Notice::findFirstBy(['clef_chapeau' => $this->getClefChapeau(),
+                                      'tome_alpha' => $this->getClefNumero()]);
+  }
+
+
+  public function getMarcRecord() {
+    return (new Class_Notice)->setUnimarc($this->getUnimarc());
+  }
 }
\ No newline at end of file
diff --git a/library/Trait/CodifProviderAware.php b/library/Trait/CodifProviderAware.php
new file mode 100644
index 0000000000000000000000000000000000000000..4ff8ceac71a2c044b816e89f60c03c07f13a9c95
--- /dev/null
+++ b/library/Trait/CodifProviderAware.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright (c) 2012-2021, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+trait Trait_CodifProviderAware {
+  protected $_codif_provider;
+
+  /** @category testing */
+  public function setCodifProvider($provider) {
+    $this->_codif_provider = $provider;
+    return $this;
+  }
+
+
+  protected function _getCodifProvider() {
+    if ($this->_codif_provider)
+      return $this->_codif_provider;
+
+    return $this->_codif_provider = (new Class_Cosmogramme_Integration_CodifProvider)
+      ->setIndexation(Class_Indexation::getInstance());
+  }
+
+
+  protected function _getCodifAuthorFor($label) {
+    return $this->_getCodifProvider()->getAuthor($label);
+  }
+
+
+  protected function _getCodifSubjectFor($subject) {
+    return $this->_getCodifProvider()->getSubject($subject);
+  }
+}
diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTest.php b/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTest.php
index a10dea586c342aac05c8dc06d9e6116e67508fa2..82a07a1b051ec5b929376cc7ba34ff1122f14710 100644
--- a/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTest.php
+++ b/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTest.php
@@ -92,7 +92,6 @@ abstract class PhaseNoticeImportTestCase extends PhaseNoticeTestCase {
 
     $time_source = (new TimeSourceForTest('2015-10-19'))->atCoffeeTime();
     Class_Cosmogramme_Integration_PhaseNotice::setTimeSource($time_source);
-    Class_Cosmogramme_Integration_CodifProvider::setTimeSource($time_source);
   }
 }
 
diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseSerialArticlesIndexTest.php b/tests/library/Class/Cosmogramme/Integration/PhaseSerialArticlesIndexTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..43915d993e0aa5f197778b79a907269ac86e26ad
--- /dev/null
+++ b/tests/library/Class/Cosmogramme/Integration/PhaseSerialArticlesIndexTest.php
@@ -0,0 +1,202 @@
+<?php
+/**
+ * Copyright (c) 2012-2021, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Class_Cosmogramme_Integration_PhaseSerialArticlesIndexTest
+  extends Class_Cosmogramme_Integration_PhaseTestCase {
+
+  protected
+    $_issue,
+    $_called;
+
+
+  protected function _getPreviousPhase() {
+    return (new Class_Cosmogramme_Integration_Phase(2))->beCron();
+  }
+
+
+  protected function _prepareFixtures() {
+    Class_CosmoVar::setValueOf('unimarc_zone_titre', '200$a');
+    Class_CosmoVar::setValueOf('unimarc_zone_matiere', '600$a');
+
+    $this->_issue = $this->fixture(Class_Notice::class,
+                                   ['id' => 2,
+                                    'clef_chapeau' => 'STRANGE----',
+                                    'tome_alpha' => '1',
+                                    'titres' => 'STRANGE STRANJ',
+                                    'auteurs' => '',
+                                    'matieres' => '',
+                                   ]);
+
+    $marc = (new Class_NoticeUnimarc_Fluent)
+      ->zoneWithChildren('200', ['a' => 'Les X-MEN'])
+      ->zoneWithChildren('701', ['a' => 'Lee', 'b' => 'Stan'])
+      ->zoneWithChildren('701', ['a' => 'Kirby', 'b' => 'Jack'])
+      ->zoneWithChildren('600', ['a' => 'Slips'])
+      ->zoneWithChildren('600', ['a' => 'Capes'])
+      ->zoneWithChildren('600', ['a' => 'Moulants'])
+      ->zoneWithChildren('600', ['a' => 'Collants'])
+      ;
+
+    $xmen = $this->fixture(Class_Notice_SerialArticles::class,
+                           ['id' => 2,
+                            'clef_chapeau' => 'STRANGE----',
+                            'clef_numero' => '1',
+                            'unimarc' => $marc->render(),
+                            'date_maj' => $this->_chrono->mainStartDate(),
+                           ]);
+
+    $marc = (new Class_NoticeUnimarc_Fluent)
+      ->zoneWithChildren('200', ['a' => 'Iron Man'])
+      ->zoneWithChildren('701', ['a' => 'Lee', 'b' => 'Stan'])
+      ->zoneWithChildren('701', ['a' => 'Lieber', 'b' => 'Larry'])
+      ->zoneWithChildren('701', ['a' => 'Heck', 'b' => 'Don'])
+      ->zoneWithChildren('600', ['a' => 'Armure'])
+      ->zoneWithChildren('600', ['a' => 'Jaune'])
+      ->zoneWithChildren('600', ['a' => 'Rouge'])
+      ->zoneWithChildren('600', ['a' => 'Bling-Bling'])
+      ;
+
+    $iron_man = $this->fixture(Class_Notice_SerialArticles::class,
+                               ['id' => 2,
+                                'clef_chapeau' => 'STRANGE----',
+                                'clef_numero' => '1',
+                                'unimarc' => $marc->render(),
+                                'date_maj' => $this->_chrono->mainStartDate(),
+                               ]);
+
+    $orphan = $this->fixture(Class_Notice_SerialArticles::class,
+                             ['id' => 3,
+                              'clef_chapeau' => 'UNKOWN----',
+                              'clef_numero' => '42',
+                              'unimarc' => $marc->render(),
+                              'date_maj' => $this->_chrono->mainStartDate(),
+                             ]);
+
+    $this->_called = false;
+    $this->onLoaderOfModel(Class_Notice_SerialArticles::class)
+         ->whenCalled('findAllBy')
+         ->willDo(function() use($xmen, $iron_man, $orphan)
+                  {
+                    if ($this->_called)
+                      return [];
+
+                    $this->_called = true;
+                    return [$xmen, $orphan, $iron_man];
+                  });
+
+    $this->onLoaderOfModel(Class_CodifAuteur::class);
+    $this->_prepareAuthor(1, 'LEExSTAN')
+         ->_prepareAuthor(2, 'KIRBYxJACK')
+         ->_prepareAuthor(3, 'LIEBERxLARRY')
+         ->_prepareAuthor(4, 'HECKxDON')
+      ;
+
+    $time_source = new TimeSourceForTest('2021-05-06 17:51:45');
+    Class_Cosmogramme_Integration_PhaseSerialArticlesIndex::setTimeSource($time_source);
+  }
+
+
+  protected function _prepareAuthor($id, $formes) {
+    $author = $this->fixture(Class_CodifAuteur::class,
+                             ['id' => $id,
+                              'formes' => $formes,
+                             ]);
+
+    Class_CodifAuteur::whenCalled('findFirstBy')
+      ->with(['where' => "MATCH(formes) AGAINST('" . $formes . "' IN BOOLEAN MODE)"])
+      ->answers($author);
+
+    return $this;
+  }
+
+
+  public function setUp() {
+    parent::setUp();
+
+    $this->_phase = $this->_buildPhase('SerialArticlesIndex')
+                         ->setMemoryCleaner(function() {})
+                         ->setPrinter($this->_printer)
+                         ->run();
+  }
+
+
+  /** @test */
+  public function logShouldContainsIndexationDesArticlesDePeriodiques() {
+    $this->assertContains('Indexation des articles de périodique', $this->_log_content);
+  }
+
+
+  /** @test */
+  public function logShouldContains1Orphan() {
+    $this->assertContains('Notices orphelines : 1', $this->_log_content);
+  }
+
+
+  /** @test */
+  public function issueFacetsShouldContainsXMenAuthorsFacets() {
+    $this->assertContains('A1 A2', $this->_issue->getFacettes(), $this->_log_content);
+  }
+
+
+  /** @test */
+  public function issueFacetsShouldContainsIronManAuthorsFacets() {
+    $this->assertContains('A3 A4', $this->_issue->getFacettes());
+  }
+
+
+  /** @test */
+  public function issueFacetsShouldContainsXMenSubjectsFacets() {
+    $this->assertContains('M1 M2 M3 M4', $this->_issue->getFacettes());
+  }
+
+
+  /** @test */
+  public function issueFacetsShouldContainsIronManSubjectsFacets() {
+    $this->assertContains('M5 M6 M7 M8', $this->_issue->getFacettes());
+  }
+
+
+  /** @test */
+  public function issueTitlesShouldContainsXMenAndIronManTerms() {
+    $this->assertContains('IRON MAN X00 MEN', $this->_issue->getTitres());
+  }
+
+
+  /** @test */
+  public function issueMatieresShouldContainsXMenAndIronManSubjectsTerms() {
+    $this->assertEquals('ARMURE ARMUR JAUNE JON ROUGE ROUJ BLING SLIPS SLIP CAPES KAP MOULANTS MOULAN COLLANTS KOLAN',
+                        $this->_issue->getMatieres());
+  }
+
+
+  /** @test */
+  public function issueAuteursShouldContainsXMenAndIronManAuthorsTerms() {
+    $this->assertEquals('LEE STAN LIEBER LIEB LARRY LARI HECK EK DON KIRBY KIRBI JACK JAK',
+                        $this->_issue->getAuteurs());
+  }
+
+
+  /** @test */
+  public function issueDateMajShouldBe2021_05_06_17_51_45() {
+    $this->assertEquals('2021-05-06 17:51:45', $this->_issue->getDateMaj());
+  }
+}
diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseTestCase.php b/tests/library/Class/Cosmogramme/Integration/PhaseTestCase.php
index ae29d9c6b05622452a1c0ecd612978d3f5f97449..36d4ca493c5d2bedc970bee95fac7a24d8f70c47 100644
--- a/tests/library/Class/Cosmogramme/Integration/PhaseTestCase.php
+++ b/tests/library/Class/Cosmogramme/Integration/PhaseTestCase.php
@@ -35,12 +35,16 @@ abstract class Class_Cosmogramme_Integration_PhaseTestCase extends ModelTestCase
 
     profil_donnees::clearCache();
 
-    $append_log = function($content) { $this->_log_content .= ' ' . $content; };
-    $this->_log = $this->mock()
-                       ->whenCalled('error')->willDo($append_log)
-                       ->whenCalled('success')->willDo($append_log)
-                       ->whenCalled('info')->willDo($append_log)
-                       ->whenCalled('log')->willDo($append_log);
+    $this->_log = $this->mock();
+    $append_log = function($content) {
+      $this->_log_content .= ' ' . $content;
+      return $this->_log;
+    };
+
+    $this->_log->whenCalled('error')->willDo($append_log)
+               ->whenCalled('success')->willDo($append_log)
+               ->whenCalled('info')->willDo($append_log)
+               ->whenCalled('log')->willDo($append_log);
 
     $this->_chrono = new Class_Cosmogramme_Integration_Chronometre();
     $this->_printer = $this->mock()
@@ -66,7 +70,7 @@ abstract class Class_Cosmogramme_Integration_PhaseTestCase extends ModelTestCase
 
 
   protected function _buildPhase($name) {
-    $class_name = 'Class_Cosmogramme_Integration_Phase'.ucfirst($name);
+    $class_name = 'Class_Cosmogramme_Integration_Phase' . ucfirst($name);
     return (new $class_name($this->_getPreviousPhase(),
                             $this->_log,
                             $this->_chrono))
diff --git a/tests/library/Class/Indexation/PseudoNoticeTest.php b/tests/library/Class/Indexation/PseudoNoticeTest.php
index 58310d3f88bf3e27462276b1bd72a82e610f8ee0..b5126db30103c4ca0a13eb2d9a60d25b92f7f6ad 100644
--- a/tests/library/Class/Indexation/PseudoNoticeTest.php
+++ b/tests/library/Class/Indexation/PseudoNoticeTest.php
@@ -830,7 +830,7 @@ class Class_Indexation_PseudoNoticeAlbumUpdateTest extends ModelTestCase {
 
   /** @test */
   public function recordShouldHaveBeenUpdated() {
-    $this->assertEquals('SHOULD CHOUL UPDATE UPDAT RECORD REKOR WITH OUI THIS TI NEW  TITLE TITL',
+    $this->assertEquals('SHOULD CHOUL UPDATE UPDAT RECORD REKOR WITH OUI THIS TI NEW TITLE TITL',
                         Class_Notice::find(15)->getTitres());
   }