Dans le post précédente, nous avons appris comment utiliser les plugins de processus pour transformer les données entre la source et la destination. Certains champs Drupal ont des composants multiples. Par exemple, les champs texte formatés enregistrent le texte à afficher et le format texte à appliquer. Les champs d’image stockent une référence au fichier, le texte de l’alternative et du titre, la largeur et la hauteur. L’API de migration se réfère au composant d’une champ comme sous-champ. Aujourd’hui, nous allons apprendre comment migrer vers ces sous-champs et savoir quels sont les sous-champs disponibles.
L’exemple d’aujourd’hui consistera à migrer les données dans les champs `Corps` et `Image` du type de contenu `Article` qui sont disponibles par défaut. Cela suppose que Drupal a été installé en utilisant le profil d’installation `standard`. Comme dans les exemples précédents, nous allons créer un nouveau module et écrire un fichier de définition de migration pour effectuer la migration. Les extraits de code seront compacts pour se concentrer sur des éléments particuliers de la migration. Le code complet est disponible sur https://github.com/dinarcon/ud_migrations. Le nom du module est `UD Migration Subfields` et son nom de machine est `ud_migrations_subfields`. Le `id` de l’exemple de migration est `udm_subfields`. Consultez cet article pour savoir comment activer le module et exécuter la migration.
Loading gist https://gist.github.com/dinarcon/68470f1a50f013ff9fbe35ca79bd1488
Un seul enregistrement est présenté pour que l’extrait soit court, mais il en existe d’autres. En plus d’avoir un identificateur unique, chaque enregistrement comprend un nom, un profil court et des détails sur l’image.
Le champ `Corps` est de type `Texte (formaté, long, avec résumé)`. Ce type de champ comporte trois éléments : le texte intégral à présenter, un texte sommaire et un format texte. Le Migrate API vous permet d’écrire dans chaque composant séparément en définissant les cibles des sous-champs. Le prochain extrait de code montre comment le faire :
Loading gist https://gist.github.com/dinarcon/68470f1a50f013ff9fbe35ca79bd1488
La syntaxe à migrer dans les sous-champs est le nom de la machine du champ et le nom du sous-champ séparés par une barre oblique (/). Puis, un deux-points (:), un espace, et la valeur. Vous pouvez définir la valeur d’un nom de colonne source pour une copie mot à mot ou utiliser n’importe quelle combinaison de plugins de processus. Il n’est pas nécessaire de migrer dans toutes les sous-champs. Chaque champ détermine les composants requis, de sorte qu’il est possible que toutes les sous-champs ne soient pas définies. Dans cet exemple, seuls le format de la valeur et du texte seront définis.
Loading gist https://gist.github.com/dinarcon/68470f1a50f013ff9fbe35ca79bd1488
Le sous-champ `value` est définie sur la colonne source `profile`. Comme vous pouvez le voir dans le premier extrait, il contient des balises HTML. Une balise `a` pour être précis. Parce que nous voulons que la balise soit rendue comme un lien, un format de texte qui autorise cette balise doit être spécifié. Il n’y a pas d’informations sur les formats de texte dans les sources, mais Drupal est livré avec un couple que nous pouvons choisir. Dans ce cas, nous utilisons le format de texte `Restricted HTML`. Notez que le plugin `default_value` est utilisé et défini sur `restricted_html`. Lors du réglage des formats de texte, il est nécessaire d’utiliser leur nom de machine. Vous pouvez les trouver dans la page de configuration pour chaque format de texte. Pour `HTML restreint’; c’est-à-dire /admin/config/content/formats/manage/restricted_html.
Remarque: Les formats de texte sont un sujet complètement différent qui a même des implications en matière de sécurité. Pour que la discussion ne s’éloigne pas du sujet, nous ne donnerons que quelques recommandations. Lorsque vous devez migrer les balises HTML, vous devez savoir quelles balises apparaissent dans votre source, lesquelles vous voulez autoriser dans Drupal, et sélectionner un format de texte qui accepte ce que vous avez mis sur liste blanche et filtrer toute balise dangereuse comme `script`. En règle générale, vous devriez éviter de définir le sous-champ `format` pour utiliser le format texte `Full HTML`.
Ils existent différentes approches pour migrer les images. Aujourd’hui, nous allons utiliser le module Migrate Files. Il est important de noter que Drupal traite les images comme des fichiers avec des propriétés et un comportement supplémentaires. Toute approche utilisée pour migrer des fichiers peut être adaptée pour migrer des images.
Loading gist https://gist.github.com/dinarcon/68470f1a50f013ff9fbe35ca79bd1488
Lorsque vous migrez n’importe quel champ, vous devez utiliser leur machine dans la section de mappage. Pour le champ `Image`, le nom de la machine est `field_image`. Sachant cela, vous avez défini chacune de ses sous-champs:
Pour le `target_id`, le plugin `file_import` est utilisé. Ce plugin nécessite une valeur de configuration `source` avec une url vers le fichier. Dans ce cas, la colonne `photo_url` de la section source est utilisée. L’indicateur `reuse` indique que si un fichier avec le même emplacement et le même nom existe, il doit être utilisé au lieu de télécharger une nouvelle copie. Lorsque vous travaillez sur des migrations, il est commun de les exécuter une et une autre fois jusqu’à ce que vous obteniez les résultats désirés. L’utilisation de l’option `reuse` évitera de créer plusieurs références ou copies du fichier image, en fonction de la configuration du plugin. L’option `id_only` est définie de telle sorte que le plugin ne renvoie que l’identifiant de fichier utilisé par Drupal au lieu d’un tableau de référence d’entité. Ceci est dû au fait que chaque sous-champ est définie manuellement. Pour les autres sous-zones (`alt`, `title`, `width` et `height`), la valeur est une copie exacte de la source.
Remarque: Le module Migrate Files propose un autre plugin nommé `image_import`. Celui-ci vous permet de définir tous les sous-champs dans le cadre de la configuration du plugin. Un exemple de son utilisation sera montré dans le prochain article. Cet exemple utilise le plugin `file_import` pour mettre en évidence la configuration des sous-champs image.
Certaines champs ont de nombreuses sous-champs. Les champs d’adresse, par exemple, ont 13 sous-champs. Comment pouvez-vous savoir lesquels sont disponibles ? La réponse se trouve dans la classe qui fournit le type de champ. Une fois que vous avez trouvé la classe, recherchez la méthode `schema`. Les sous-champs sont contenues dans le tableau `columns’; de la valeur retournée par cette méthode. Voyons quelques exemples.
La méthode `schema` définit les colonnes de la base de données utilisées par le champ pour stocker ses données. Lorsque vous migrez dans des sous-champs, vous migrez en fait dans ces colonnes de base de données particulières. Toute restriction imposée par le schéma de la base de données doit être respectée. C’est pourquoi vous n’utilisez pas d’unités lors de la migration de la largeur et de la hauteur des images. La base de données n’attend qu’un nombre entier représentant les valeurs correspondantes en pixels. En raison des pratiques orientées objet, vous avez parfois besoin de regarder la classe parent pour connaître tous les sous-champs qui sont disponibles.
Note technique: L’API Migrate contourne les validations de l’API Form. Par exemple, il est possible de migrer des images sans paramétrer le sous-champ `alt` même si celle-ci est définie comme requis dans la configuration du champ. Si vous essayez de modifier un nœud créé de cette façon, vous obtiendrez une erreur de zone indiquant que le texte alternatif est obligatoire. De même, il est possible d’écrire le sous-champ `title` même si le champ ne s’y attend pas, comme dans l’exemple d’aujourd’hui. Si vous deviez activer le texte `title` plus tard, les informations seront déjà là. Rappelez-vous que lorsque vous utilisez l‘API Migrate, vous écrivez directement dans la base de données.
Une autre option est de se connecter à la base de données et de vérifier les structures des tables. Par exemple, le champ `Image` stocke ses données dans la table `node__field_image’;. Entre autres, cette table comporte cinq colonnes qui portent le nom du nom de la machine et de le sous-champ du champ:
L’examination du code source ou du schéma de la base de données n’est pas simple. Ces informations sont incluses à titre de référence pour ceux qui souhaitent explorer plus en détail l’API Migrate. Vous pouvez rechercher des exemples de migrations pour voir quels sous-champs sont disponibles. Je pourrais même fournir une liste dans un futur billet de blog. 😉
Conseil: Vous pouvez utiliser Drupal Console pour l’introspection du code et l’analyse de la structure des tables de la base de données. De plus, de nombreux plugins sont définis par des classes qui se terminent par la chaîne de caractères `Item`. Vous pouvez utiliser la fonction de recherche de votre EDI pour trouver la classe en utilisant le nom du champ comme indice.
Chaque champ Drupal possède au moins une sous-champ. Par exemple, `Text (simple)` et `Number (integer)` définit uniquement la sous-zone `valeur`. Les extraits de code suivants sont équivalents :
Loading gist https://gist.github.com/dinarcon/68470f1a50f013ff9fbe35ca79bd1488
Loading gist https://gist.github.com/dinarcon/68470f1a50f013ff9fbe35ca79bd1488
Dans les exemples des jours précédents, aucun sous-champ n’a été définie manuellement, mais Drupal sait quoi faire. Comme nous l’avons mentionné, l’API Migrate offre du sucre syntaxique pour écrire des fichiers de définition de migration plus courts. C’est un autre exemple. Vous pouvez sauter le sous-champ défini par défaut et régler manuellement les autres au besoin. Pour les champs `Fichier` et `Image`, le sous-champ par défaut est `target_id`. Comment l’API Migrate sait-elle quel sous-champ est le sous-champ par défaut ? Tu dois revérifier le code.
Le sous-champ par défaut est déterminée par la valeur de retour de la méthode `mainPropertyName` de la classe fournissant le type de zone. Encore une fois, les pratiques orientées objet peuvent nécessiter de regarder les classes parentales pour trouver cette méthode. Dans le cas du champ `Image`, il est fourni par ImageItem qui étend FileItem qui étend EntityReferenceItem. C’est ce dernier qui contient le `mainPropertyName` renvoyant la chaîne `target_id`.
Qu’avez-vous appris dans le billet d’aujourd’hui ? Connaissiez-vous le concept de sous-champs ? Vous êtes-vous déjà demandé quelles sont les cibles de destination possibles (sous-champs ) pour chaque type de champ ? Saviez-vous que l’API Migrate trouve le sous-champ par défaut pour vous ? Veuillez partager vos réponses dans les commentaires. Aussi, je vous serais reconnaissant de bien vouloir partager ce billet de blog avec vos collègues.