Dans ce tutoriel, nous allons aborder la synchronisation de données avec iTop et nous allons voir comment l’adapter à un besoin spécifique grâce aux collecteurs de données.

Nous utiliserons les API en libre accès mises à disposition sur le site https://api.gouv.fr/ afin de synchroniser les établissements de l’éducation nationale sur notre serveur iTop.
Vous pourrez par la suite ajouter d’autres données disponibles dans d’autres API du site.

Ce site référence les API du service public, mises à la disposition des collectivités, des ministères et des entreprises pour construire des services informatiques au service de tous.

api.gouv.fr

⏱️Durée approximative du tutoriel: 4 heures

Les étapes clés de ce tutoriel

1/ La structuration des données
2/ La création d’une extension pour iTop
3/ La création d’un collecteur pour iTop
4/ L’industrialisation de la solution
5/ Exercice
6/ Quizz

Prérequis

Un serveur iTop communautaire de version 2.7 ou supérieure installé en local ou sur une machine distante de votre réseau avec les droits utilisateurs pour apporter des modifications à l’installation.
Un environnement d’exécution PHP compatible avec la version d’iTop et quelques connaissances en PHP.
Un éditeur de texte Notepad++ ou autre.

Principe de synchronisation avec iTop

Schéma de principe

Le rôle du collecteur est de convertir les données externes au format CSV, de mettre à jour les réplicas avec ces données et enfin de synchroniser ces derniers avec les données d’iTop.
Une couche d’abstraction s’occupe de la phase d’importation et de synchronisation pour nous.


Pour notre collecteur spécifique REST, nous devons simplement extraire les données de l’API et les convertir en CSV.

Les étapes du tutoriel

1/ La structuration des données

Nous souhaitons synchroniser la liste des établissements de l’éducation nationale Française avec notre iTop. Les données seront en lecture seule côté iTop.
Nous utiliserons l’API annuaire éducation: https://api.gouv.fr/les-api/api-annuaire-education.

L’analyse

La première étape consiste à analyser l’API et à identifier les données que nous souhaitons remonter sur iTop.
En allant sur la page de présentation de l’API, nous pouvons découvrir les principales données disponibles.

Aperçu des données fournies par l’API

La sélection des données à synchroniser

Nous choisissons les informations des établissements suivantes:

· L’identifiant unique (UAI)
· Le nom
· L’adresse postale
· Le type d’établissement
· L’information public / privé
· Le code académie
· Le nombre d’élèves
· La présence d’un service de restauration
· La date d’ouverture

Plusieurs types de données (texte, nombre, date, énumération et booléen) seront ainsi synchronisés.

La source de données

La requête de l’API que nous utiliserons est la suivante:

GET /catalog/datasets/fr-en-annuaire-education/records

Nous utiliserons les paramètres select, limit et offset afin de ne sélectionner que les données qui nous intéresse et nous pourrons ainsi, parcourir l’ensemble des enregistrements en plusieurs itérations. Il est en effet impossible de sélectionner l’ensemble des établissements, la limite du nombre de résultats fixée par l’API étant de 100 établissements par requête.

Vous pouvez effectuer quelques tests pour prendre en main l’API ici: https://api.gouv.fr/documentation/api-annuaire-education.

Page de test de l’API

2/ La création d’une extension pour iTop

Nous allons créer une extension pour nous permettre de customiser le modèle de données d’iTop et ainsi nous permettre de collecter des données de type établissement d’éducation. Nous étendrons la classe localisation et ajouterons les informations spécifiques aux établissements de l’éducation nationale. Nous apporterons également quelques modifications au menu latéral d’iTop afin d’accueillir les menus associés aux API du site api.gouv.fr.

Génération du squelette

Commencez par générer un squelette d’extension en saisissant les informations suivantes dans le formulaire de création.
Cliquez sur le bouton Generate et téléchargez ensuite l’archive créée.
Décompressez l’archive téléchargée dans le dossier extensions sur le serveur iTop.

