Importer des contenus multilingues et des médias dans WordPress avec Polylang

Importer des contenus multilingues et des médias dans WordPress avec Polylang

Migrer du contenu multilingue avec des médias depuis une ancienne technologie vers un nouveau site WordPress doté d’une architecture personnalisée : tel est le défi de ce tutoriel.

Ce tutoriel est réservé aux développeurs ou utilisateurs passionnés qui cherchent à apprendre la méthode manuelle pour importer des contenus tiers dans un site multilingue sous WordPress. La méthode décrite ci-dessous fait suite à une mission de refonte pour le compte d’un client.

Objectifs

Le challenge à relever est le suivant : migrer des données en provenance d’un outil de gestion tiers vers un site WordPress moderne. Le système d’origine est obsolète et accumule de la dette technique depuis plusieurs années.

Ces données présentent 3 difficultés techniques :

  • Multiples types de contenu : articles, pages et produits ;
  • Contenus multilingues : des milliers de publication en français et anglais ;
  • Fichiers médias : des milliers de médias en vrac dans plusieurs répertoires ;

L’objectif est donc de prendre ces données et de les remettre dans les bonnes cases de notre WordPress. La dette technique sera résorbée et notre client disposera d’un nouveau système capable de publier ou de mettre à jour des contenus en toute simplicité.

Solution technique

Pour réaliser cette mission, nous allons développer un thème WordPress sur-mesure capable d’afficher l’ensemble de nos données de manière personnalisée. Au préalable, nous aurons mandaté un partenaire de confiance pour s’occuper de la direction artistique. Cette partie ne sera pas évoquée dans ce tutoriel qui se focalise sur la migration des données.

Sur le plan architectural, les articles et les pages sont natifs sous WordPress. Il n’y a donc rien à développer de ce côté. En revanche, nous allons devoir créer un type de contenu personnalisé pour les produits et une taxonomie personnalisée pour les classer proprement. Cette taxonomie nous sera très utile pour l’ajout ultérieur de filtres à facettes.

Pour la gestion des interfaces en back-office, nous utiliserons l’extension Advanced Custom Fields capable d’ajouter les champs personnalisés nécessaire pour nos données. ACF c’est véritablement l’outil indispensable pour le développeur WordPress.

En ce qui concerne les aspects multilingues, c’est l’extension Polylang qui a été retenue pour des questions de performances et de respect des standards de WordPress. Elle dispose également des hooks et des fonctions PHP nécessaires pour la suite des opérations.

Pour la gestion des médias, nous avons déjà tout ce qu’il nous faut dans WordPress.

En résumé, nous aurons recours à une solution tout ce qu’il y a de plus classique sous WordPress : fiable et durable. Je pars donc du principe que ces prérequis techniques sont respectés pour la suite du tutoriel.

Étape n°1 – Créer un fichier CSV à partir des données sources

La première étape nécessite d’exporter les données sources dans un fichier exploitable en PHP. En effet, nos contenus sont pour l’instant stockés dans une base de données structurée différemment de celle de WordPress.

Dans ce cas de figure, la méthode la plus simple est d’exporter les tables dans un format universellement reconnu comme :

  • Le CSV pour Comma Separated Values ;
  • Le JSON pour JavaScript Object Notation ;
  • Le XML pour Extensible Markup Language ;

En ce qui nous concerne, c’est le format CSV que nous avons retenu ici pour les raisons suivantes :

  • Les données sources sont suffisamment bien ordonnées et ne nécessite par d’être retraitées. Nous aurons un seul import à opérer, il ne s’agit pas d’une mission de syndication de flux auquel cas le JSON serait plus intéressant ;
  • Ce format peut être lu facilement par un tableur ce qui nous permet de vérifier en amont l’exactitude des données exportées en termes de volumétrie, d’encodage, etc. ;
  • L’ancien back-office dispose d’un bouton d’export CSV (et même XML) : c’est presque anecdotique ici car nous passerons en ligne de commande pour réaliser l’export SQL ou via phpMyAdmin ;

Un fichier CSV se compose de colonnes et de lignes à la manière d’un tableur. La première ligne du fichier contient les en-têtes de colonnes. Chaque ligne correspond à une publication qu’il nous faut importer.

Pour les besoins de ce tutoriel, nous nous concentrerons sur l’import du catalogue de produits qui nous permettra d’aborder tout les points techniques. Il ne sera guère difficile de décliner la méthode pour des articles ou des pages.

