diff --git a/library/Class/Import/Typo3.php b/library/Class/Import/Typo3.php
index 9f5c3a7a181784b7abaff9f02f5ff3927fc333e3..d7926a2fb371a64550b1f21dae8c0c3fba6743d4 100644
--- a/library/Class/Import/Typo3.php
+++ b/library/Class/Import/Typo3.php
@@ -38,7 +38,7 @@ class Class_Import_Typo3 {
     $unknown_koha_urls = [];
 
   public function __construct() {
-    $this->t3db = new Typo3DB();
+    $this->t3db = new Class_Import_Typo3_Db();
     $this->report = ['categories_created' => 0,
                      'domaine_created' => 0,
                      'categories_sites_created' => 0,
@@ -54,8 +54,8 @@ class Class_Import_Typo3 {
                      'sitotheque_errors' => 0];
 
     $this->errors = [];
-    $this->domaine_map = new DomaineMap();
-    $this->userMap = new UserMap();
+    $this->domaine_map = new Class_Import_Typo3_DomaineMap();
+    $this->userMap = new Class_Import_Typo3_UserMap();
     $this->createCustomField();
   }
 
@@ -187,23 +187,13 @@ class Class_Import_Typo3 {
 
 
   public function updateCategories($update_date) {
-    $this->news_categories_map = new ArticleCategoriesMap('Non classé', $this->domaine_map);
+    $this->news_categories_map = new Class_Import_Typo3_ArticleCategoriesMap('Non classé', $this->domaine_map);
+    $this->sites_categories_map = new Class_Import_Typo3_SiteCategoriesMap('Non classé', $this->domaine_map);
 
     $t3categories = $this->t3db->findAllNewsCatSince($update_date);
 
-    foreach ($t3categories as $t3category)  {
-      if ($category = ArticleCategoriesMap::getCategory($t3category['uid'])) {
-        $this->updateCategory($category,$t3category);
-        continue;
-      }
-
-      $this->news_categories_map->newCategory($t3category['title'],
-                                              $t3category['uid'],
-                                              $t3category['parent_category']);
-
-      $this->news_categories_map->fixParentCategory($t3category['uid'],
-                                                    $t3category['parent_category']);
-    }
+    $this->news_categories_map->build($t3categories);
+    $this->sites_categories_map->build($t3categories);
   }
 
 
@@ -217,9 +207,9 @@ class Class_Import_Typo3 {
 
     $this->reset_auto_increment();
 
-    $this->cal_categories_map= new CalendarCategoriesMap('Agenda', $this->domaine_map);
-    $this->news_categories_map = new ArticleCategoriesMap('Non classé', $this->domaine_map);
-    $this->sites_categories_map = new SiteCategoriesMap('Non classé', $this->domaine_map);
+    $this->cal_categories_map= new Class_Import_Typo3_CalendarCategoriesMap('Agenda', $this->domaine_map);
+    $this->news_categories_map = new Class_Import_Typo3_ArticleCategoriesMap('Non classé', $this->domaine_map);
+    $this->sites_categories_map = new Class_Import_Typo3_SiteCategoriesMap('Non classé', $this->domaine_map);
 
     $t3categories = $this->t3db->findAllNewsCat();
     $this->news_categories_map->build($t3categories);
@@ -239,7 +229,7 @@ class Class_Import_Typo3 {
 
 
   public function updateSites($update_date) {
-    $this->sites_categories_map = new SiteCategoriesMap('Non classé', $this->domaine_map);
+    $this->sites_categories_map = new Class_Import_Typo3_SiteCategoriesMap('Non classé', $this->domaine_map);
     $t3news = $this->t3db->findAllSitesSince($update_date);
 
     foreach($t3news as $new) {
@@ -260,7 +250,7 @@ class Class_Import_Typo3 {
     Class_Sitotheque::deleteBy([]);
     Class_SitothequeCategorie::deleteBy([]);
 
-    $this->sites_categories_map = new SiteCategoriesMap('Non classé', $this->domaine_map);
+    $this->sites_categories_map = new Class_Import_Typo3_SiteCategoriesMap('Non classé', $this->domaine_map);
     $t3categories = $this->t3db->findAllNewsCat();
     $this->sites_categories_map->build($t3categories);
 
@@ -525,7 +515,7 @@ class Class_Import_Typo3 {
     $t3catIds = $this->t3db->findAllForeignUidForNewsCat($new['uid']);
 
     foreach ($t3catIds as $t3catId) {
-      $id_cat = ArticleCategoriesMap::getCategoryOrDefaultCategory($t3catId['uid_foreign'])->getId();
+      $id_cat = Class_Import_Typo3_ArticleCategoriesMap::getCategoryOrDefaultCategory($t3catId['uid_foreign'])->getId();
     }
 
     $block = function() use ($new, $id_cat){
@@ -922,429 +912,4 @@ class Class_Import_Typo3 {
             'description' => $new['short']];
   }
 }
-
-
-
-class UserMap {
-  protected $map = [];
-
-  public function init() {
-    $where = 'ROLE_LEVEL < ' . ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL; // exclude ADMIN.
-    $where .= ' AND ROLE_LEVEL <> ' . ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB; // exclude SIGB members.
-    Class_Users::deleteBy(['where' => $where]);
-  }
-
-
-  public function updateUser($data, $user) {
-    $user->setNom($data['realName'])
-         ->setMail($data['email'])
-         ->setPassword('achanger');
-  }
-
-
-  public function newUser($data) {
-    $logs = Class_Import_Typo3_Logs::getInstance();
-    $logs->incrementT3Users();
-
-    $user = $this->_findOrCreate($data['username']);
-    $updated = !$user->isNew();
-    $this->updateUser($data, $user);
-
-    ($data['admin'] == '1') ?
-      $user->beAdminPortail() :
-      $user->changeRoleTo(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
-
-    if (!$user->save()) {
-      $logs->incrementRejected($user, $data);
-      return;
-    }
-
-    $updated
-      ? $logs->incrementUpdated()
-      : $logs->incrementSaved();
-
-    $this->map[$data['uid']] = $user->getId();
-  }
-
-
-  protected function _findOrCreate($login) {
-    return ($user = Class_Users::findFirstBy(['login' => $login])) ?
-      $user : Class_Users::newInstance(['login' => $login]);
-  }
-
-
-  public function find($uid) {
-    return isset($this->map[$uid]) ? $this->map[$uid] : 0;
-  }
-}
-
-
-
-
-abstract class CategoriesMap {
-
-  const UID_TYPO3_CF = 'uid_typo3';
-
-  protected
-    $map = [],
-    $default_cat,
-    $domaine_map;
-
-  public function __construct($default_cat_title, $domaine_map) {
-    $this->domaine_map = $domaine_map;
-    $this->default_cat = $this->_buildNewCategory($default_cat_title);
-    $this->default_cat->assertSave();
-  }
-
-
-  public function build($t3categories) {
-    foreach($t3categories as $t3cat)
-      $this->newCategory($t3cat['title'], $t3cat['uid'], $t3cat['parent_category']);
-
-    foreach($t3categories as $t3cat)
-      $this->fixParent($t3cat['uid'], $t3cat['parent_category']);
-
-    $this->createDomainMap();
-  }
-
-
-  public function getParentCatId($t3id) {
-    if (isset($this->map[$t3id])) {
-      $cat = $this->map[$t3id];
-      return $cat->getId();
-    }
-
-    return  0;
-  }
-
-
-  public function newCategory($title, $t3uid, $t3pid) {
-    $category = $this->_buildNewCategory($title, $this->getParentCatId($t3pid));
-    $category->setCustomField(Class_Import_Typo3::UID_TYPO3_CF,$t3uid);
-    if(!$category->saveWithCustomFields())
-      return $this->addError($category, $title, $t3uid, $t3pid);
-
-    $this->incrementSaved();
-    return $this->map[$t3uid] = $category;
-  }
-
-
-  public function fixParent($t3uid, $t3pid) {
-    $category = $this->find($t3uid);
-    if (!$category->hasParentCategorie() &&
-        $category->getId() !== $this->default_cat->getId() &&
-        isset($this->map[$t3pid])) {
-      $category->setParentCategorie($this->find($t3pid))
-               ->save();
-    }
-  }
-
-
-  public static function getOrCreateDefaultCategory() {
-    if ($category = Class_ArticleCategorie::findFirstBy(['libelle' => 'Non classé']))
-      return $category;
-
-    $cat = Class_ArticleCategorie::newInstance(['libelle' => 'Non classé',
-                                                'id_cat_mere' => 0]);
-    $cat->save();
-    return $cat;
-
-  }
-
-
-  public static function getCategory($uid) {
-    return Class_ArticleCategorie::findFirstByCustomFieldValue(Class_Import_Typo3::UID_TYPO3_CF, $uid);
-  }
-
-
-  public static function getCategoryOrDefaultCategory($uid) {
-    return ($category = self::getCategory($uid)) ?
-      $category : self::getOrCreateDefaultCategory();
-  }
-
-
-  public function fixParentCategory($t3uid, $t3pid) {
-    if(!$category = self::getCategory($t3uid))
-      return;
-
-    if ($category->getId() == $this->default_cat->getId())
-      return;
-
-    $category->setParentCategorie(self::getCategory($t3pid))
-             ->save();
-  }
-
-
-  public function createDomainMap() {
-    foreach($this->map as $category)
-      $this->domaine_map->findOrCreateDomaine($category);
-  }
-
-
-  abstract protected function addError($category, $title, $t3uid, $t3pid);
-
-  abstract protected function incrementSaved();
-
-  protected function findByUidTypo3($t3id) {
-    return null;
-  }
-
-  public function find($t3id) {
-    if (isset($this->map[$t3id]))
-      return $this->map[$t3id];
-
-    if ($category = $this->findByUidTypo3($t3id)) {
-      $this->map[$t3id] = $category;
-      return $category;
-    }
-
-    return $this->default_cat;
-  }
-
-
-  public function setDomainsFor($model, $t3_domain_ids) {
-    $domains = [];
-    foreach ($t3_domain_ids as $t3_domain) {
-      $category = $this->find($t3_domain['uid_foreign']);
-      $domains[] = $this->domaine_map
-        ->findOrCreateDomaine($category,$t3_domain['uid_foreign']);
-    }
-
-    if (isset($category))
-      $model->setCategorie($category);
-
-    $model->setDomaines($domains)->save();
-  }
-}
-
-
-
-class DomaineMap {
-  protected $map = [];
-
-  public function findOrCreateDomaine($category, $uid=0) {
-    if (!$category)
-      return null;
-
-    $path = $category->getPath();
-
-    if (isset($this->map[$path]))
-      return $this->map[$path];
-
-    $parent_domaine = $this->findOrCreateDomaine($category->getParentCategorie());
-
-    $catalogue = Class_Catalogue::newInstance(['libelle' => $category->getLibelle(),
-                                               'parent_id' => $parent_domaine ? $parent_domaine->getId() : 0]);
-
-    if (!$uid)
-      $catalogue->setCustomField(Class_Import_Typo3::UID_TYPO3_CF, $uid);
-
-    if (!$catalogue->saveWithCustomFields()) {
-      Class_Import_Typo3_Logs::getInstance()->incrementDomainsRejected($catalogue);
-      return;
-    }
-
-    Class_Import_Typo3_Logs::getInstance()->incrementDomainsSaved();
-    return $this->map[$path] = $catalogue;
-  }
-}
-
-
-class ArticleCategoriesMap extends CategoriesMap {
-  protected function _buildNewCategory($libelle, $parent_id=0) {
-    return Class_ArticleCategorie::newInstance(['libelle' => $libelle,
-                                                'id_cat_mere' => $parent_id]);
-  }
-
-
-  protected function addError($category, $title, $t3uid, $t3pid) {
-    return Class_Import_Typo3_Logs::getInstance()
-      ->incrementArticleCategoriesRejected($category, $title, $t3uid, $t3pid);
-  }
-
-
-  protected function incrementSaved() {
-    Class_Import_Typo3_Logs::getInstance()->incrementArticleCategoriesSaved();
-  }
-
-
-  protected function findByUidTypo3 ($t3id) {
-    return Class_ArticleCategorie::findFirstByCustomFieldValue(self::UID_TYPO3_CF, $t3id);
-  }
-}
-
-
-class SiteCategoriesMap extends CategoriesMap {
-  protected function _buildNewCategory($libelle, $parent_id=0) {
-    return Class_SitothequeCategorie::newInstance(['libelle' => $libelle,
-                                                   'id_cat_mere' => $parent_id]);
-  }
-
-
-  protected function addError($category, $title, $t3uid, $t3pid) {
-    return Class_Import_Typo3_Logs::getInstance()
-      ->incrementSitoCategoriesRejected($category, $title, $t3uid, $t3pid);
-  }
-
-
-  protected function incrementSaved() {
-    Class_Import_Typo3_Logs::getInstance()->incrementSitoCategoriesSaved();
-  }
-
-
-  public function findOrCreateByPath($path) {
-    if ($path == Trait_TreeNode::$PATH_SEPARATOR)
-      return null;
-
-    $parts = array_values(array_filter(explode(Trait_TreeNode::$PATH_SEPARATOR, $path)));
-
-    $category = null;
-    foreach($parts as $part)
-      $category = $this->_findOrCreateUnder($part, $category);
-
-    return $category;
-  }
-
-
-  protected function _findOrCreateUnder($label, $parent) {
-    $attribs = ['libelle' => $label,
-                'id_cat_mere' => $parent ? $parent->getId() : 0];
-
-    if (!$category = Class_SitothequeCategorie::findFirstBy($attribs)) {
-      $category = Class_SitothequeCategorie::newInstance($attribs);
-      $category->save();
-    }
-
-    return $category;
-  }
-
-
-  protected function findByUidTypo3($t3id) {
-    return Class_SitothequeCategorie::findFirstByCustomFieldValue(self::UID_TYPO3_CF, $t3id);
-  }
-}
-
-
-
-
-class CalendarCategoriesMap  extends ArticleCategoriesMap {
-  public function getParentCatId($t3id) {
-    return $this->find($t3id)->getId();
-  }
-}
-
-
-
-class Typo3DB {
-  protected
-    $t3db,
-    $pages_titles;
-
-  public function __construct() {
-    $this->t3db = new Class_Systeme_Sql('','','','');
-    $this
-      ->t3db
-      ->setAdapter(Zend_Db::factory(
-                                    'mysqli',
-                                    ['host' => 'localhost',
-                                     'username' => 'root',
-                                     'password' => 'root',
-                                     'dbname' =>  'miop_typo3']));
-  }
-
-
-  public function findPageTitle($uid) {
-    if (isset($this->pages_titles[$uid]))
-      return $this->pages_titles[$uid];
-
-    $title = ($row = $this->t3db->fetchEnreg('select title from pages where uid=' . $uid)) ?
-      $row['title'] : '';
-
-    return $this->pages_titles[$uid] = $title;
-  }
-
-
-  public function findAllPagesWithPid($pid) {
-    return $this->t3db->fetchAll('select * from pages where pid='.$pid);
-  }
-
-
-  public function findAllUsers() {
-    return $this->t3db->fetchAll('select * from be_users where uid > 1');
-  }
-
-
-  public function findAllNewsCat() {
-    return $this->t3db->fetchAll('select * from tt_news_cat where deleted=0 order by uid ASC');
-  }
-
-
-  public function findAllNewsCatSince($update_date) {
-    return $this->t3db->fetchAll('select * from tt_news_cat where deleted=0 and tstamp >='.$update_date.' order by uid ASC');
-  }
-
-
-  public function findAllEventCat() {
-    return $this->t3db->fetchAll("select * from tx_cal_category where deleted=0 order by uid");
-  }
-
-
-  public function findAllEventCatSince($update_date) {
-    return $this->t3db->fetchAll("select * from tx_cal_category where deleted=0 and tstamp >=".$update_date." order by uid");
-  }
-
-
-  public function findAllSitesSince($update_date) {
-    return $this->t3db->fetchAll("select * from tt_news where deleted=0 and t3ver_label  not like 'DELETED!' and hidden=0 and ext_url not like '%koha.mediathequeouestprovence.fr%'  and ext_url>'' and tstamp >= ".$update_date." order by uid ASC");
-  }
-
-
-  public function findAllSites() {
-    return $this->t3db->fetchAll("select * from tt_news where deleted=0 and t3ver_label  not like 'DELETED!' and hidden=0 and ext_url not like '%koha.mediathequeouestprovence.fr%'  and ext_url>'' order by uid ASC");
-  }
-
-
-  public function findAllExternalSites() {
-    return $this->t3db->fetchAll("select * from tt_news where deleted=0 and t3ver_label  not like 'DELETED!' and hidden=0 and image>'' and ext_url not like '%koha.mediathequeouestprovence.fr%' and  ext_url>'' order by uid ASC");
-  }
-
-
-  public function findAllArticlesSince($last_import_date) {
-    return $this->t3db->fetchAll("select * from tt_news where hidden=0 and ext_url='' and tstamp >= ".$last_import_date."  order by uid ASC");
-  }
-
-
-  public function findAllArticles() {
-    return $this->t3db->fetchAll("select * from tt_news where deleted=0 and hidden=0 and ext_url='' order by uid ASC");
-  }
-
-
-  public function findAllForeignUidForNewsCat($uid) {
-    return $this->t3db->fetchAll("select distinct uid_foreign from tt_news_cat_mm where uid_local=". $uid ." order by sorting");
-  }
-
-
-  public function findAllForeignUidForCalendarEventCategory($uid) {
-    return $this->t3db->fetchAll("select distinct uid_foreign from tx_cal_event_category_mm where uid_local=" . $uid . " order by sorting");
-  }
-
-
-  public function findAllCalendarEvents() {
-    return $this->t3db->fetchAll("select * from tx_cal_event where deleted=0 and hidden=0 order by uid ASC");
-  }
-
-
-  public function findAllContents($page_id=false) {
-    $pid_sql='';
-    if ($page_id)
-      $pid_sql='and pid='.$page_id;
-
-    return $this->t3db->fetchAll("select * from tt_content where deleted=0 and hidden=0 and header>'' and bodytext>'' and  (ctype='text' or ctype='textpic') ".$pid_sql." order by uid ASC");
-  }
-
-
-  public function findAllContentsSince($update_date) {
-    return $this->t3db->fetchAll("select * from tt_content where deleted=0 and tstamp>=".$update_date." and hidden=0 and header>'' and bodytext>'' and  (ctype='text' or ctype='textpic') order by uid ASC");
-  }
-}
 ?>
\ No newline at end of file
diff --git a/library/Class/Import/Typo3/ArticleCategoriesMap.php b/library/Class/Import/Typo3/ArticleCategoriesMap.php
new file mode 100644
index 0000000000000000000000000000000000000000..aa2322a049e0440c67c9c11ee5cb1750871f80a0
--- /dev/null
+++ b/library/Class/Import/Typo3/ArticleCategoriesMap.php
@@ -0,0 +1,49 @@
+<?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_Import_Typo3_ArticleCategoriesMap extends Class_Import_Typo3_CategoriesMap {
+  protected function _buildNewCategory($libelle, $parent_id=0) {
+    return Class_ArticleCategorie::newInstance(['libelle' => $libelle,
+                                                'id_cat_mere' => $parent_id]);
+  }
+
+
+  public static function getCategory($uid) {
+    return Class_ArticleCategorie::findFirstByCustomFieldValue(Class_Import_Typo3::UID_TYPO3_CF, $uid);
+  }
+
+
+  protected function addError($category, $title, $t3uid, $t3pid) {
+    return Class_Import_Typo3_Logs::getInstance()
+      ->incrementArticleCategoriesRejected($category, $title, $t3uid, $t3pid);
+  }
+
+
+  protected function incrementSaved() {
+    Class_Import_Typo3_Logs::getInstance()->incrementArticleCategoriesSaved();
+  }
+
+
+  protected function findByUidTypo3 ($t3id) {
+    return Class_ArticleCategorie::findFirstByCustomFieldValue(self::UID_TYPO3_CF, $t3id);
+  }
+}
+?>
diff --git a/library/Class/Import/Typo3/CalendarCategoriesMap.php b/library/Class/Import/Typo3/CalendarCategoriesMap.php
new file mode 100644
index 0000000000000000000000000000000000000000..c6b59f191070caf05f0a2f4c0f22f291b91f352a
--- /dev/null
+++ b/library/Class/Import/Typo3/CalendarCategoriesMap.php
@@ -0,0 +1,26 @@
+<?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_Import_Typo3_CalendarCategoriesMap  extends Class_Import_Typo3_ArticleCategoriesMap {
+  public function getParentCatId($t3id) {
+    return $this->find($t3id)->getId();
+  }
+}
+?>
diff --git a/library/Class/Import/Typo3/CategoriesMap.php b/library/Class/Import/Typo3/CategoriesMap.php
new file mode 100644
index 0000000000000000000000000000000000000000..b3bbdb29cb634053279e4ade855ce9953faf1e5d
--- /dev/null
+++ b/library/Class/Import/Typo3/CategoriesMap.php
@@ -0,0 +1,174 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+abstract class Class_Import_Typo3_CategoriesMap {
+
+  const UID_TYPO3_CF = 'uid_typo3';
+
+  protected
+    $map = [],
+    $default_cat,
+    $domaine_map;
+
+  public function __construct($default_cat_title, $domaine_map) {
+    $this->domaine_map = $domaine_map;
+    $this->default_cat = $this->_buildNewCategory($default_cat_title);
+    $this->default_cat->assertSave();
+  }
+
+
+  public function build($t3categories) {
+    foreach($t3categories as $t3cat) {
+      if ($category = $this->getCategory($t3cat['uid'])) {
+        $this->updateCategory($t3cat, $category);
+        continue;
+      }
+
+      $this->newCategory($t3cat['title'], $t3cat['uid'], $t3cat['parent_category']);
+    }
+
+    foreach ($t3categories as $t3cat)
+      $this->fixParent($t3cat['uid'], $t3cat['parent_category']);
+
+
+    $this->createDomainMap();
+  }
+
+
+  public function getParentCatId($t3id) {
+    if (isset($this->map[$t3id])) {
+      $cat = $this->map[$t3id];
+      return $cat->getId();
+    }
+
+    if ($category = $this->findByUidTypo3($t3id)) {
+      $this->map[$t3id] = $category;
+      return $category->getId();
+    }
+
+    return  0;
+  }
+
+
+  public function newCategory($title, $t3uid, $t3pid) {
+    $category = $this->_buildNewCategory($title, $this->getParentCatId($t3pid));
+    $category->setCustomField(Class_Import_Typo3::UID_TYPO3_CF,$t3uid);
+    if(!$category->saveWithCustomFields())
+      return $this->addError($category, $title, $t3uid, $t3pid);
+
+    $this->incrementSaved();
+    return $this->map[$t3uid] = $category;
+  }
+
+
+  public function updateCategory($t3cat, $category) {
+    $category->updateAttributes(['libelle' => $t3cat['title'],
+                                 'id_cat_mere' => $this->getParentCatId($t3cat['parent_category'])]);
+
+    if(!$category->save())
+      return $this->addError($category, $title, $t3cat['uid'], $t3cat['parent_category']);
+
+    return $this->map[$t3cat['uid']] = $category;
+  }
+
+
+  public function fixParent($t3uid, $t3pid) {
+    $category = $this->find($t3uid);
+    if (!$category->hasParentCategorie() &&
+        $category->getId() !== $this->default_cat->getId() &&
+        isset($this->map[$t3pid])) {
+      $category->setParentCategorie($this->find($t3pid))
+               ->save();
+    }
+  }
+
+
+  public static function getOrCreateDefaultCategory() {
+    if ($category = Class_ArticleCategorie::findFirstBy(['libelle' => 'Non classé']))
+      return $category;
+
+    $cat = Class_ArticleCategorie::newInstance(['libelle' => 'Non classé',
+                                                'id_cat_mere' => 0]);
+    $cat->save();
+    return $cat;
+
+  }
+
+
+  public static function getCategoryOrDefaultCategory($uid) {
+    return ($category = static::getCategory($uid)) ?
+      $category : static::getOrCreateDefaultCategory();
+  }
+
+
+  public function fixParentCategory($t3uid, $t3pid) {
+    if(!$category = static::getCategory($t3uid))
+      return;
+
+    if ($category->getId() == $this->default_cat->getId())
+      return;
+
+    $category->setParentCategorie(static::getCategory($t3pid))
+             ->save();
+  }
+
+
+  public function createDomainMap() {
+    foreach($this->map as $category)
+      $this->domaine_map->findOrCreateDomaine($category);
+  }
+
+
+  abstract protected function addError($category, $title, $t3uid, $t3pid);
+
+  abstract protected function incrementSaved();
+
+  protected function findByUidTypo3($t3id) {
+    return null;
+  }
+
+  public function find($t3id) {
+    if (isset($this->map[$t3id]))
+      return $this->map[$t3id];
+
+    if ($category = $this->findByUidTypo3($t3id)) {
+      $this->map[$t3id] = $category;
+      return $category;
+    }
+
+    return $this->default_cat;
+  }
+
+
+  public function setDomainsFor($model, $t3_domain_ids) {
+    $domains = [];
+    foreach ($t3_domain_ids as $t3_domain) {
+      $category = $this->find($t3_domain['uid_foreign']);
+      $domains[] = $this->domaine_map
+        ->findOrCreateDomaine($category,$t3_domain['uid_foreign']);
+    }
+
+    if (isset($category))
+      $model->setCategorie($category);
+
+    $model->setDomaines($domains)->save();
+  }
+}
+?>
diff --git a/library/Class/Import/Typo3/Db.php b/library/Class/Import/Typo3/Db.php
new file mode 100644
index 0000000000000000000000000000000000000000..8beb52a4a57d9128ce7b8a19962a72f4b966ef39
--- /dev/null
+++ b/library/Class/Import/Typo3/Db.php
@@ -0,0 +1,132 @@
+<?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_Import_Typo3_DB {
+  protected
+    $t3db,
+    $pages_titles;
+
+  public function __construct() {
+    $this->t3db = new Class_Systeme_Sql('','','','');
+    $this
+      ->t3db
+      ->setAdapter(Zend_Db::factory(
+                                    'mysqli',
+                                    ['host' => 'localhost',
+                                     'username' => 'root',
+                                     'password' => 'root',
+                                     'dbname' =>  'miop_typo3']));
+  }
+
+
+  public function findPageTitle($uid) {
+    if (isset($this->pages_titles[$uid]))
+      return $this->pages_titles[$uid];
+
+    $title = ($row = $this->t3db->fetchEnreg('select title from pages where uid=' . $uid)) ?
+      $row['title'] : '';
+
+    return $this->pages_titles[$uid] = $title;
+  }
+
+
+  public function findAllPagesWithPid($pid) {
+    return $this->t3db->fetchAll('select * from pages where pid='.$pid);
+  }
+
+
+  public function findAllUsers() {
+    return $this->t3db->fetchAll('select * from be_users where uid > 1');
+  }
+
+
+  public function findAllNewsCat() {
+    return $this->t3db->fetchAll('select * from tt_news_cat where deleted=0 order by uid ASC');
+  }
+
+
+  public function findAllNewsCatSince($update_date) {
+    return $this->t3db->fetchAll('select * from tt_news_cat where deleted=0 and tstamp >='.$update_date.' order by uid ASC');
+  }
+
+
+  public function findAllEventCat() {
+    return $this->t3db->fetchAll("select * from tx_cal_category where deleted=0 order by uid");
+  }
+
+
+  public function findAllEventCatSince($update_date) {
+    return $this->t3db->fetchAll("select * from tx_cal_category where deleted=0 and tstamp >=".$update_date." order by uid");
+  }
+
+
+  public function findAllSitesSince($update_date) {
+    return $this->t3db->fetchAll("select * from tt_news where deleted=0 and t3ver_label  not like 'DELETED!' and hidden=0 and ext_url not like '%koha.mediathequeouestprovence.fr%'  and ext_url>'' and tstamp >= ".$update_date." order by uid ASC");
+  }
+
+
+  public function findAllSites() {
+    return $this->t3db->fetchAll("select * from tt_news where deleted=0 and t3ver_label  not like 'DELETED!' and hidden=0 and ext_url not like '%koha.mediathequeouestprovence.fr%'  and ext_url>'' order by uid ASC");
+  }
+
+
+  public function findAllExternalSites() {
+    return $this->t3db->fetchAll("select * from tt_news where deleted=0 and t3ver_label  not like 'DELETED!' and hidden=0 and image>'' and ext_url not like '%koha.mediathequeouestprovence.fr%' and  ext_url>'' order by uid ASC");
+  }
+
+
+  public function findAllArticlesSince($last_import_date) {
+    return $this->t3db->fetchAll("select * from tt_news where hidden=0 and ext_url='' and tstamp >= ".$last_import_date."  order by uid ASC");
+  }
+
+
+  public function findAllArticles() {
+    return $this->t3db->fetchAll("select * from tt_news where deleted=0 and hidden=0 and ext_url='' order by uid ASC");
+  }
+
+
+  public function findAllForeignUidForNewsCat($uid) {
+    return $this->t3db->fetchAll("select distinct uid_foreign from tt_news_cat_mm where uid_local=". $uid ." order by sorting");
+  }
+
+
+  public function findAllForeignUidForCalendarEventCategory($uid) {
+    return $this->t3db->fetchAll("select distinct uid_foreign from tx_cal_event_category_mm where uid_local=" . $uid . " order by sorting");
+  }
+
+
+  public function findAllCalendarEvents() {
+    return $this->t3db->fetchAll("select * from tx_cal_event where deleted=0 and hidden=0 order by uid ASC");
+  }
+
+
+  public function findAllContents($page_id=false) {
+    $pid_sql='';
+    if ($page_id)
+      $pid_sql='and pid='.$page_id;
+
+    return $this->t3db->fetchAll("select * from tt_content where deleted=0 and hidden=0 and header>'' and bodytext>'' and  (ctype='text' or ctype='textpic') ".$pid_sql." order by uid ASC");
+  }
+
+
+  public function findAllContentsSince($update_date) {
+    return $this->t3db->fetchAll("select * from tt_content where deleted=0 and tstamp>=".$update_date." and hidden=0 and header>'' and bodytext>'' and  (ctype='text' or ctype='textpic') order by uid ASC");
+  }
+}
diff --git a/library/Class/Import/Typo3/DomaineMap.php b/library/Class/Import/Typo3/DomaineMap.php
new file mode 100644
index 0000000000000000000000000000000000000000..3914484c7f81bd73658148281e8778327df35174
--- /dev/null
+++ b/library/Class/Import/Typo3/DomaineMap.php
@@ -0,0 +1,50 @@
+<?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_Import_Typo3_DomaineMap {
+  protected $map = [];
+
+  public function findOrCreateDomaine($category, $uid=0) {
+    if (!$category)
+      return null;
+
+    $path = $category->getPath();
+
+    if (isset($this->map[$path]))
+      return $this->map[$path];
+
+    $parent_domaine = $this->findOrCreateDomaine($category->getParentCategorie());
+
+    $catalogue = Class_Catalogue::newInstance(['libelle' => $category->getLibelle(),
+                                               'parent_id' => $parent_domaine ? $parent_domaine->getId() : 0]);
+
+    if (!$uid)
+      $catalogue->setCustomField(Class_Import_Typo3::UID_TYPO3_CF, $uid);
+
+    if (!$catalogue->saveWithCustomFields()) {
+      Class_Import_Typo3_Logs::getInstance()->incrementDomainsRejected($catalogue);
+      return;
+    }
+
+    Class_Import_Typo3_Logs::getInstance()->incrementDomainsSaved();
+    return $this->map[$path] = $catalogue;
+  }
+}
+?>
diff --git a/library/Class/Import/Typo3/SiteCategoriesMap.php b/library/Class/Import/Typo3/SiteCategoriesMap.php
new file mode 100644
index 0000000000000000000000000000000000000000..863f2cc93b66966442b66ec4bcf7ca1fcce0cdcb
--- /dev/null
+++ b/library/Class/Import/Typo3/SiteCategoriesMap.php
@@ -0,0 +1,77 @@
+<?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_Import_Typo3_SiteCategoriesMap extends Class_Import_Typo3_CategoriesMap {
+  protected function _buildNewCategory($libelle, $parent_id=0) {
+    return Class_SitothequeCategorie::newInstance(['libelle' => $libelle,
+                                                   'id_cat_mere' => $parent_id]);
+  }
+
+
+  public static function getCategory($uid) {
+    return Class_SitothequeCategorie::findFirstByCustomFieldValue(Class_Import_Typo3::UID_TYPO3_CF, $uid);
+  }
+
+
+
+
+  protected function addError($category, $title, $t3uid, $t3pid) {
+    return Class_Import_Typo3_Logs::getInstance()
+      ->incrementSitoCategoriesRejected($category, $title, $t3uid, $t3pid);
+  }
+
+
+  protected function incrementSaved() {
+    Class_Import_Typo3_Logs::getInstance()->incrementSitoCategoriesSaved();
+  }
+
+
+  public function findOrCreateByPath($path) {
+    if ($path == Trait_TreeNode::$PATH_SEPARATOR)
+      return null;
+
+    $parts = array_values(array_filter(explode(Trait_TreeNode::$PATH_SEPARATOR, $path)));
+
+    $category = null;
+    foreach($parts as $part)
+      $category = $this->_findOrCreateUnder($part, $category);
+
+    return $category;
+  }
+
+
+  protected function _findOrCreateUnder($label, $parent) {
+    $attribs = ['libelle' => $label,
+                'id_cat_mere' => $parent ? $parent->getId() : 0];
+
+    if (!$category = Class_SitothequeCategorie::findFirstBy($attribs)) {
+      $category = Class_SitothequeCategorie::newInstance($attribs);
+      $category->save();
+    }
+
+    return $category;
+  }
+
+
+  protected function findByUidTypo3($t3id) {
+    return Class_SitothequeCategorie::findFirstByCustomFieldValue(self::UID_TYPO3_CF, $t3id);
+  }
+}
+?>
diff --git a/library/Class/Import/Typo3/UserMap.php b/library/Class/Import/Typo3/UserMap.php
new file mode 100644
index 0000000000000000000000000000000000000000..caffeca28b3af970d07127191c5eb56c30f45449
--- /dev/null
+++ b/library/Class/Import/Typo3/UserMap.php
@@ -0,0 +1,73 @@
+<?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_Import_Typo3_UserMap {
+  protected $map = [];
+
+  public function init() {
+    $where = 'ROLE_LEVEL < ' . ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL; // exclude ADMIN.
+    $where .= ' AND ROLE_LEVEL <> ' . ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB; // exclude SIGB members.
+    Class_Users::deleteBy(['where' => $where]);
+  }
+
+
+  public function updateUser($data, $user) {
+    $user->setNom($data['realName'])
+         ->setMail($data['email'])
+         ->setPassword('achanger');
+  }
+
+
+  public function newUser($data) {
+    $logs = Class_Import_Typo3_Logs::getInstance();
+    $logs->incrementT3Users();
+
+    $user = $this->_findOrCreate($data['username']);
+    $updated = !$user->isNew();
+    $this->updateUser($data, $user);
+
+    ($data['admin'] == '1') ?
+      $user->beAdminPortail() :
+      $user->changeRoleTo(ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL);
+
+    if (!$user->save()) {
+      $logs->incrementRejected($user, $data);
+      return;
+    }
+
+    $updated
+      ? $logs->incrementUpdated()
+      : $logs->incrementSaved();
+
+    $this->map[$data['uid']] = $user->getId();
+  }
+
+
+  protected function _findOrCreate($login) {
+    return ($user = Class_Users::findFirstBy(['login' => $login])) ?
+      $user : Class_Users::newInstance(['login' => $login]);
+  }
+
+
+  public function find($uid) {
+    return isset($this->map[$uid]) ? $this->map[$uid] : 0;
+  }
+}
+?>
diff --git a/tests/library/Class/Import/Typo3Test.php b/tests/library/Class/Import/Typo3Test.php
index b9c658e3fd8b25a428dbd4f2064c07015a122267..4a86047ee9ef85bed50bd068274432c693845959 100644
--- a/tests/library/Class/Import/Typo3Test.php
+++ b/tests/library/Class/Import/Typo3Test.php
@@ -753,6 +753,11 @@ class Import_Typo3UpdateArticleTest extends Import_Typo3TestCase {
 
   }
 
+  /** @test */
+  public function updateCategoriesShouldAddSitoCategoryJeux() {
+    $this->assertNotNull(Class_SitothequeCategorie::findFirstBy(['libelle' => 'Jeux']));
+  }
+
   /** @test */
   public function articleShouldBeModified() {
     $this->assertEquals(14474, Class_Article::findFirstBy(['titre' => 'Tous à bord du bateau pirate'])->getCustomField('uid_typo3'));