Company name: MyCompany
Extension name: gouv-api-extension
Extension label: api.gouv.fr data synchronisation
Version: 1.0.0
Dependencies: itop-structure/3.0.0

Formulaire pour la génération du squelette

Pour aller plus loin dans la création d’extensions, visitez la documentation officielle.

Création de la classe du modèle de données

Nous allons créer notre classe pour stocker les informations des établissement scolaires. Nous faisons le choix de dériver la classe Location et héritons ainsi des données de localisation.

Informations générales

Initialisation de la classe Establishment qui dérive de la classe Location.

Ajoutez les informations générales de la classe dans le fichier de modèle de données comme suit:

datamodel.gouv-edu-extension.xml

<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.6">
  …
    <classes>
      <class id="Establishment" _delta="define">
        <parent>Location</parent>
        <properties>
          <category>bizmodel,searchable</category>
          <abstract>false</abstract>
          <key_type>autoincrement</key_type>
          <db_table>establishment</db_table>
          <db_key_field>id</db_key_field>
          <db_final_class_field/>
          <naming>
            <format>%1$s</format>
            <attributes>
              <attribute id="name"/>
            </attributes>
          </naming>
          <display_template/>
          <icon>assets/img/school.png</icon>
        </properties>
      </class>
    </classes>
  …
</itop_design>

💡La balise <icon> permets d’associer une image à la classe.

Ajout des attributs de la classe du modèle de données

Déclaration des attributs de la classe Establishment. Pour chacun de ces attributs nous spécifions son type de donnée xsi:type="AttributeXXX".
Nous rendons obligatoires les attributs identifier, type et private_public.

Ajoutez les attributs de la classe dans le fichier de modèle de données comme suit:

datamodel.gouv-edu-extension.xml

<classes>
  <class id="Establishment" _delta="define">
  …
    <fields>
      <!-- identifier-->
      <field id="identifier" xsi:type="AttributeString">
        <sql>identifier</sql>
        <default_value/>
        <is_null_allowed>false</is_null_allowed>
      </field>
      <!-- type -->
      <field id="type" xsi:type="AttributeString">
        <sql>type</sql>
        <default_value/>
        <is_null_allowed>false</is_null_allowed>
      </field>
      <!-- private_public -->
      <field id="private_public" xsi:type="AttributeEnum">
        <values>
          <value>unknown</value>
          <value>private</value>
          <value>public</value>
        </values>
        <sql>private_public</sql>
        <default_value/>
        <is_null_allowed>false</is_null_allowed>
        <display_style>radio_horizontal</display_style>
      </field>
      <!-- academy_code -->
      <field id="academy_code" xsi:type="AttributeString">
        <sql>code_academie</sql>
        <default_value/>
        <is_null_allowed>true</is_null_allowed>
      </field>
      <!-- catering_service -->
      <field id="catering_service" xsi:type="AttributeBoolean">
        <sql>catering_service</sql>
        <default_value/>
        <is_null_allowed>true</is_null_allowed>
      </field>
      <!-- students_count -->
      <field id="students_count" xsi:type="AttributeInteger">
        <sql>students_count</sql>
        <default_value/>
        <is_null_allowed>false</is_null_allowed>
      </field>
      <!-- opening_date -->
      <field id="opening_date" xsi:type="AttributeDate">
        <sql>opening_date</sql>
        <default_value/>
        <is_null_allowed>false</is_null_allowed>
      </field>
    </fields>
  </class>
</classes>

Ajoutez les traductions de nos attributs de classe dans le fichier d’internationalisation.
Par défaut, seul le fichier de traduction anglais est créé, ajoutez d’autres langues au besoin.

en.dict.gouv-api-extension.php

