Drupal Console - la commande generate

Générer un type d'entité ? Drupal console c’est vraiment trop bien

Dans la série d'articles sur la Création d'un module avec Drupal 8, nous avons procédé à l'installation de Drupal Console. Nous avons installé un site Drupal 8. Nous avons généré un module nommé "internal_link" avec Drupal Console. Nous avons fait un petit survol du système d'annotations. Nous pouvons maintenant commencer l'implémentation de notre module à proprement dit.

Comme nous l'avons vu dans le ticket concernant la génération d'un module, Drupal Console est particulièrement efficace pour créer des squelettes de classes afin de nous éviter le travail répétitif. Nous allons en profiter pour l'utiliser dans le but de générer un squelette de type d'entité. Vous allez voir qu'en quelques minutes, nous allons obtenir toutes les classes nécessaires à la mise en place d'un nouveau type d'entité, et celà en répondant simplement à quelques questions.

Génération d'un squelette d'entité

Reprenons le terminal, plaçons-nous à la racine de notre site et démarrons la génération de notre nouveau type d'entité:

MacPro:~ titouille$ cd /Users/titouille/Dev/web/htdocs/sabugo/drupal8
MacPro:drupal8 titouille$ drupal generate:entity:content
 Enter the module name [internal_link]:
 > 
 
 Enter the class of your new content entity [DefaultEntity]:
 > InternalLink
 
 Enter the name of your new content entity [internal_link]:
 > 
 
 Enter the label of your new content entity [Internal link]:
 > 
 
 Enter the base-path for the content entity routes [/admin/structure]:
 > 
 
 Do you want this (content) entity to have bundles (yes/no) [no]:
 > 
 
 Add this to your hook_theme:                                                                                           
 
   $theme['internal_link'] = array(
     'render element' => 'elements',
     'file' => 'internal_link.page.inc',
     'template' => 'internal_link',
   );
 
 
Generated or updated files
 Site path: /Users/titouille/Dev/web/htdocs/sabugo/drupal8
 1 - modules/custom/internal_link/internal_link.permissions.yml
 2 - modules/custom/internal_link/internal_link.links.menu.yml
 3 - modules/custom/internal_link/internal_link.links.task.yml
 4 - modules/custom/internal_link/internal_link.links.action.yml
 5 - modules/custom/internal_link/src/InternalLinkInterface.php
 6 - modules/custom/internal_link/src/InternalLinkAccessControlHandler.php
 7 - modules/custom/internal_link/src/Entity/InternalLink.php
 8 - modules/custom/internal_link/src/InternalLinkHtmlRouteProvider.php
 9 - modules/custom/internal_link/src/Entity/InternalLinkViewsData.php
 10 - modules/custom/internal_link/src/InternalLinkListBuilder.php
 11 - modules/custom/internal_link/src/Form/InternalLinkSettingsForm.php
 12 - modules/custom/internal_link/src/Form/InternalLinkForm.php
 13 - modules/custom/internal_link/src/Form/InternalLinkDeleteForm.php
 14 - modules/custom/internal_link/internal_link.page.inc
 15 - modules/custom/internal_link/templates/internal_link.html.twig
MacPro:drupal8 titouille$ 

Bon, là vous vous rendez compte que ça devient sérieux, hein ? Drupal Console nous a généré toute une série de fichiers à partir des réponses que nous avons apportées à la commande generate:entity:content. Tiens d'ailleurs... pourquoi generate:entity:content et pas generate:entity tout court ? Parce que dans Drupal 8, il y a maintenant 2 types d'entités de base. Les entités de type contenu, qui sont stockées dans la base de données, et les entités de type configuration, qui sont stockées dans le système de configuration. On utilisera généralement les entités de type configuration pour des données qui ne sont pas reproduites trop souvent, tandis que les entités de type contenu, qui sont amenées à être très nombreuses dans le système, pourront être stockées dans des tables qui leurs seront dédiées.

Analyse du code généré

Revenons à nos moutons et regardons plus précisément ce que Drupal Console a généré.

Structure du module

Nous avions 3 fichiers après la génération du module, nous voilà maintenant avec une arborescence relativement complexe: Des fichiers d'entité (dans le répertoire src/Entity), des fichiers de formulaires (dans le répertoire src/Form), quelques fichiers à la racine du répertoire src, un template twig (dans le répertoire templates) et une série de fichiers YAML.

L'incontournable hook_theme

Avant toute chose, nous allons suivre l'indication de Drupal Console: dans le fichier internal_link.module, nous allons rajouter l'implémentation du hook_theme et y inclure le code demandé :

/**
 * Implements hook_theme().
 */
function internal_link_theme() {
  return [
    'internal_link' => [
      'render element' => 'elements',
      'file' => 'internal_link.page.inc',
      'template' => 'internal_link',
    ],
  ];
}

Ce premier ajout effectué, nous allons regarder d'un peu plus près les différents fichiers générés.

Les fichiers YAML

Commençons par les fichiers YAML pour nous donner une idée de leur utilité. Nous avions vu que internal_link.info.yaml correspondait à l'ancien fichier .info de D7. Il décrit le module.

