Configurer des workflows avec State Machine pour Drupal Commerce 2.x

Auteur(s) de l'article

Ce blogpost répond à la problématique Comment attacher un Workflow "State Machine" à une entité Produit (Commerce Product) dans Drupal Commerce 2.x.
Comme nous l'avons vu dans le billet précédent The good, the bad and the ugly - Workflow & State Machine with Drupal 8, il existe plusieurs moyens pour résoudre cette problématique.
Cependant, étant un fervent défenseur de l'approche développeur dans Drupal 8, je vais naturellement consacrer ce papier à la création de workflows de publication via le module "State Machine".
Cet article va vous guider pas à pas dans le processus nécessaire à la création de Workflow - par le code.
Truth can only be found in one place: the code.

Robert C. Martin

Clean Code: A Handbook of Agile Software

Trêve de bavardages, voici 2 différentes fonctionnalités générales couvertes pas ce post:
  • L'état de publication des produits est géré par une State Machine.
    En somme, le champ de publication n'est plus accessible "en direct", les différents états du workflow influencent l'état de publication.
  • Réagir aux transitions des états de publication afin d'appliquer des Business Logics sur celles-ci.
    Par exemple: envoyer un e-mail à l'auteur d'un produit lorsque celui-ci est prêt pour une mise en ligne.
Ce billet se base sur la version 2.11.x de Drupal Commerce 2.x et se repose également sur la version 8.x-1.0-beta3 du module State Machine.
Gif : Let the game begin

Getting Started

L'utilisation du module State Machine et l'implémentation d'une machine d'état sont plutôt simples:
  • Les workflows doivent être définis dans un module personnalisé à l'aide de fichier YAML.
    Ces fichiers contiennent les différents états (en orange sur le schéma ci-dessous) ainsi que les différentes transitions entre les états (en bleu sur le schéma ci-dessous).
  • Le module State Machine expose un nouveau type de champ State.
    Il est alors possible d'ajouter autant de champs que nécessaire, et ce pour n'importe quel type d'entités.
    On peut ensuite définir quels sont les workflows qui s'appliquent pour chaque champ - indépendamment les uns des autres.
  • Enfin, à chaque changement d'état, un événement est propagé par Drupal.
    Il est donc maintenant possible d'agir et de réagir à ces événements et d'effectuer autant d'actions que nécessaire pour répondre à votre propre Business Logic.
À noter, qu'il vous sera nécessaire d'appliquer ce patch Drupal 8 afin d'utiliser l'ensemble des nouveaux événements génériques en pre et post transitions.

Création des workflows

Contrairement aux modules Content Moderation et Workflows, les workflows de State Machine nécessitent d'être déclarés manuellement à l'aide de fichier YAML.
Avant de commencer à créer votre fichier de définition YAML, je vous conseille fortement de créer une conception de votre Workflow.
Voici celui que nous allons utiliser pour la réalisation de cet article.
Image d'un schéma de state machine
Nous allons donc créer un nouveau module que nous nommerons "my_workflow". Ce module utilise la structure de base suivante:
Les fichiers qui vont nous intéresser sont les suivants:
  • my_workflow.workflow_groups.yml, permet la création des groupes de workflow;
  • my_workflow.workflows.yml, déclare et défini l'ensemble des workflows du module;
  • Et finalement WorkflowTransitionEventSubscriber.php, dans lequel nous allons réagir aux différents états et transitions de notre workflow.
Un workflow de State Machine doit obligatoirement faire partie d'un Workflow Group.
Nous allons donc créer ce groupe (product_publication) qui sera déclaré dans le fichier my_workflow.workflow_groups.yml.
Nous pouvons maintenant déclarer et définir toutes les transitions de ce nouveau workflow directement dans le fichier my_workflow.workflows.yml
Comme le démontre cet exemple, il vous faut déclarer un ensemble d'états - sous la clé states - ainsi qu'un ensemble de transitions - sous la clé transitions.
Une rapide comparaison avec le schéma illustré plus haut vous permettra de mieux comprendre la déclaration des états et des transitions.
Vous aurez remarqué que j'ai volontairement ajouté une clé published dans certains états.
Celles-ci va me permettre de mettre en place une Business Logic lors d'une transition d'état en se fiant à cette propriété pour changer l'état de publication d'un produit.
Nous aurons alors uniquement besoin de vérifier la présence de cette propriété ainsi que de sa valeur, plutôt que d'utiliser le nom de la transition afin de gérer les états de publication/dépublication.
  • published: true, publier le produit;
  • published: false, dépublier un contenu.