Dict::Add('EN US', 'English', 'English', array(
  'Class:Establishment/Attribute:identifier' => 'Establishment code',
  'Class:Establishment/Attribute:identifier+' => 'Code UAI',
  'Class:Establishment/Attribute:type' => 'Establishment type',
  'Class:Establishment/Attribute:private_public' => 'Private / Public',
  'Class:Establishment/Attribute:private_public/Value:private' => 'Private',
  'Class:Establishment/Attribute:private_public/Value:public' => 'Public',
  'Class:Establishment/Attribute:private_public/Value:unknown' => 'Unknown',
  'Class:Establishment/Attribute:academy_code_academie' => 'Academy code',
  'Class:Establishment/Attribute:catering_service' => 'Catering service',
  'Class:Establishment/Attribute:students_count' => 'Students count',
  'Class:Establishment/Attribute:opening_date' => 'Opening date',
));

💡Le symbole + permets de joindre une bulle de survol au formulaire pour un attribut donné: ‘Class:Establishment/Attribute:identifier+

Ajout des données de présentation

Déclaration des différents modes d’affichage de notre classe.
La section détails determine l’affichage de notre classe lors de la visualisation ou de l’édition d’objet.
La section list determine les attributs de notre classe utilisés comme colonnes dans les listes.
La section search quant à elle définit les attributs utilisés comme critères lors des recherches.

Ajoutez les modes d’affichage comme suit:

datamodel.gouv-edu-extension.xml

      <presentation>
        <details>
          <items>
            <item id="type">
              <rank>30</rank>
            </item>
            <item id="identifier">
              <rank>10</rank>
            </item>
            <item id="private_public">
              <rank>40</rank>
            </item>
            <item id="academy_code">
              <rank>50</rank>
            </item>
            <item id="catering_service">
              <rank>60</rank>
            </item>
            <item id="students_count">
              <rank>70</rank>
            </item>
            <item id="opening_date">
              <rank>80</rank>
            </item>
            <item id="org_id">
              <rank>90</rank>
            </item>
            <item id="address">
              <rank>100</rank>
            </item>
            <item id="postal_code">
              <rank>110</rank>
            </item>
            <item id="city">
              <rank>120</rank>
            </item>
            <item id="country">
              <rank>130</rank>
            </item>
          </items>
        </details>
        <search>
          <items>
            <item id="type">
              <rank>10</rank>
            </item>
            <item id="private_public">
              <rank>20</rank>
            </item>
            <item id="academy_code">
              <rank>30</rank>
            </item>
          </items>
        </search>
        <list>
          <items>
            <item id="identifier">
              <rank>10</rank>
            </item>
            <item id="private_public">
              <rank>30</rank>
            </item>
            <item id="city">
              <rank>40</rank>
            </item>
            <item id="opening_date">
              <rank>50</rank>
            </item>
            <item id="catering_service">
              <rank>60</rank>
            </item>
            <item id="students_count">
              <rank>70</rank>
            </item>
          </items>
        </list>
      </presentation>
Ajout des données de réconciliation

Déclaration des attributs de réconciliation de notre classe.
Nous nous servons de l’identifiant de l’établissement scolaire pour la réconciliation car il est unique.

🎓La réconciliation définit un ou plusieurs attributs garants de l’identification d’un objet.

Ajoutez les informations de réconciliation de la classe dans le fichier de modèle de données comme suit:

datamodel.gouv-edu-extension.xml

<classes>
  <class id="Establishment" _delta="define">
    …
    <properties>
      …
      <reconciliation>
        <attributes>
          <attribute id="identifier"/>
        </attributes>
      </reconciliation>
    </properties>
  </class>
</classes>

Personnalisation du menu iTop

Nous allons organiser nos données issues du site api.gouv.fr dans un menu intégré au menu latéral d’iTop.
Vous pourrez par la suite ajouter autant d’entrées dans ce menu que d’API que vous implémenterez.

Aperçu du menu api.gouv.fr

Ajoutez les informations de menu de la classe dans le fichier de modèle de données comme suit:

datamodel.gouv-edu-extension.xml

