Image mise en avant pour l'article

Créer un Process Plugin personnalisé pour Migrate dans Drupal 10

23 décembre 2024
Drupal
Dans tous projets digitaux, la migration de données est un enjeu clé. Bien que le CMS Drupal propose de nombreux outils prêts à l’emploi, ces derniers ne couvrent pas toujours les cas complexes ou spécifiques. Alors comment faire ? Dans cet article, je vous montre comment concevoir un process plugin personnalisé pour Migrate, afin de relever ces défis et de réussir vos migrations vers Drupal 10.


Drupal 10 offre une API de migration robuste permettant aux développeurs de transférer des données depuis diverses sources vers un site Drupal. Les process plugins (ou plugins de processus en français) jouent un rôle essentiel dans la transformation des données durant la migration.

Bien que le CMS Drupal fournisse plusieurs process plugins prêts à l'emploi, des exigences spécifiques de projets peuvent nécessiter la création de plugins personnalisés.

Cet article vous guide de manière détaillée à travers la création d’un process plugin personnalisé pour le module Migrate dans Drupal 10, couvrant la configuration de l’environnement, la définition du plugin, son utilisation dans une configuration de migration, et l’ajout de services pour des transformations plus avancées.

Un développeur travaille sur un élément de code d'un site internet

Avant-propos : étapes d’une migration Drupal

Une migration de données via l’API de migration de Drupal suit 3 étapes principales définies dans un fichier de migration au format YAML :

  1. Récupération des données sources - Ciblage des valeurs à récupérer depuis les données sources.
  2. Traitement des données récupérées (Process) – Les valeurs sont, si nécessaire, transformées pour correspondre au formatage de destination dans Drupal. Chaque étape de transformation est réalisée par un process plugins.
  3. Écriture des données de destination – Les valeurs ainsi traitées sont transmises à un plugin de destination qui se charge de créer les contenus et renseigner les valeurs de champs dans Drupal.

Dans cet article, nous allons nous intéresser à l’étape 2 de ce processus de migration.

Etape 1 : Installer les modules nécessaires

Pour utiliser les fonctionnalités de migration avancées, vous devez installer les modules Migrate, issu du core et Migrate Plus, issu de la communauté. Le module Migrate Plus étend les fonctionnalités du module Migrate, offrant des plugins supplémentaires et des options de configuration avancées.

1. Installation via Composer

Utilisez Composer pour installer le module Migrate Plus. Ouvrez votre terminal et exécutez la commande suivante depuis la racine de votre projet Drupal :

composer require drupal/migrate_plus

Cette commande télécharge le module Migrate Plus et ses dépendances dans le répertoire modules/contrib.

2. Activation du module via Drush

Après l'installation, activez le module en utilisant Drush, l'interface en ligne de commande de Drupal. Exécutez la commande suivante :

drush en migrate_plus -y

NB : Le module Migrate étant requis pour pouvoir installer Migrate Plus, il sera automatiquement activé lorsque vous activez Migrate Plus.

Étape 2 : Création du Process Plugin personnalisé

Dans cet exemple, nous allons créer un Process Plugin personnalisé dont l’objectif sera de concaténer 2 valeurs de type texte en les séparant par un espace.

1. Structure du module

Commencez par créer un module personnalisé qui contiendra votre process plugin. Pour cet exemple, nous allons créer un module nommé custom_migrate.

> Création du répertoire du module

Naviguez dans le répertoire modules/custom de votre installation Drupal et créez un nouveau module nommé custom_migrate.

Votre module doit contenir les fichiers suivants :

custom_migrate/
├─ custom_migrate.info.yml
├─ custom_migrate.module
└─ src/
   └─ Plugin/
    └─ migrate/
     └─ process/
      └─ CustomConcat.php

> Définir le Process plugin

Créez le fichier CustomConcat.php dans le répertoire src/Plugin/migrate/process/ avec le contenu suivant :

namespace Drupal\custom_migrate\Plugin\migrate\process;

use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Row;
use Drupal\migrate\ProcessPluginBase;

/**
* Concatenate multiple fields.
*
* @MigrateProcessPlugin(
* id = "custom_concat"
* )
*/
class CustomConcat extends ProcessPluginBase {

  /**
  * Transforms the source value by concatenating two fields.
  *
  * @param mixed $value
  * The source value.
  * @param \Drupal\migrate\MigrateExecutableInterface $migrate_executable
  * The migrate executable.
  * @param \Drupal\migrate\Row $row
  * The row from the source to process.
  * @param string $destination_property
  * The destination property.
  *
  * @return string
  * The concatenated value.
  */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    $field1 = $value['field1'];
    $field2 = $value['field2'];


    return $field1 . ' ' . $field2;
  }

}