Plusieurs fichiers CSV seront générés à partir des tables correspondantes en base de données :

  1. Les marques rattachées aux produits (taxonomie personnalisée) ;
  2. Le catalogue produit avec environ 1 500 références (type de contenu personnalisé) ;
  3. Les médias rattachés aux produits (type de contenu natif) ;

Pour procéder à l’export de ces fichiers, plusieurs méthodes existent avec par ordre de préférence :

  • L’interface en ligne de commandes (CLI) : l’approche la plus fiable pour exporter les tables de votre choix, nécessite un accès SSH ;
  • phpMyAdmin : moins fiable mais parfois la seule méthode disponible ;
  • L’interface d’administration : cette fonctionnalité existait dans notre cas, cela dépendra directement du projet source ;

Choisissez donc la méthode de votre choix pour exporter les données. Si vous avez de la chance, les données seront bien segmentées vous évitant d’avoir à croiser plusieurs tables entre elles lors de la phase d’import dans WordPress – ce fut mon cas par bonheur. Dans le cas contraire, il vous faudra adapter la partie code pour opérer des traitements complémentaires ou bien utiliser un tableur pour créer votre propre jeu de données.

À ce stade, nous sommes donc en possession de 3 fichiers CSV distincts avec des données plus ou moins bien formatées. La présence de code HTML nécessitera un traitement additionnel pour opérer un nettoyage.

Étape n°2 – Coder le script d’import en PHP

C’est l’étape la plus longue : coder les différents scripts d’importation dans le langage PHP.

Import des marques dans une taxonomie personnalisée

Le premier fichier CSV contient les marques de nos produits. Ce sont des termes qui peupleront notre taxonomie personnalisée Marque. Il est important de commencer par importer ces données avant le catalogue produit sans quoi il nous sera impossible d’associer les produits aux marques.

Ce fichier se compose des colonnes suivantes :

  • Ancien identifiant : il s’agit du numéro unique présent sur l’ancien site. Il nous sera utile pour créer les liaisons marque / produit lors de l’import suivant ;
  • Nom de la marque : l’intitulé du terme ;
  • Une description : pratique pour afficher quelques lignes introductives et pour le référencement naturel ;

Vous pouvez étoffer ce fichier avec une colonne contenant le logo de la marque. Comme WordPress ne supporte pas nativement un tel champ image pour chaque terme, je vous recommande d’utiliser Advanced Custom Fields pour gérer cela.

Commençons par créer un nouveau fichier PHP que nous nommerons import-brand.php. Placez-le à la racine de votre projet Web.

Ajoutons WordPress comme dépendance en début de fichier comme ceci :

require_once('wp/wp-load.php');

Spécifions ensuite le chemin du fichier CSV à importer. Pour faire simple, posez-le à la racine du projet Web et indiquez simplement le nom du fichier comme ceci :

$file_path = 'brand.csv';

Il nous faut à présent boucler sur chaque ligne du fichier pour insérer le terme dans notre base de données, à l’aide de la fonction wp_insert_term() :