<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.6">
  …
  <menus>
    <menu id="GouvAPIMenu" xsi:type="MenuGroup" _delta="define">
      <rank>10</rank>
      <style>
        <decoration_classes>fas fa-dice-d20</decoration_classes>
      </style>
    </menu>
    <menu id="EstablishmentSearchMenu" xsi:type="SearchMenuNode" _delta="define">
      <rank>10</rank>
      <parent>GouvAPIMenu</parent>
      <class>Establishment</class>
    </menu>
  </menus>
  …
</itop_design>

💡La balise <decoration_classes> permets de définir une icône pour le groupe de menu.

Les codes pour les icônes sont disponibles sur le site de Font Awesome: https://fontawesome.com/.

Ajoutez les traductions de nos menus dans le fichier d’internationalisation comme suit:

en.dict.gouv-api-extension.php

Dict::Add('EN US', 'English', 'English', array(
  'Menu:GouvAPIMenu' => 'api.gouv.fr',
  'Menu:EstablishmentSearchMenu' => 'National Education Establishments',
));

Installation de notre extension

Copiez l’extension dans le dossier extensions de votre serveur iTop.
Ajoutez les autorisations d’écriture au fichier de configuration d’iTop se trouvant dans le dossier conf/production/config-itop.php puis accédez à l’adresse web de votre iTop suivante: http://{adresse-serveur-itop}/setup dans un navigateur internet afin de lancer l’installation.

Confirmez les étapes de l’installation et assurez-vous que notre nouvelle extension soit cochée à la fin de l’assistant d’installation.

Ecran de sélection des extensions

Et voilà ! Nous pouvons à présent accueillir des établissements de l’éducation nationale dans notre iTop.
Essayez de créer un établissement pour vérifier que tout est opérationnel.

Naviguez dans le menu api.gouv.fr > Etablissements éducation nationale et cliquez sur create a establishment.

Formulaire de création d’un nouvel établissement

Dans le chapitre suivant, nous verrons comment synchroniser les données grâce à un collecteur.

3/ La création d’un collecteur pour iTop

Installation iTop data collector

Télécharger l’extension data collector base.
Et décompressez le contenu dans le dossier de votre choix. (Ne pas décompresser dans le dossier www de votre serveur afin de ne pas en exposer le contenu)
Il est tout à fait possible de décompresser sur une autre machine du réseau du moment qu’elle possède un environnement d’exécution PHP 7.x.

Tout savoir sur Data collector base dans notre documentation officielle.

Configuration de la source de données

La configuration de la source de données est décrite au format JSON.
Le plus simple est de paramétrer la source de données dans l’interface utilisateur de la console d’iTop et de la transformer au format JSON via un script fourni par l’extension iTop data collector.

Créez une nouvelle source de données dans le menu configuration > sources de dé données de synchronisation.
Saisissez les informations suivantes et laissez les autres champs à leur valeur par défaut.

Name: Synchro établissements éducation nationale
Description: https://api.gouv.fr/documentation/api-annuaire-education
Target class: Establishment
Contact to notify: Your_email
Datatable: data_national_education_establishment

Ecran de configuration source de donnée (Properties)

Choisissez l’attribut identifier pour la réconciliation.
Choisissez la clé de réconciliation Full name pour l’attribut Owner organization ce qui nous permettra d’indiquer l’organisation par son nom et être ainsi plus lisible.

Ecran de configuration source de donnée (Attributes)

Générez ensuite la définition JSON de cette source de données dans le répertoire collectors.

php toolkit/dump_tasks.php --task_name="Synchro établissements éducation nationale" > collectors/DataEducationCollector.class.inc.json

Pour aller plus loin sur ce sujet, consultez notre documentation officielle.

Paramétrage du collecteur

Nous devons préparer un fichier de paramétrage pour l’utilisation du collecteur.

Dupliquez le fichier de configuration params.distrib.xml en le nommant params.local.xml.
Mettez à jour le fichier de paramétrage avec vos paramètres comme suit:

conf/params.local.xml

<?xml version="1.0" encoding="UTF-8"?>

