Dans le cadre de la liste d'articles sur la Création d'un module avec Drupal 8, je parlerai aujourd'hui du système d'annotations intégré dans Drupal 8. Lors de mes premiers tests sur l'implémentation de "champs" (FieldType, FieldWidget, FieldFormatter), j'avais déjà eu un bref aperçu de cette nouveauté introduite dans le noyau D8.
Je ne vais pas trop m'étaler sur le sujet, mais il est nécessaire d'en parler pour pouvoir ensuite travailler. Les annotations de classes sont un nouveau système intégré dans D8, qui permet de déclarer certaines informations sous la forme de commentaires. Néanmoins, ce ne sont pas de simples commentaires. Un système de détection intégré au noyau s'occupe de parser ces annotations et de les utiliser dans le cadre du développement. Drupal n'est pas le premier à implémenter cette logique. D'autres frameworks les utilisent depuis de nombreuses années. J'ai par exemple souvenir du même type de système intégré à Java Hibernate pour la déclaration de services web lorsque je travaillais avec Flex et LCDS.
Il y a eu de grands débats à propos des annotations, oposant les défenseurs et les adversaires de cette méthode de déclaration. Les annotations ont finalement été adoptées au sein de Drupal pour la déclaration de "plugin".
Pour faire simple: lorsqu'on déclare un plugin, qu'il soit de type Formatter, Widget, Block ou autre, nous devons utiliser un bloc de commentaire de type annotation, qui indique les propriétés du plugin. Ces métadonnées décrivent le comportement du plugin, les propriétés ainsi que les classes rattachées. Chaque type de plugin possède ses propres métadonnées, il est donc important de les utiliser de manière correcte.
Je n'ai pas encore trop poussé les investigations à ce propos, mais il est certainement possible de déclarer son propre système d'annotations afin d'utiliser des métadonnées descriptives pour un type de plugin que nous pourrions inventer. Il suffit de regarder le module Block du noyau (lib/Drupal/Core/Block) pour voir qu'il y a un répertoire "Annotation" qui contient une classe "Block.php" étendant "Plugin". Si nous regardons ensuite le module de contribution "Examples", il contient un module "block_example" qui démontre l'implémentation de blocs. Ce dernier contient plusieurs exemple (dans src/Plugin/Block) et chacun utilise des métadonnées que nous retrouvons dans "Block.php".
Voici quelques petits exemples d'annotations issus du module "Example" :
Déclaration d'un plugin de block (examples/block_example/src/Plugin/Block/ExampleEmptyBlock.php):
/** * Provides a 'Example: empty block' block. * * @Block( * id = "example_empty", * admin_label = @Translation("Example: empty block") * ) */ class ExampleEmptyBlock extends BlockBase { }
Déclaration d'une entité de type "configuration" (examples/config_entity_example/src/Entity/Robot.php):
/** * Defines the robot entity. * * @ConfigEntityType( * id = "robot", * label = @Translation("Robot"), * admin_permission = "administer robots", * handlers = { * "access" = "Drupal\config_entity_example\RobotAccessController", * "list_builder" = "Drupal\config_entity_example\Controller\RobotListBuilder", * "form" = { * "add" = "Drupal\config_entity_example\Form\RobotAddForm", * "edit" = "Drupal\config_entity_example\Form\RobotEditForm", * "delete" = "Drupal\config_entity_example\Form\RobotDeleteForm" * } * }, * entity_keys = { * "id" = "id", * "label" = "label" * }, * links = { * "edit-form" = "/examples/config_entity_example/manage/{robot}", * "delete-form" = "/examples/config_entity_example/manage/{robot}/delete" * } * ) */ class Robot extends ConfigEntityBase { }
Déclaration d'un type de champ (examples/field_example/src/Plugin/Field/FieldType/RgbItem.php):
/** * Plugin implementation of the 'field_example_rgb' field type. * * @FieldType( * id = "field_example_rgb", * label = @Translation("Example Color RGB"), * module = "field_example", * description = @Translation("Demonstrates a field composed of an RGB color."), * default_widget = "field_example_text", * default_formatter = "field_example_simple_text" * ) */ class RgbItem extends FieldItemBase { }
Chaque élément pouvant utiliser des annotations propose un set de métadonnées qui décrit l'élément, et cette description va permettre à Drupal de détecter à quoi la classe va servir afin de l'intégrer dans le système.
Comme vous l'avez certainement compris, les annotations dans D8 sont importantes et ne pas en parler aurait été une erreur. Vous pourrez trouver quelques liens à la fin de l'article pour mieux comprendre leur utilisation, bonne lecture.