Il y a une série de fichier YAML supplémentaires:

  • internal_link.links.action.yml: ce fichier sert à décrire les boutons d'actions et leur emplacement. Il contient une seule déclaration, qui indique qu'un bouton "Add internal link" doit être placé sur la page de listing de notre nouveau type d'entité;
  • internal_link.links.menu.yml: ce fichier indique les menus qui vont être créés pour notre type d'entité. L'entrée "entity.internal_link.collection" permettra d'accéder à la liste des entités du type internal link, tandis que l'entrée "internal_link.admin.structure.settings" permettra d'accéder à la partie "configuration" de notre type d'entité.;
  • internal_link.links.task.yml: ce fichier indique les "tâches" que nous pourrons effectuer pour notre nouveau type d'entité. Nous allons y trouver différentes entrées correspondantes à des actions : la configuration des onglets (settings_tab), le visuel (canonical, le mode "View"), le formulaire d'édition (edit_form, le mode "Edit"), le formulaire de suppression (delete_form, le mode "Delete");
  • internal_link.permissions.yml: ce fichier décrit les permissions attribuables pour notre nouveau type d'entité. Administer, add, edit, delete, view published, view unpublished;

Nous allons déjà en profiter pour faire quelques menus changements. Dans le fichier internal_link.links.menu.yml, nous allons remplacer la déclaration du menu settings par celle-là: 

internal_link.admin.config.search.settings:
  title: Internal link settings
  description: 'Configure Internal link entities'
  route_name: internal_link.settings
  parent: system.admin_config_search

Afin de placer la partie configuration dans le menu config/search. Nous voyons que les fichiers YAML font maintenant partie intégrante du processus et qu'ils permettent de séparer et de décrire les options de configuration de notre module.

Les classes

Dans le répertoire src, nous trouvons plusieurs classes:

  • InternalLinkAccessControlHandler, qui étend la classe EntityAccessControlHandler. Cette classe défini les accès suivant les permissions décrites dans internal_link.permissions.yml.
  • InternalLinkHtmlRouteProvider, qui étend la classe AdminHtmlRouteProvider. Cette classe décrit les routes possibles. Nous pouvons d'ores et déjà modifier la dernière fonction getSettingsFromRoute pour indiquer la bonne route: $route = new Route("/admin/config/search/{$entity_type->id()}/settings");
  • InternalLinkInterface est une interface pour notre type d'entité InternalLink. L'interface permet d'indiquer les méthodes publiques qui devront obligatoirement être implémentées dans les classes qui l'implémente;
  • InternalLinkListBuilder, qui étend la classe EntityListBuilder. Cette classe implémente l'affichage de la liste d'entités de type internal_link. Nous verrons par la suite comment personnaliser cette liste pour y afficher les informations les plus intéressantes sur nos entités;

Dans le répertoire src/Entity, nous trouvons 2 classes:

  • InternalLink, qui étend ContentEntityBase et implémente l'interface InternalLinkInterface. C'est notre nouveau type d'entité "internal_link". C'est ici que nous pourrons coder les parties intéressantes de notre type d'entité, tels que les getters et autres fonctions utiles;
  • InternalLinkViewsData, qui étend EntityViewData. Cette classe permet de définir la structure de notre entité, qui pourra ensuite être pleinement utilisée dans le système de vue (views) dorénavant intégré au noyau Drupal;

Enfin, le répertoire src/Form contient 3 classes:

  • InternalLinkDeleteForm, qui étend ContentEntityDeleteForm. Cette classe permet de surdéfinir et d'ajouter des fonctionnalités lors de la suppression d'une entité de type internal_link;
  • InternalLinkForm, qui étend ContentEntityForm. Cette classe permet de surdéfinir et d'ajouter des fonctionnalités lors de l'ajout ou de l'édition d'une entité de type internal_link;
  • InternalLinkSettingsForm, qui étend FormBase. Cette classe permet de surdéfinir et d'ajouter des fonctionnalités au formulaire de configuration du type d'entité internal_link;

Nous ferons l'impasse sur les templates, celui ayant été généré étant très simple.

Conclusion

Nous voyons que:

  1. Drupal Console a été particulièrement utile pour générer tous les squelettes de classes et fichier YAML. Sans son utilisation, nous aurions pu passer des heures à chercher et plus ou moins comprendre les besoins nécessaires à la création d'un type d'entité;
  2. Avec une logique orientée objet, Drupal 8 décompose grandement l'implémentation en de multiples classes afin de compartimenter son code plutôt que d'avoir un seul fichier .module qui va détenir toutes les fonctions;
  3. La plupart des classes générées "héritent" (mot-clé extends) d'autres classes parent qui s'occupent d'implémenter les fonctionnalités de base, pour nous permettre de nous concentrer sur la partie importante de notre code;

Maintenant que nous avons notre nouveau type d'entité, nous allons pouvoir nous pencher sérieusement sur le squelette de la classe src/Entity/InternalLink.php et y apporter nos propres fonctionnalités.

Ajouter un commentaire

CAPTCHA
Cette question permet de savoir si vous êtes un visiteur ou un robot de soumission de spams