<parameters>
  <itop_url>itop_server_url</itop_url>
  <itop_login>your_login</itop_login>
  <itop_password>your_password</itop_password>
  <itop_login_mode></itop_login_mode>

  <synchro_user>admin</synchro_user>
  <contact_to_notify>your_email</contact_to_notify>
  …

Création de la classe collector

Création de la classe DataEducationCollector dérivée de la classe Collector.
On vérifie la présence de curl et on initialise en supprimant les anciennes données collectées.

DataEducationCollector.class.inc.php

class DataEducationCollector extends Collector
{
  /** @var array education establishment data */
  protected $aData = [];

  /** @var integer current process element */
  protected $iCurrent;

  /** @var integer fetched elements count */
  protected $idx;

  /**
  * Constructor.
  *
  * @throws Exception
  */
  public function __construct()
  {
    parent::__construct();

    // test curl presence
    if(!function_exists('curl_version')){
      throw new Exception('Curl is mandatory, check your PHP installation');
    }

    // initialization
    $this->init();
  }

  /**
  * Initialization.
  *
  * @return void
  */
  private function init() : void
  {
    // remove data files
    $this->RemoveDataFiles();
  }
}


On déclare notre fonction principale pour l’appel à l’API.
Cette méthode retourne un booléen pour signifier qu’il reste des données à récolter.
On itère par paquets de 100 éléments (max définit par l’API) et on se limite à 300 résultats pour l’instant.

DataEducationCollector.class.inc.php

class DataEducationCollector extends Collector
{
  …
  /**
  * Call rest api to acquire data.
  *
  * @return bool true if more data available
  */
  private function callRestApi() : bool
  {
    // open curl
    $oCurl = curl_init();

    // check limit
    $limit = 100;
    $max = 300;
    if($this->iCurrent + $limit > $max){
      $limit = $max - $this->iCurrent;
    }

    // construct API url
    $url = "https://data.education.gouv.fr/api/v2/catalog/datasets/fr-en-annuaire-education/records?limit=$limit&offset=$this->iCurrent";

    // curl options
    curl_setopt($oCurl, CURLOPT_URL, $url);
    curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, false);

    // execute
    $aResult = json_decode(curl_exec($oCurl), true);
    echo "curl_exec: $url\n";
    curl_close($oCurl);

    // retrieve records
    $this->aData = $aResult['records'];
    $this->iCurrent += count($aResult['records']);

    // processing flags
    $hasMoreData = $this->iCurrent < $aResult['total_count'];
    $hasReachMax = $this->iCurrent >= $max;

    return $hasMoreData && !$hasReachMax;
  }
}

Le mécanisme de fond de la collecte.
On appelle la fonction prépare pour collecter un lot puis on dépile les enregistrements de ce lots en les ajoutant dans des fichiers csv respectant une taille maximum de données.
On recommence tant qu’il y a des données à collecter.

DataEducationCollector.class.inc.php

class DataEducationCollector extends Collector
{
  …
  /**
  * Prepare data.
  *
  * @return bool true if more data available
  */
  public function Prepare() : bool
  {
    // call rest API for new block of data
    $this->idx = 0;
    return $this->callRestApi(); // return true if more data available
  }