Explications du code :

  • Namespace : Indique le chemin logique de la classe au sein de Drupal.
  • Use Statements : Importent les classes nécessaires pour le plugin.
  • Annotation @MigrateProcessPlugin : Indique à Drupal que cette classe est un process plugin pour le module Migrate. L'ID custom_concat sera utilisé pour référencer ce plugin dans les configurations de migration.
  • Classe CustomConcat : Hérite de la classe ProcessPluginBase, ce qui permet d'utiliser les fonctionnalités de base des plugins de processus.
  • Méthode transform() : C’est la méthode principale où la logique de transformation des données est implémentée. Ici, elle concatène les valeurs de deux champs source field1 et field2 avec un espace entre eux.

NB : Penser à vider le cache de Drupal après avoir créé votre plugin afin que celui-ci soit bien reconnu.

Étape 3 : Utiliser le plugin dans une configuration de migration

Comme vu en avant-propos, la configuration de migration est définie dans un fichier YAML qui spécifie les détails de la migration, notamment la source des données, les processus de transformation à appliquer à chaque donnée source, et la destination des données.

1. Créer une configuration de migration

Créez un fichier YAML de migration, par exemple migrate_plus.migration.custom_migration.yml, dans le répertoire config/install/ de votre module personnalisé ou dans un autre répertoire de configuration approprié.

Voici un exemple de contenu pour ce fichier :

id: custom_migration
label: 'Custom Migration Example'
migration_group: default

source:
  plugin: oembed_data
  data_rows:
   - field1: 'Hello'
   - field2: 'World'

  ids:
   field1:
    type: string
process:
  concatenated_field:
   plugin: custom_concat
   source:
    - field1
    - field2
destination:
  plugin: entity:node
  default_bundle: article
  default_langcode: true

dependencies: {}

Explications des sections du YAML :

  • id : Identifiant unique de la migration. Utilisé pour exécuter ou réexécuter la migration.
  • label : Nom de la migration tel qu'il apparaîtra dans l'interface d'administration.
  • migration_group : Groupe auquel appartient la migration. Utile pour organiser plusieurs migrations.
  • source : Définition de la source des données. Ici, nous utilisons embedded_data pour des données d'exemple intégrées directement dans le fichier YAML.
    • plugin : Le type de plugin de source. embedded_data est utilisé pour des données statiques ou de test.
    • data_rows : Les données à migrer. Chaque ligne représente une entité source avec les champs field1 et field2.
    • ids : Définit les identifiants uniques pour chaque entité source. Ici, field1 est utilisé comme identifiant unique de type string.
  • process : Définit les transformations à appliquer aux données source avant de les stocker dans la destination.
    • concatenated_field : Le champ de destination dans Drupal.
      • plugin : Le plugin de processus utilisé, ici custom_concat que nous avons défini précédemment.
      • source : Les champs source utilisés par le plugin. Ici, field1 et field2 sont passés au plugin pour être concaténés.
    • destination : Définit où les données seront migrées.
      • plugin : Le type de destination, ici entity:node indique que les données seront migrées vers des entités de type node.
      • default_bundle : Le type de contenu Drupal, ici « article », indique que les données migrées seront stockées dans des nœuds de type « Article ».

2. Activer le module et exécuter la migration

Après avoir créé votre module personnalisé et défini la configuration de migration, vous devez activer le module et exécuter la migration.

Pour cela, activez votre module personnalisé :

drush en custom_migrate -y

Utilisez Drush pour exécuter votre migration et importer les données source définies dans votre configuration de migration :

drush migrate-import custom_migration

Aller plus loin - Ajout d’un service dans le process plugin

Pour des transformations plus complexes, vous pouvez injecter des services Drupal dans votre process plugin personnalisé. Cela vous permet d'utiliser des services existants tels que le gestionnaire d'entités ou les services de journalisation pour enrichir la logique de transformation.

1. Modifier le plugin pour accepter le service

Modifiez le fichier CustomConcat.php pour implémenter l’injection de dépendances. Cela permet au plugin d'utiliser le service injecté pour effectuer des transformations plus sophistiquées.

Remplacez le contenu de CustomConcat.php par le code suivant :

namespace Drupal\custom_migrate\Plugin\migrate\process;

use Drupal\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Row;
use Drupal\migrate\ProcessPluginBase;

/**
* Concatenate multiple fields.
*
* @MigrateProcessPlugin(
* id = "custom_concat"
* )
*/
class CustomConcat extends ProcessPluginBase {

  /**
  * The entity type manager service.
  *
  * @var \Drupal\Core\Entity\EntityTypeManagerInterface
  */
  protected $entityTypeManager;

