# Tester wp_privacy_personal_data_exporters pour l’export RGPD

> Une extension qui stocke des données personnelles doit déclarer un exportateur RGPD fonctionnel. Voici comment le vérifier automatiquement plutôt qu'à l'œil.

- Auteur : Clément Hadrot
- Publié le : 2020-03-23
- Mis à jour le : 2020-03-23
- Catégorie : Tests
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tests/tester-export-rgpd-wp-privacy-personal-data-exporters/

## L’essentiel

- Déclarer un exportateur via le filtre officiel
- Vérifier la structure du tableau retourné
- Couvrir la pagination des gros volumes

Une extension de billetterie que nous maintenons stocke des numéros de téléphone et des préférences alimentaires liés à des commandes. Le jour où un client a exercé son droit d'accès RGPD, l'export généré par WordPress était vide. La fonction d'export existait bien dans le code, mais elle n'était jamais appelée : le filtre `wp_privacy_personal_data_exporters` pointait vers une méthode renommée lors d'un refactoring, sans qu'aucun test ne le détecte.

Ce genre de régression silencieuse justifie à elle seule d'écrire un test dédié à l'exportateur RGPD, séparé des tests fonctionnels classiques de l'extension.

## Comprendre le contrat attendu par WordPress

Le cœur de WordPress construit la liste des exportateurs disponibles à partir du filtre `wp_privacy_personal_data_exporters`. Chaque entrée doit fournir un `callback` respectant une signature précise : recevoir un e-mail et un numéro de page, retourner un tableau avec les clés `data`, `done`. Chaque élément de `data` doit lui-même contenir `group_id`, `group_label`, `item_id` et `data` (un tableau de paires `name`/`value`).

```
add_filter('wp_privacy_personal_data_exporters', function ($exporters) {
    $exporters['billetterie-commandes'] = [
        'exporter_friendly_name' => __('Commandes de billetterie', 'billetterie'),
        'callback'               => 'billetterie_exporter_donnees',
    ];
    return $exporters;
});
```

## Écrire le test d'intégration

Le test doit créer une commande réaliste rattachée à un e-mail connu, appeler le callback directement — sans passer par l'interface d'administration — puis vérifier la forme exacte du retour :

```
class Test_Export_RGPD_Billetterie extends WP_UnitTestCase {

    public function test_export_contient_les_champs_attendus(): void {
        $commande_id = $this->factory()->post->create([
            'post_type' => 'commande_billet',
        ]);
        update_post_meta($commande_id, '_email_client', 'julie@example.test');
        update_post_meta($commande_id, '_telephone', '0601020304');

        $resultat = billetterie_exporter_donnees('julie@example.test', 1);

        $this->assertArrayHasKey('data', $resultat);
        $this->assertArrayHasKey('done', $resultat);
        $this->assertTrue($resultat['done']);
        $this->assertNotEmpty($resultat['data']);

        $item = $resultat['data'][0];
        $this->assertSame('billetterie-commandes', $item['group_id']);
        $this->assertArrayHasKey('item_id', $item);
        $this->assertArrayHasKey('data', $item);
    }
}
```

> L'essentiel à retenir : Déclarer un exportateur via le filtre officiel ; Vérifier la structure du tableau retourné ; Couvrir la pagination des gros volumes

Ce test aurait immédiatement échoué le jour du renommage de la méthode, avant même que le client ne s'en aperçoive.

## Couvrir la pagination sur un gros volume

WordPress appelle l'exportateur page par page tant que `done` vaut `false`. Une extension qui traite mal la pagination — en renvoyant toujours la première page, par exemple — produit un export incomplet sans lever la moindre erreur visible. Il faut donc créer un volume de données dépassant la taille d'une page (souvent 500 lignes côté cœur, mais l'extension peut définir sa propre limite) et vérifier que plusieurs appels successifs couvrent bien l'ensemble sans doublon :

```
public function test_export_pagine_sans_doublon(): void {
    for ($i = 0; $i < 12; $i++) {
        $id = $this->factory()->post->create(['post_type' => 'commande_billet']);
        update_post_meta($id, '_email_client', 'gros-client@example.test');
    }

    $vus = [];
    $page = 1;
    do {
        $resultat = billetterie_exporter_donnees('gros-client@example.test', $page);
        foreach ($resultat['data'] as $item) {
            $vus[] = $item['item_id'];
        }
        $page++;
    } while (!$resultat['done']);

    $this->assertCount(12, array_unique($vus));
}
```

## Vérifier aussi l'absence de données pour un e-mail inconnu

Un cas souvent oublié : que se passe-t-il quand l'e-mail demandé n'a jamais rien commandé ? L'exportateur doit renvoyer un tableau `data` vide et `done` à `true`, jamais une erreur PHP ni un `null` qui ferait planter l'outil natif de traitement des demandes RGPD :

- Tester explicitement un e-mail sans aucune correspondance en base.
- Vérifier que le type de retour reste un tableau bien formé, même vide.
- S'assurer qu'aucune notice PHP n'est émise (utile depuis le passage à PHP 8, plus strict sur les accès aux tableaux).

> Sur nos projets, l'exportateur RGPD est traité comme une fonctionnalité de production à part entière, avec sa propre suite de tests — pas comme une case à cocher ajoutée en fin de développement.

## Pour aller plus loin

Un test unitaire ne remplace pas une vérification manuelle occasionnelle depuis **Outils → Exporter les données personnelles** dans l'administration, qui reste la meilleure façon de contrôler le rendu final du fichier envoyé à l'utilisateur. Mais automatiser la vérification du contrat de retour évite la régression la plus fréquente : un callback qui existe dans le code sans jamais être réellement branché au bon filtre. Ce point précis, une fois testé, élimine la classe d'incidents la plus embarrassante en matière de conformité — celle où l'on répond « nous exportons vos données » sans que ce soit vrai.
