Aller au contenu principal

Surdéfinir le schéma d'un entité avec hook_config_schema_info_alter()

Image
Déclaration d'un hook dans une classe.
Par Thierry V le
Dans la catégorie

Dans la série "les petites astuces bien utiles", il y a celle-ci qui mérite d'être connue...

Le contexte

Dans mes développements autour d'un générateur de site, j'ai mis en place pas mal de petites choses qui me simplifient la vie. Il y a entre autre un système qui compte le nombre d'utilisations d'un style d'image ou d'un style responsive, afin d'éviter qu'un utilisateur supprime un style alors qu'il est encore en utilisation.

J'avais implémenté ce système sur le schéma responsive_image.styles.* avec Drupal 10. A l'époque, j'avais cherché comment faire sans trouver de solution adéquate, à part celle de redéclarer le schéma dans mon propre module qui devait l'altérer. J'avais donc redéclaré un fichier responsive_image.schema.yml dans mon propre module (oui, je sais, c'est bad), j'y avais collé la définition de responsive_image.styles.* et j'y avait également ajouté une clé _cm_import afin que le schéma corresponde bien aux données sauvegardées dans la base de données. 

Le problème

Actuellement, je travaille sur une refonte d'un de mes modules. Ce dernier génère certains styles adaptatifs (responsive style) et m'affichait un joli message d'erreur à propos du schéma. Le truc, c'est qu'entre les version 10 et 11 de Drupal, le schéma de responsive_image.styles.* a changé. Et là, j'ai commencé à chercher pourquoi ça m'affichait ce message. A ce moment-là, je ne me souvenais plus que j'avais surdéfini le schéma dans mon propre module. J'ai donc passé un peu de temps à faire des tests et à tenter de comprendre. J'ai fini par me souvenir de cette surdéfinition, et je me suis mis en quête d'une façon plus "drupalienne" de faire ça. Écraser un schéma par une version personnalisée, on voit que ça a ses limites. Pour peu que le schéma soit modifié dans le module original, on va se retrouver avec un schéma obsolète dans son module et on risque de ne pas le remarquer tout de suite.

La solution

Elle est dans le titre : hook_config_schema_info_alter. Ce hook permet d'altérer n'importe quel schéma sans devoir réellement y toucher. Dans mon cas, c'est exactement le besoin : ajouter une ou plusieurs entrées au schéma d'un autre module sans toucher au schéma, et sans l'écraser.

Au final, ça se révèle assez simple : 

<?php

namespace Drupal\my_module\Hook;

use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\Hook\Order\Order;

/**
 * Config hook implementations for site_generator.
 */
class ConfigHooks {

  /**
   * Implements hook_config_schema_info_alter().
   *
   * Add _cm_import key into :
   *
   * - responsive_image.styles.*
   * - image.style.*
   *
   * schema definitions.
   */
  #[Hook('config_schema_info_alter', order: Order::Last)]
  public function configSchemaInfoAlter(&$definitions): void {

    $schemas = [
      'responsive_image.styles.*',
      'image.style.*',
    ];
    foreach ($schemas as $schema) {
      if (isset($definitions[$schema])) {
        $definitions[$schema]['mapping']['_cm_import'] = [
          'type' => 'mapping',
          'label' => 'CM Import',
          'mapping' => [
            'usage' => [
              'type' => 'integer',
              'label' => 'Usage count',
            ],
          ],
        ];
      }
    }

  }

}

Je déclare un fichier src/Hook/ConfigHooks.php dans lequel je vais mettre mon hook. J'itère sur les clés de schéma à modifier, à savoir : 

  • responsive_image.styles.*
  • image.style.*

Et je rajoute la nouvelle entrée _cm_import avec la définition qui va bien. That's it !

Simple, rapide, efficace.

Conclusion

Il faut dès fois aller chercher assez loin dans les méandres du code, mais il existe en général toujours une solution "propre" pour implémenter une fonctionnalité avec Drupal. Le tout étant de la trouver.