  /**
  * Fetch next block of data.
  *
  * @return bool|array current element data or false if no more data to fetch
  */
  public function Fetch()
  {
    // has something to fetch ?
    if ($this->idx < count($this->aData))
    {
      // next value to fetch
      $aElement = $this->aData[$this->idx++]['record'];

      // table conversion establishment private public enumeration
      $tableConvPrivatePublicEnum = [
        'Privé' => 'private',
        'Public' => 'public',
        '' => 'unknown',
      ];

      return array(
        'primary_key' => $aElement['id'],
        'identifiant' => $aElement["fields"]['identifiant_de_l_etablissement'],
        'name' => $aElement["fields"]['nom_etablissement'],
        'org_id' => $this->aSynchroFieldsToDefaultValues['org_id'],
        'address' => $aElement['fields']['adresse_1'],
        'city' => $aElement['fields']['nom_commune'],
        'postal_code' => $aElement['fields']['code_postal'],
        'country' => 'France',
        'status' => 'active',
        'type' => $aElement['fields']['type_etablissement'],
        'private_public' => $tableConvPrivatePublicEnum[$aElement['fields']['statut_public_prive']],
        'code_academie' => $aElement['fields']['code_academie'],
        'restauration' => $aElement['fields']['restauration'] == '' ? '0' : $aElement['fields']['restauration'],
        'nombre_eleves' => $aElement['fields']['nombre_d_eleves'] == null ? 0 : $aElement['fields']['nombre_d_eleves'],
        'date_ouverture' => $aElement['fields']['date_ouverture']
      );
    }

    return false; // no more data to fetch
  }

  /**
  * Collect data.
  *
  * @return bool true if data has been collected
  */
  public function Collect($iMaxChunkSize = 0)
  {
    $idx = 0;

    do{
      // block preparation
      $continue = $this->Prepare();

      // fetch elements...
      while ($aRow = $this->Fetch()) {
        if (($idx == 0) || (($iMaxChunkSize > 0) && (($idx % $iMaxChunkSize) == 0))) {
          $this->NextCSVFile();
          $this->AddHeader($this->aColumns);
        }
        $this->AddRow($aRow);
        $idx++;
      }
    }
    while($continue); // next block

    // cleanup
    $this->Cleanup();

    return $idx > 0;
  }
}


Inscription du collecteur

Nous allons à présent déclarer notre nouveau collecteur à l’orchestrateur.

Créez un fichier main.php à la racine du dossier collectors et initialisez le comme suit:

collectors/main.php

Orchestrator::AddCollector(1, 'DataEducationCollector');

Lancement de la synchronisation

Vous pouvez à présent déclencher la synchronisation avec la commande suivante.

php .\exec.php

Naviguez dans le menu api.gouv.fr > Etablissements éducation nationale.
Vous devriez retrouver vos 300 établissements synchronisés.

4/ Industrialisation de la solution

Nous souhaitons à présent finaliser notre solution en externalisant des paramètres de notre collecteur dans le fichier de paramétrage.

Ajout de paramètres

Ajoutez les membres de classe comme suit:

DataEducationCollector.class.inc.php

class DataEducationCollector extends Collector
{
  const PRIMARY_KEY = 'primary_key';

  /** @var string rest API url */
  protected $sRestUrl;

  /** @var integer rest results amount limit */
  protected $iRestLimit;

  /** @var integer max elements to synchronize */
  protected $iMaxElements;

  /** @var array data columns */
  protected $aSynchroCols;

  /** @var array data translation */
  protected $aSynchroTranslation;

  /** @var array default values */
  protected $aSynchroDefaultValues;

  /** @var array class fields */
  protected $aSynchroClassFields;
  …

  /**
  * Initialization.
  *
  * @return void
  */
  private function init() : void
  {
    $this->iCurrent = 0;
    $this->iMaxElements = -1;

    // extract configuration values
    $this->extractConfigurationValues();

    // remove data files
    $this->RemoveDataFiles();
  }