  /**
  * Constructs a CustomConcat object.
  *
  * @param array $configuration
  * A configuration array containing information about the plugin instance.
  * @param string $plugin_id
  * The plugin ID for the plugin instance.
  * @param mixed $plugin_definition
  * The plugin implementation definition.
  * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
  * The entity type manager service.
  */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
  * {@inheritdoc}
  */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager')
    );
  }

/**
  * Transforms the source value by concatenating two fields.
  *
  * @param mixed $value
  * The source value.
  * @param \Drupal\migrate\MigrateExecutableInterface $migrate_executable
  * The migrate executable.
  * @param \Drupal\migrate\Row $row
  * The row from the source to process.
  * @param string $destination_property
  * The destination property.
  *
  * @return string
  * The concatenated value.
  */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    $field1 = $value['field1'];
    $field2 = $value['field2'];

    $node = $this->entityTypeManager->getStorage('node')->load($value['field3']);
    if ($node) {
      return $field1 . ' ' . $field2 . ' (' . $node->getTitle() . ')';
    }
    return $field1 . ' ' . $field2;
  }

}

Explications des Modifications :

  • Interface ContainerFactoryPluginInterface : Implémentée pour permettre l’injection de dépendances via le conteneur de services de Drupal.
  • Propriété $entityTypeManager : Stocke le service injecté entity_type.manager pour une utilisation ultérieure.
  • Constructeur __construct : Reçoit et stocke le service injecté.
  • Méthode create : Méthode statique utilisée par Drupal pour instancier le plugin en injectant le service depuis le conteneur.
  • Méthode transform : Utilise le gestionnaire d'entités pour charger un nœud basé sur la valeur source $value[‘field3’] (supposée être un ID de nœud). Si le nœud existe, il ajoute son label à la valeur concaténée.

Dans l’exemple précédent, nous avons injecté le service entity_type.manager afin de pouvoir charger un nœud spécifique de Drupal et utiliser son champ « label » dans le processus de concaténation de nos champs $field1 et $field2.

2. Mettre à jour la configuration de migration

Après avoir modifié le plugin pour accepter un service, vous devez mettre à jour votre fichier de migration YAML pour refléter les changements.

Voici un exemple mis à jour de migrate_plus.migration.custom_migration.yml :

id: custom_migration_with_service
label: 'Custom Migration Example'
migration_group: default

source:
  plugin: oembed_data
  data_rows:
   - field1: 'Hello'
   - field2: 'World'
   - field3: '124' # Supposons que ceci est un ID

  ids:
   field3:
    type: string
process:
  concatenated_field:
   plugin: custom_concat
   source:
    - field1
    - field2
    - field3
destination:
  plugin: entity:node
  default_bundle: article
  default_langcode: true

dependencies: {}

Explications des changements :

  • id : Changé en custom_migration_with_service pour refléter l'utilisation du service.
  • source.data_rows : Ajout de field3 , supposée être un ID de nœud existant dans Drupal.
  • process.concatenated_field.source : Maintenant, le plugin custom_concat reçoit field3 comme source pour utiliser le gestionnaire d'entités.

Ce qu’il faut retenir, la création de process plugins personnalisés dans Drupal 10 offre une flexibilité exceptionnelle pour adapter les migrations de données aux besoins spécifiques de chaque projet. En suivant ce guide détaillé, vous avez appris à :

  1. Configurer votre environnement Drupal pour utiliser Migrate API - Installer et activer les modules nécessaires pour la migration.
  2. Créer un module personnalisé - Définir la structure de base d'un module Drupal et créer les fichiers essentiels.
  3. Définir un process plugin personnalisé - Créer une classe PHP qui implémente la logique de transformation des données.
  4. Utiliser le plugin dans une configuration de migration - Définir une migration YAML qui utilise votre plugin personnalisé pour transformer les données.
  5. Ajouter des services au plugin - Enrichir votre plugin en injectant des services Drupal pour des transformations plus sophistiquées.
  6. Tester et valider la migration - Vérifier que les données sont migrées correctement et ajuster si nécessaire.

En maîtrisant ces techniques, vous serez en mesure de gérer efficacement les migrations complexes, garantissant que les données sont transformées et intégrées correctement dans votre site Drupal. N’hésitez pas à adapter et étendre ces exemples selon les exigences spécifiques de vos projets.

J’espère que cet article vous aidera. Pour le compléter, je vous propose d'autres articles :

Et des ressources complémentaires :

Crédit photo : Sarinyapinngam

Image mise en avant pour l'article
Fabien Estrabaud
Développeur Web
Vous avez un projet de refonte de site à nous confier ?
Notre équipe d'experts vous conseille et accompagne dans votre projet de refonte.
Contactez-nous !