if (($handle = fopen($file_path, 'r')) !== FALSE) {
while (($data = fgetcsv($handle, NULL, ';')) !== FALSE) {
$term = wp_insert_term(
$data[1],
'brand'
);

Cette fonction accepte le nom du terme en premier argument et le nom de la taxonomie en second. Dans notre fichier, c’est la colonne numéro 1 qui remplit ce rôle – n’oubliez pas que PHP démarre à 0.

Nous enchaînons en définissant la langue du terme nouvellement importé. Le français est notre langue par défaut, c’est donc le code ISO fr que nous indiquons :

pll_set_term_language($term['term_id'], 'fr');

L’étape suivante va consister à ajouter quelques métadonnées sur notre terme. Cela fonctionne comme des champs personnalisés sur lesquels vous pourrez greffer ACF pour disposer d’une interface plus aboutie. C’est la fonction add_term_meta() que nous allons utiliser. Elle accepte 4 arguments dont :

  • L’identifiant du terme à modifier : nous reprenons celui nouvellement créé plus haut ;
  • La clé du champ personnalisé : dans mon exemple, nous aurons un champ pour stocker l’ancien identifiant et un autre pour la description du terme – vous pourriez également utiliser le champ natif pour gérer la description ;
  • La valeur : la colonne à utiliser comme valeur ;
  • Valeur unique : un booléen sur true pour indiquer que la valeur sera unique, il ne peut y avoir plusieurs champs portant la même clé dans notre exemple ;
if (! is_wp_error($term)) {
add_term_meta($term['term_id'], 'wpc_brand_id', $data[0], true);
add_term_meta($term['term_id'], 'wpc_brand_desc', $data[4], true);
}

Même si les noms de marque ne se traduisent pas, il nous faut quand même créer les tableaux associatifs entre les langues. C’est la condition sine qua none pour générer les traductions des métadonnées comme la description du terme.

Nous reprenons donc le même code que précédemment tout en rajoutant un suffixe pour différencier les termes en base – la version premium de Polylang gère les identifiants identiques pour information :

$term_en = wp_insert_term(
$data[1],
'brand',
['slug' => $data[1] . '-en']
);

pll_set_term_language($term_en['term_id'], 'en');

Vous pouvez également reprendre le code précédent pour injecter vos métadonnées.

Pour terminer, nous allons créer l’association des termes multilingues pour Polylang comme ceci :

$array = [
'fr' => $term['term_id'],
'en' => $term_en['term_id']
];
pll_save_term_translations( $array );

De cette manière, vous obtiendrez une colonne liant la version française et la version anglaise dans la liste des termes de votre back-office WordPress.

Le code complet est le suivant :

<?php

require_once('wp/wp-load.php');

// Set the path to the CSV file
$file_path = 'brands.csv';

// Open the CSV file
if (($handle = fopen($file_path, 'r')) !== FALSE) {
// Loop through each row in the CSV file
while (($data = fgetcsv($handle, NULL, ';')) !== FALSE) {
// Create the term object
$term = wp_insert_term(
$data[1],
'brand'
);

pll_set_term_language($term['term_id'], 'fr');

if (! is_wp_error($term)) {
add_term_meta($term['term_id'], 'wpc_brand_id', $data[0], true);
add_term_meta($term['term_id'], 'wpc_brand_desc', $data[4], true);
}

$term_en = wp_insert_term(
$data[1],
'brand',
['slug' => $data[1] . '-en']
);

pll_set_term_language($term_en['term_id'], 'en');

if (!is_wp_error($term_en)) {
add_term_meta($term_en['term_id'], 'wpc_brand_id', $data[0], true);
add_term_meta($term_en['term_id'], 'wpc_brand_desc', $data[5], true);
}

$array = [
'fr' => $term['term_id'],
'en' => $term_en['term_id']
];
pll_save_term_translations( $array );
}

fclose($handle);
}

Import d’un catalogue produit dans un type de contenu personnalisé

Le second fichier CSV qui correspond à notre catalogue produit se compose des colonnes suivantes :

  • Ancien identifiant : ce numéro unique nous sera très utile pour lier les contenus multilingues entre eux ;
  • Langue : le code ISO de la langue qui sera repris par Polylang. Il s’agit de fr et en dans notre cas ;
  • Titre de la publication : le nom du produit qui pourra être combiné avec d’autres colonnes pour des questions de référencement naturel ;
  • Prix : le montant en euro du produit ;
  • Visibilité (publique ou masqué) : l’état de visibilité du produit ;
  • Description longue en français : le corps de texte en français ;
  • Description longue en anglais : le corps de texte en anglais ;
  • Vidéo YouTube : le lien vers une vidéo YouTube ;
  • Image à la une : le chemin vers le fichier pour l’image mise en avant ;
  • Identifiant de taxonomie (Marque) : le numéro unique pour le terme de la taxonomie rattachée au produit, ici une marque ;

Déplacez ensuite ce fichier à la racine de votre projet Web.

À l’aide de votre éditeur de code favori comme PhpStorm ou Visual Studio Code, créez un nouveau fichier PHP que vous nommerez par exemple import-products.php.

Là encore, la première chose à faire et d’ajouter WordPress comme dépendance.

<?php

require_once('wp/wp-load.php');

Définissons ensuite une première variable pour spécifier le chemin du fichier CSV à importer. Si vous avez placé le fichier CSV à la racine du projet Web, de même que votre script d’import alors indiquez simplement le nom du fichier CSV.

// Définir le chemin du fichier CSV
$file_path = 'products.csv';

Nous allons à présent transformer le fichier en un tableau pour la raison suivante : la première colonne contient l’ancien identifiant d’un contenu. Il nous faut ordonner le tableau pour que les identifiants se suivent ce qui va nous permettre d’avoir les contenus multilingues qui s’enchaînent proprement. Ainsi, nous aurons par exemple l’identifiant 40 présent deux fois avec une ligne pour le français et une ligne pour l’anglais. Nous pourrons alors créer des couples de traductions conformes pour Polylang.

$count = 0;
$csv_data = array();

if (($handle = fopen($file_path, 'r')) !== FALSE) {
while (($data = fgetcsv($handle, NULL, ';')) !== FALSE) {
$csv_data[] = $data;
}
fclose($handle);
}

array_multisort(array_column($csv_data, 0), SORT_ASC, $csv_data);

Maintenant que le tableau est traité correctement, nous devons boucler dessus pour insérer les contenus dans les bonnes cases de WordPress. C’est la fonction wp_insert_post() qui est la pièce maîtresse du script dans laquelle nous allons injecter un tableau d’arguments.

Nous aurons besoin de définir les termes de la taxonomie qui correspondent aux marques des produits. Pour cela, nous récupérons l’identifiant du terme via la fonction get_terms(). Seul un identifiant sera retourné ici étant donné qu’un produit n’est associé qu’à une seule marque. Il sera stocké dans une variable $brand_id. Cette étape nécessite d’avoir importé les termes de la taxonomie au préalable.

$brand_id = get_terms(array(
'taxonomy' => 'brand',
'meta_key' => 'nom_du_champ_qui_stocke_identifiant',
'meta_value' => $data[15],
'hide_empty' => false,
'fields' => 'ids'
));

Nous pouvons désormais créer notre tableau d’arguments pour la fonction wp_insert_post() avec :

  • 'post_type' : pour le type de contenu personnalisé qui accueillera les données ;
  • 'post_status' : optez pour 'publish' pour publier immédiatement le contenu, laissez vide pour rester en brouillon qui est la valeur par défaut ;
  • 'post_title' : spécifiez la colonne qui contient votre titre à partir de la variable $data dans laquelle le tableau de données est stocké ;
  • 'post_date' : même chose pour la date dont le format accepté est le suivant Y-m-d H:i:s, à vous d’opérer un traitement supplémentaire si nécessaire ;
  • 'tax_input' : pour les termes rattachés à la taxonomie personnalisée, c’est ici que nous injectons l’identifiant de la marque du produit stocké précédemment dans $brand_id ;
  • 'meta_input' : nous passons un tableau associatif avec une clé et une valeur correspondant à une colonne de notre fichier CSV. Il vous faudra adapter en fonction de votre fichier source. Il pourra être nécessaire d’opérer des traitements préalables notamment pour formater ou nettoyer la donnée. Une fonction comme wp_strip_all_tags() vous sera utile pour supprimer la présence de code HTML ;
$args = [
'post_type' => 'product',
'post_status' => 'publish',
'post_title' => $data[3],
'post_date' => $data[2],
'tax_input' => [
'brand' => $brand_id
],
'meta_input' => [
'meta_key_1' => $data[0],
'meta_key_2' => $data[5],
'meta_key_3' => $data[6],
'meta_key_4' => $data[7],
'meta_key_5' => wp_strip_all_tags( $data[10] ),
]
];
$post_id = wp_insert_post( $args );

Si vous utilisez l’extension Advanced Custom Fields, vous pourrez avoir besoin de mettre à jour des champs personnalisés complexes de type oEmbed, galeries, ou encore relationnel. La fonction update_field() répond à ce besoin, voici un exemple pour un champ oEmbed pour une URL vidéo YouTube. Ici, la donnée se trouve dans la colonne numéro 13 :

update_field( 'champ_oembed_youtube', $data[13], $post_id );

Il nous faut ensuite définir la langue du contenu afin que Polylang dispose de l’information. C’est la fonction pll_set_post_language() qui nous permet d’attribuer une langue sur l’identifiant du contenu nouvellement inséré. La colonne numéro 1 contient le code ISO de la langue :

pll_set_post_language( $post_id, $data[1] );

Continuons notre script avec l’import de l’image mise en avant. Le code est légèrement plus complexe car nous devons attacher le fichier média sur le contenu inséré précédemment. Passons en revue ces quelques lignes de code.

Tout d’abord, les lignes 1 à 6 : nous créons un tableau d’arguments pour éviter les erreurs SSL sur notre installation locale qui ne dispose pas d’un certificat SSL valide.

La ligne 9 détermine le numéro de colonne qui contient le chemin de l’image. La ligne 10 récupère le nom du fichier.

La ligne 14 définit comme variable le fichier à envoyer puis l’envoie comme fichier attaché dans le contenu à l’aide de la fonction wp_insert_attachment(). Cette fonction reçoit un tableau d’arguments avec :

  • 'post_mime_type' : le format du type de fichier ;
  • 'post_parent' : l’identifiant de la publication obtenue à l’étape d’avant, indispensable pour attacher l’image au contenu ;
  • 'post_title' : le titre donné au fichier dans la médiathèque généré à partir du nom du fichier ;

L’identifiant du fichier attaché est ensuite stockée dans la variable $attachment_id.

Nous allons maintenant définir la langue du média et créer le couple d’identifiants entre la version française et anglaise. Pour rappel, nous avons trié le tableau de façon à ce que les lignes s’enchaînent en alternant les deux langues, le français puis l’anglais. Ainsi, il est facile d’utiliser un compteur puis d’injecter mon tableau associatif avec la fonction pll_save_post_translations().

Cette étape est fondamentale car elle permet d’envoyer une seule fois le fichier média tout en créant l’association de langues. Vous pourrez ainsi basculer entre les versions pour opérer vos traductions.

$args = [
'fr' => $attachmentFR,
'en' => $attachmentEN
];
pll_save_post_translations( $args );

La dernière ligne de code définit l’image mise en avant à partir du fichier envoyé et affecté à la bonne publication grâce à la fonction set_post_thumbnail().

$options = array(
"ssl" => array(
"verify_peer" => false,
"verify_peer_name" => false,
),
);

// Get the image path and filename
$image_path = $data[14];
$image_filename = basename($image_path);


if ($image_path) {
$upload_file = wp_upload_bits( $image_filename, null, file_get_contents( $image_path ) );

if ( ! $upload_file['error'] ) {
$wp_filetype = wp_check_filetype( $image_filename, null );

$attachment = [
'post_mime_type' => $wp_filetype['type'],
'post_parent' => $post_id,
'post_title' => $image_filename
];

$attachment_id = wp_insert_attachment( $attachment, $upload_file['file'], $post_id );

if ( ! is_wp_error( $attachment_id ) ) {
require_once( ABSPATH . "wp-admin" . '/includes/image.php' );

$attachment_data = wp_generate_attachment_metadata( $attachment_id, $upload_file['file'] );
wp_update_attachment_metadata( $attachment_id, $attachment_data );

if ( $count % 2 == 0 ) {
$attachmentFR = $attachment_id;
} else {
$attachmentEN = $attachment_id;
}

if ( $count % 2 === 0 ) {
$args = [
'fr' => $attachmentFR,
'en' => $attachmentEN
];
pll_save_post_translations( $args );
}

set_post_thumbnail( $post_id, $attachment_id );
}
}

Le code intégral est disponible ci-dessous :

<?php

require_once('wp/wp-load.php');

// Set the path to the CSV file
$file_path = 'products.csv';

$count = 0;
$csv_data = array();

// Load the CSV file into an array
if (($handle = fopen($file_path, 'r')) !== FALSE) {
while (($data = fgetcsv($handle, NULL, ';')) !== FALSE) {
$csv_data[] = $data;
}
fclose($handle);
}

// Sort the array by the first column in ascending order
array_multisort(array_column($csv_data, 0), SORT_ASC, $csv_data);

// Loop through each row in the sorted CSV data
foreach ($csv_data as $data) {
$count++;

$term_id = get_terms( array(
'taxonomy' => 'brand',
'meta_key' => 'wpc_brand_id',
'meta_value' => $data[15],
'hide_empty' => false,
'fields' => 'ids'
) );

$args = [
'post_type' => 'product',
'post_status' => 'publish',
'post_title' => $data[3],
'post_date' => $data[2],
'tax_input' => [
'brand' => $term_id
],
'meta_input' => [
'meta_key_1' => $data[0],
'meta_key_2' => $data[5],
'meta_key_3' => $data[6],
'meta_key_4' => $data[7],
'meta_key_5' => wp_strip_all_tags( $data[10] ),
]
];

$post_id = wp_insert_post( $args );
update_field( 'wpc_product_video', $data[13], $post_id );
pll_set_post_language( $post_id, $data[1] );

$options=array(
"ssl"=>array(
"verify_peer" => false,
"verify_peer_name" => false,
),
);

// Get the image path and filename
$image_path = $data[14];
$image_filename = basename($image_path);

if ($image_path) {
$upload_file = wp_upload_bits( $image_filename, null, file_get_contents( $image_path ) );

if ( ! $upload_file['error'] ) {
$wp_filetype = wp_check_filetype( $image_filename, null );

$attachment = [
'post_mime_type' => $wp_filetype['type'],
'post_parent' => $post_id,
'post_title' => $image_filename
];

$attachment_id = wp_insert_attachment( $attachment, $upload_file['file'], $post_id );

if ( ! is_wp_error( $attachment_id ) ) {
require_once( ABSPATH . "wp-admin" . '/includes/image.php' );

$attachment_data = wp_generate_attachment_metadata( $attachment_id, $upload_file['file'] );
wp_update_attachment_metadata( $attachment_id, $attachment_data );

if ( $count % 2 == 0 ) {
$attachmentFR = $attachment_id;
} else {
$attachmentEN = $attachment_id;
}

if ( $count % 2 === 0 ) {
$args = [
'fr' => $attachmentFR,
'en' => $attachmentEN
];
pll_save_post_translations( $args );
}

set_post_thumbnail( $post_id, $attachment_id );
}
}
}
if ($count % 2 == 0) {
$postFR = $post_id;
} else {
$postEN = $post_id;
}

if ($count % 2 === 0) {
$args = [
'fr' => $postFR,
'en' => $postEN
];
pll_save_post_translations( $args );
}
}

Import des médias multilingues

Notre dernier fichier de données est composée de 3 colonnes :

  1. L’identifiant du média ;
  2. L’identifiant du produit auquel est rattaché le média : utile pour créer les liaisons entre la publication et les médias ;
  3. Le nom du fichier ;

Plusieurs médias sont associés à une même publication, de manière à créer des galeries photos.

Nous allons créer un nouveau script d’import en PHP que nous nommerons import-media.php.

Les premières lignes sont similaires au script d’import précédent, je vais donc m’attarder sur les lignes 15 à 22. Pour chaque ligne – autrement dit chaque média à importer, nous allons rechercher s’il existe une publication relative à l’identifiant. Si tel est le cas, nous importerons les médias sur cette publication.

C’est la fonction WP_Query qui nous sera utile ici. Très connue des développeurs, nous allons lui faire passer le tableau d’arguments que voici :

  • 'meta_key' : le nom du champ personnalisé qui contient l’ancien identifiant ;
  • 'meta_value' : la valeur à rechercher, définie dans la colonne numéro 1 me concernant ;
  • 'posts_per_page' : seule une publication doit être retournée, ce paramètre est presque inutile en réalité ;
  • 'post_type' : le type de contenu sur lequel opérer la requête ;
  • 'lang' : ce paramètre est spécifique à Polylang, nous allons l’ajouter pour filtrer uniquement sur les publications en français, qui est la langue par défaut ;

Les lignes 25 à 50 sont identiques au script précédent sur l’envoi des médias. C’est la suite qui diverge avec la création de la galerie de médias associée à la publication.

Une nouvelle fois, nous utiliserons un champ personnalisée de type galerie créé à l’aide de l’extension ACF. Nous testons dans un premier temps qu’aucune galerie existe déjà auquel cas nous déclarons un nouveau tableau.

Ensuite, nous associons chaque identifiant de fichier attaché récupéré plus haut à ce tableau.

Nous terminons avec la mise à jour du champ galerie via la fonction update_field() qui passera notre tableau sur le produit associé. Notez que nous utilisons la clé du champ et non l’identifiant ce qui permet de gérer le cas où le champ n’a pas encore été ajouté en base de données.

$gallery = get_field( 'field_id', get_the_ID(), false );
if ( ! $gallery ) {
$gallery = array();
}
$gallery[] = $attachment_id;
update_field( 'field_id', $gallery, get_the_ID() );

Il nous faut à présent récupérer la publication en version anglaise et mettre à jour le champ galerie. De cette façon, aucun média ne sera envoyé en double et nous aurons la garantie que les galeries seront identiques entre les langues.

$english_post_id = pll_get_post(get_the_ID(), 'en');
update_field( 'field_id', $gallery, $english_post_id );

Ce script est le plus long à exécuter car il agit sur des fichiers physiques et la base de données de WordPress de manière importante. La durée d’exécution sera directement liée au nombre de médias à importer. Pensez à réviser à la hausse certains réglages de votre configuration PHP afin d’éviter les délais dépassés.

Vous retrouverez l’intégralité du code juste ici :

<?php

require_once( 'wp/wp-load.php' );

// Set the path to the CSV file
$file_path = 'products_images.csv';

$count = 0;
$csv_data = array();

// Load the CSV file into an array
if ( ( $handle = fopen( $file_path, 'r' ) ) !== false ) {
while ( ( $data = fgetcsv( $handle, null, ';' ) ) !== false ) {
$args = array(
'meta_key' => 'wpc_product_id',
'meta_value' => $data[1],
'posts_per_page' => 1,
'post_type' => 'product',
'lang' => 'fr'
);
$products = new WP_Query($args);
if ($products->have_posts()) :
while ( $products->have_posts() ) : $products->the_post();
// Get the image path and filename
$image_path = $data[2];
$image_filename = basename($image_path);

if ($image_path) {
$upload_file = wp_upload_bits( $image_filename, null, file_get_contents( $image_path ) );

if ( ! $upload_file['error'] ) {
$wp_filetype = wp_check_filetype( $image_filename, null );

$attachment = [
'post_mime_type' => $wp_filetype['type'],
'post_parent' => get_the_id(),
'post_title' => $image_filename
];

$attachment_id = wp_insert_attachment( $attachment, $upload_file['file'], get_the_id() );

if ( ! is_wp_error( $attachment_id ) ) {
require_once( ABSPATH . "wp-admin" . '/includes/image.php' );

$attachment_data = wp_generate_attachment_metadata( $attachment_id, $upload_file['file'] );
wp_update_attachment_metadata( $attachment_id, $attachment_data );


// return array of current image IDs
$gallery = get_field( 'field_id', get_the_ID(), false );
if ( ! $gallery ) {
$gallery = array();
}
$gallery[] = $attachment_id;
update_field( 'field_id', $gallery, get_the_ID() );

$english_post_id = pll_get_post(get_the_ID(), 'en');
update_field( 'field_id', $gallery, $english_post_id );
}
}
}
endwhile;
endif; wp_reset_postdata();
}
fclose( $handle );
}

Étape n°3 – Exécuter les scripts d’importations

C’est l’étape la plus excitante car nous allons tester l’import de nos données. Vous aurez sans doute besoin de vous y reprendre plusieurs fois avant d’obtenir une migration correcte. Pensez donc à faire une sauvegarde intégrale de votre instance locale pour vous permettre de revenir à l’état antérieur en cas d’erreurs.

Vous devrez respecter un ordre d’exécution pour vos scripts d’importation :

  1. Import des termes de taxonomie ;
  2. Import du catalogue produits ;
  3. Import des médias ;

Si vous ne respectez pas cet ordre, les scripts tomberont en échec et / ou importeront des données partielles.

La méthode la plus simple consiste tout simplement ouvrir le fichier PHP dans votre navigateur Web. Comme nous avions pris soin de placer les scripts à la racine de votre projet Web, l’URL prendra cette forme : https://example.com/nom-script.php

Dès validation de l’adresse, le navigateur exécutera le script et la page chargera pendant plusieurs minutes. La page est blanche sauf si vous obtenez des erreurs PHP – sous réserve d’avoir activer les débogueurs dans votre environnement de développement.

Étape n°4 – Vérifier les données importées

Si tout a fonctionné correctement, vous verrez des données dans votre back-office. Il vous faudra vérifier que les informations sont stockées dans les bons champs et sous le bon format.

En cas de stockage incorrect, vous devrez ajuster le script PHP et recommencez l’import en partant d’une base saine.

Allez-y pas à pas quitte à opérer les imports sur des jeux de données plus limités.

Nous voici arrivés au terme de ce long tutoriel technique. J’espère que vous disposerez des bases nécessaires pour aller plus loin en développant vos propres scripts d’import de données. À vous de jouer !

Par Aurélien Denis

Consultant & Développeur WordPress / WooCommerce. Un site à créer, à maintenir ou à débuguer ? Contactez-moi.

Laisser un commentaire