Set up workflows with State Machine on Drupal Commerce 2.x

Kevin

Kevin


Dec 14th 2018 in code explication

This blog post addresses the issue of How to attach a State Machine Workflow to a Commerce Product in Drupal Commerce 2.x.

As we demonstrate in this previous post, it exists several ways to solve this problem.
However, as a strong advocate of the developer approach in Drupal 8, I will, of course, devote this paper to creating publishing workflows via the "State Machine module".

This article will guide you step by step in the process of code driven Workflow creation.

Truth can only be found in one place: the code.
- Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship

Enough history, here is 2 different features covered by this post:

  • The release status of products is managed by a State Machine.
    To summarise, the Publish button is no longer accessible, the different states of the workflow influence the state of publication.

  • React to transitions of the publication states in order to apply Business Logics to them.
    For example: send an e-mail to the author of a product when it is ready for upload.

This post is based on version 2.11.x of Drupal Commerce 2.x and relies on the 8.x-1.0-beta3 of State Machine module.

Getting Started

The use of the State Machine module and the implementation of a state machine are simple:

  • Workflows must be defined in a custom module using YAML file.
    These files contain the different states (in orange on the diagram below) as well as the different transitions between the states (in blue on the same diagram).

  • The State Machine module exposes a new State field type.
    You will be able to add as many fields as needed for any entity type.
    Then we can define which workflows apply for each field independently of each other.

  • Finally, on each state change, an event is propagated by Drupal.
    It is now possible to react to these events and perform as many actions as necessary to meet your own business logic.

Please note that you will need to apply this Drupal 8 patch to use new generic events pre and post transitions.

Workflows creation

Unlike Content Moderation and Workflows modules, State Machine workflows need to be manually declared using YAML file.

Before starting to create your YAML definition file, I advise you to design your Workflow. Here is the one we will use for this article.

We will create a new module "my_workflow". This module uses the following skeleton:

The files that will interest us are:

  • my_workflow.workflow_groups.yml, allows the creation of workflow groups;

  • my_workflow.workflows.yml, declares and defines all the workflows of the module;

  • WorkflowTransitionEventSubscriber.php, in which we will react to different states and transitions of our workflow.

A workflow of State Machine must be part of a Workflow Group.
We will create this group (product_publication) which should be declared in the my_workflow.workflow_groups.yml file.

We can now declare and define all transitions of this new workflow directly in the my_workflow.workflows.yml file.

You need to declare a set of states - under the states key - as well as a set of transitions - under thetransitions key.
A quick comparison with the diagram shown above will help you to understand statements and transitions.

You may notice that I have voluntarily added a key published in some states.
These will allow me to set up a Business Logic during a state transition by relying on this property to change the publication status of a product.
We will then only need to check the presence of this property as well as its value, instead of using the name of the transition in order to manage the publish/unpublish status.

  • published: true, publish the product;
  • published: false, unpublish it.

As you can see, you can add as many properties as you need, but you will need to code the different behaviors in an EventSubscriber, which we'll see later in this post.

You can now activate your module and configure the new State` fields in your product types.

State Machine Field Configurations

1. To enable Workflow, simply add the new State field type.
In the example below, we added a "Publication status" field to our product type.

2. Then we can configure this field to use the available workflows - see the files my_workflow.workflow_groups.yml and my_workflow.workflows.yml.

Be careful, if your workflow does not appear, check the entity_type: property of your Workflow Group.

3. Finally, we can configure our Form Display to show our State field and hide the default 'Published' button.
As we manage in our Buisness Logic the publication states, the default action buttons is no longer needed.

React to transitions and implement a Business Logic

Once the State fields created and attached to our workflows, all you have to do is to react to Transitions in order to perform operations.
Each State field will propagate a set of events during a transition:

  • a "pre-transiton" event;
  • a "post-transition" event.

The identifiers of these events follow this pattern:

Thanks to the patch mentioned in the introduction, more generic events are also propagated, using this pattern:

In order to respond to these events, we will need to implement an EventSubscriber. The declaration for this service is in the my_workflow.services.yml file.

This file declares the following services:

  • WorkflowTransitionEventSubscriber.php, this service will contain all of our Business Logic in order to publish or unpublish a product;
  • WorkflowHelper.php this one will contain only utilitarian methods concerning the workflow management.

Let's take a look at WorkflowTransitionEventSubscriber.php

In this file, we subscribe to the event state_machine.pre_transition via the method getSubscribedEvents() and we call the handleAction() method. In this method we manage the release status of products.
Then, we use our published property via WorkflowHelper::isWorkflowStatePublished() which we previously associated with multiple states.
The isWorkflowStatePublished method allows us to inspect the workflow plug-in to discover the values of our published property.

In just a few lines, we can now implement any necessary reaction based on a transition and a particular status, let's remember, on any entity of Drupal 8.


Sources

For the most curious of you, here are some sources of additional information that inspired the creation of this article.

Patrick Kenny (30 Septembre, 2017). Workflow, Workflows, Workspace, and State Machine - what is the difference?
See on https://drupal.stackexchange.com/questions/2470.../...

Kim Pepper (29 Novembre, 2017). Workflows: A new tool in the toolbox.
See on https://previousnext.com.au/blog/work../

Flocon de toile (30 Novembre, 2017). Set up workflows with State machine on Drupal 8.
See on https://flocondetoile.fr/blog/set../

Drupal Commerce. State Machine.
See on https://docs.drupalcommerce.org/commerce2/de../

Ontologia (01 Janvier 2013). Pourquoi les développeurs n'utilisent pas plus de machines à état ?
See on https://linuxfr.org/news/pourquoi../

Symfony. The EventDispatcher Component.
See on https://symfony.com/doc/current../

João Moura (29 Mars 2018). State Machine in Elixir with Machinery.
See on https://medium.com/@joaomdmoura/st../

Kevin Wenger (10 Décembre, 2018). The good, the bad and the ugly - Workflow & State Machine dans Drupal 8
See on https://antistatique.net/fr/nous/bloggons/2018.../...