Vous l'aurez compris, vous pouvez ajouter autant de propriétés que nécessaire, mais il vous faudra coder les différents comportements dans un EventSubscriber, ce que nous verrons plus loin dans ce billet.
Vous pouvez à présent activer votre module et configurer les nouveaux champs State dans vos types de produits.

Configurations des champs State Machine

Je sais cliquer, merci ! Maintenant, je veux savoir comment réagir aux changements d'état d'un champ State.
  1. Afin d'activer Workflow, il vous suffit d'ajouter le nouveau type de champ State.
    Dans l'exemple ci-dessous, nous avons ajouté un champ "Publication status” à notre type de produit.
Image d'un select
  1. Ensuite, nous pouvons configurer ce champ afin d'utiliser les workflows disponibles - voir les fichiers my_workflow.workflow_groups.yml et my_workflow.workflows.yml.
Capture d'écran du backend de Drupal
Attention, si votre workflow n'apparait pas, vérifiez la propriété entity_type: de votre Workflow Group.
  1. Enfin, nous pouvons configurer notre Form Display afin d'afficher notre champ State et cacher le bouton "Publié" par défaut.
    Puisque nous allons gérer - dans nos Buisness Logic - les états de publications, les boutons d'actions par défaut ne sont plus nécessaires.
Capture d'écran du backend de Drupal

Réagir aux transitions et implémenter une Business Logic

Une fois les champs State créés et attachés à nos workflows, ils ne vous restent plus qu'à réagir aux Transitions afin d'y effectuer des opérations.
Chaque champ State va propager un ensemble d'événements durant une transition:
  • Un événement de "pre-transiton";
  • Un événement de "post-transition".
Les identifiants de ces événements suivent le pattern suivant:
Grâce au patch mentionné en introduction, des événements plus génériques sont également propagés, ceux-ci suivent le pattern suivant:
Afin de réagir à ces événements, nous allons devoir implémenter un EventSubscriber. La déclaration de ce service se trouve dans le fichier my_workflow.services.yml.
Ce fichier déclare les services suivants:
  • WorkflowTransitionEventSubscriber.php, ce service contiendra l'ensemble de notre Business Logic afin de publier ou de dépublier un produit;
  • WorkflowHelper.php quant à celui-ci, il contiendra uniquement des méthodes utilitaires concernant la gestion des workflows.
Découvrons maintenant WorkflowTransitionEventSubscriber.php
Dans ce fichier, nous nous attachons à l'événement state_machine.pre_transition via la méthode getSubscribedEvents() et nous lui demandons d'appeler la méthode handleAction() qui nous permet de gérer l'état de publication d'un produit.
Nous faisons donc appel à notre propriété personnalisée published au travers de WorkflowHelper::isWorkflowStatePublished() que nous avons associé à plusieurs états.
La méthode isWorkflowStatePublished nous permet d'inspecter le plug-in du workflow afin de découvrir les valeurs de la propriété published.
En seulement quelques lignes, il est maintenant très simple d'étendre les réactions aux événements en se basant sur des propriétés de notre workflow, et ce sur tous les types d'entités possibles de Drupal 8.

Sources

Pour les plus curieux d'entre vous, voici quelques sources d'informations complémentaires ayant inspiré la création de cet article.
Patrick Kenny (30 Septembre, 2017). Workflow, Workflows, Workspace, and State Machine - what is the difference?
Voir sur https://drupal.stackexchange.com/questions/2470.../...
Kim Pepper (29 Novembre, 2017). Workflows: A new tool in the toolbox.
Voir sur https://previousnext.com.au/blog/work../
Flocon de toile (30 Novembre, 2017). Set up workflows with State machine on Drupal 8.
Voir sur https://www.flocondetoile.fr/blog/set-workflows-state…
Drupal Commerce. State Machine.
Voir sur https://docs.drupalcommerce.org/commerce2/de../
Ontologia (01 Janvier 2013). Pourquoi les développeurs n'utilisent pas plus de machines à état ?
Voir sur https://linuxfr.org/news/pourquoi../
Symfony. The EventDispatcher Component.
Voir sur https://symfony.com/doc/current../
João Moura (29 Mars 2018). State Machine in Elixir with Machinery.
Voir sur https://medium.com/@joaomdmoura/st../
Kevin Wenger (10 Décembre, 2018). The good, the bad and the ugly - Workflow & State Machine dans Drupal 8
Voir sur https://antistatique.net/fr/nous/bloggons/2018.../...