  /**
  * Extract configuration values.
  *
  * @return void
  * @throws Exception
  */
  private function extractConfigurationValues() : void
  {
    // read configuration values
    $aConfigurationValues = Utils::GetConfigurationValue(strtolower(get_class($this)));

    // rest url
    if (array_key_exists('rest_url', $aConfigurationValues)) {
      $this->sRestUrl = $aConfigurationValues['rest_url'];
    }

    // rest limit
    if (array_key_exists('rest_limit', $aConfigurationValues)) {
      $this->iRestLimit = $aConfigurationValues['rest_limit'];
    }

    // max elements
    if (array_key_exists('max_elements', $aConfigurationValues)) {
      $this->iMaxElements = $aConfigurationValues['max_elements'];
    }

    // fields association
    if (array_key_exists('class_fields', $aConfigurationValues)) {
      $this->aSynchroClassFields = array(Self::PRIMARY_KEY => null);
      $this->aSynchroClassFields = array_merge($this->aSynchroClassFields, $aConfigurationValues['class_fields']);
      $this->aSynchroCols = array_keys($this->aSynchroClassFields);
    }

    // translation
    if (array_key_exists('translations', $aConfigurationValues)) {
      $this->aSynchroTranslation = $aConfigurationValues['translations'];
      foreach ($this->aSynchroTranslation as $key => $aTranslation) {
        $this->aSynchroTranslation[$key] = array_flip($this->aSynchroTranslation[$key]);
      }
    }

    // default values
    if (array_key_exists('defaults', $aConfigurationValues)) {
      $this->aSynchroDefaultValues = $aConfigurationValues['defaults'];
    }
  }

  /**
  * Call rest api to acquire data.
  *
  * @return void
  * @throws Exception
  */
  private function callRestApi() : bool
  {
    …
    // check limit
    $limit = $this->iRestLimit;
    if($this->iCurrent + $this->iRestLimit > $this->iMaxElements){
      $limit = $this->iMaxElements - $this->iCurrent;
    }

    // construct API url
    $url = "$this->sRestUrl?limit=$limit&offset=$this->iCurrent";
    …
  }

  /**
  * Fetch next data.
  *
  * @return bool|array current element data or false if no more data to tech
  */
  public function Fetch()
  {
    // has something to fetch ?
    if ($this->idx < count($this->aData))
    {
      // next value to fetch
      $aElement = $this->aData[$this->idx++]['record'];

      // fetched data
      $fetchedData = array();

      // fill values
      foreach ($this->aSynchroClassFields as $classField => $value) {
        if($classField == Self::PRIMARY_KEY){
          $fetchedData[$classField] = $aElement['id'];
        }
        else if(array_key_exists($value, $aElement["fields"]) && $aElement["fields"][$value] != ''){
          $fetchedData[$classField] = $this->getFieldValue($classField, $aElement["fields"][$value]);
        }
        else{
          $fetchedData[$classField] = $this->getFieldDefaultValue($classField);
        }
      }

      return $fetchedData;
    }

    return false; // no more data to fetch
  }

Versionner le collecteur

Créez un fichier de déclaration de module à la racine du dossier collectors et initialisez le come suit:

collectors/module.gouv-api-collectors-extension.php

__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'gouv-api-collectors-extension/1.0.0',
array(
  // Identification
  //
  'label' => 'api.gouv.fr API data synchronisation collectors',
  'category' => 'business',

  // Setup
  //
  'dependencies' => array(
    'gouv-api-extension/1.0.0'
  ),
  'mandatory' => false
  )
);

5/ Exercice en autonomie !

Lister les établissements AFPA de la France entière
https://api.gouv.fr/documentation/api_etablissements_publics

Ajouter une nouvelle entrée dans le menu latéral.

6/ Quizz

– Comment créer un squelette d’extension rapidement ?
🔲 En la créant avec un éditeur de texte
🔲 Grâce au pages du wiki
🔲 Avec une autre extension

– Qu’est-ce que la réconciliation ?
🔲 La clé primaire d’une classe
🔲 L’affichage du nom intelligible d’un objet
🔲 Un ou ensemble d’attributs d’identification

– Ou sont définies les traductions des textes ?
🔲 Dans la balise class du modèle de donnée
🔲 Dans la balise dictionaries du modèle de donnée
🔲 Dans la fonction Dict::Add en PHP

– Comment installer son extension ?
🔲 Avec iTop hub
🔲 En exécutant un script d’installation
🔲 En plaçant l’extension dans le dossier extensions du serveur iTop.

– Comment donner une version à son collecteur
🔲 En nommant le dossier avec la version
🔲 En créant un fichier module
🔲 En le sauvegardant sous Git

Share This