Skip to content

Instantly share code, notes, and snippets.

@WengerK
Last active December 14, 2018 09:01
Show Gist options
  • Save WengerK/4f9e03c6019f45b956a50bf673f3cf14 to your computer and use it in GitHub Desktop.
Save WengerK/4f9e03c6019f45b956a50bf673f3cf14 to your computer and use it in GitHub Desktop.
Article Ressources - Set up workflows with State Machine on Drupal Commerce 2.x

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

This is the Gist repository for my article Set up workflows with State Machine on Drupal Commerce 2.x.

Be aware that this article has been wrote for the Blog of Antistatique — Web Agency in Lausanne, Switzerland. A place where I work as Full Stack Web Developer.

Feel free to read it the full article on Medium or check it out on Antistatique.

Content of this Gist :

  • WorkflowHelper.php : Contains helper methods to retrieve workflow related data from entities.
  • WorkflowTransitionEventSubscriber.php : Event subscriber to handle actions on workflow-enabled entities.
  • my_workflow.services.yml
  • my_workflow.workflow_groups.yml
  • my_workflow.workflows.yml : Workflow(s) définiation used by State Machine module.
services:
my_workflow.workflow.helper:
class: Drupal\my_workflow\WorkflowHelper
my_workflow.workflow_transition:
class: Drupal\my_workflow\EventSubscriber\WorkflowTransitionEventSubscriber
arguments: ['@my_workflow.workflow.helper']
tags:
- { name: event_subscriber }
product_publication:
label: Publication
entity_type: commerce_product
product_publication_default:
id: product_publication_default
label: Commerce product publication
group: product_publication
states:
draft:
label: Draft
published: false
imported:
label: Imported
published: false
needs_update:
label: Needs update
published: false
validated:
label: Published
published: true
archived:
label: Archived
published: false
transitions:
save_as_draft:
label: Save as draft
from: [draft, imported]
to: draft
validate:
label: Publish
from: [needs_update]
to: validated
needs_update:
label: Request changes
from: [draft, imported, validated]
to: needs_update
unarchive:
label: Unarchive
from: [archived]
to: draft
archive:
label: Archive
from: [draft, imported, needs_update, validated]
to: archived
├── my_workflow.info.yml   
├── my_workflow.services.yml   
├── my_workflow.workflow_groups.yml   
├── my_workflow.workflows.yml   
├── src   
│   ├── EventSubscriber   
│   │   └── WorkflowTransitionEventSubscriber.php   
│   ├── WorkflowHelper.php
[group_id].[transition_id].[pre_transition|post_transition]
state_machine.[pre_transition|post_transition]
<?php
namespace Drupal\my_workflow;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\state_machine\Plugin\Workflow\WorkflowInterface;
/**
* Contains helper methods to retrieve workflow related data from entities.
*/
class WorkflowHelper {
/**
* Checks if a state is set as published in a certain workflow.
*
* @param string $state_id
* The ID of the state to check.
* @param \Drupal\state_machine\Plugin\Workflow\WorkflowInterface $workflow
* The workflow the state belongs to.
*
* @return bool|null
* TRUE|FALSE if the state is set in the workflow, NULL otherwise.
*
* @throwns \InvalidArgumentException
* Thrown when the workflow is not plugin based, because this is required to
* retrieve the publication state from the workflow states.
*/
public function isWorkflowStatePublished($state_id, WorkflowInterface $workflow) {
// We rely on being able to inspect the plugin definition. Throw an error if
// this is not the case.
if (!$workflow instanceof PluginInspectionInterface) {
$label = $workflow->getLabel();
throw new \InvalidArgumentException("The '$label' workflow is not plugin based.");
}
// Retrieve the raw plugin definition, as all additional plugin settings
// are stored there.
$raw_workflow_definition = $workflow->getPluginDefinition();
return $raw_workflow_definition['states'][$state_id]['published'] ?? NULL;
}
}
<?php
namespace Drupal\my_workflow\EventSubscriber;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\my_workflow\WorkflowHelper;
use Drupal\state_machine\Event\WorkflowTransitionEvent;
use Drupal\state_machine\Plugin\Workflow\WorkflowInterface;
use Drupal\state_machine\Plugin\Workflow\WorkflowState;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\commerce_product\Entity\ProductInterface;
/**
* Event subscriber to handle actions on workflow-enabled entities.
*/
class WorkflowTransitionEventSubscriber implements EventSubscriberInterface {
/**
* The workflow helper.
*
* @var \Drupal\my_workflow\WorkflowHelper
*/
protected $workflowHelper;
/**
* Constructs a new WorkflowTransitionEventSubscriber object.
*
* @param \Drupal\my_workflow\WorkflowHelper $workflowHelper
* The workflow helper.
*/
public function __construct(WorkflowHelper $workflowHelper) {
$this->workflowHelper = $workflowHelper;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
'state_machine.pre_transition' => [
'handleAction', -180,
],
];
}
/**
* Handle action based on the workflow.
*
* @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event
* The state change event.
*/
public function handleAction(WorkflowTransitionEvent $event) {
$entity = $event->getEntity();
// Don't handle action on non-commerce_product or non-publishable entity.
if (!$entity instanceof ProductInterface || !$entity instanceof EntityPublishedInterface) {
return;
}
// Verify if the new state is marked as published state.
$is_published_state = $this->isPublishedState($event->getToState(), $event->getWorkflow());
if ($is_published_state === TRUE) {
$entity->setPublished();
}
elseif ($is_published_state === FALSE) {
$entity->setUnpublished();
}
}
/**
* Checks if a state is set as published in a certain workflow.
*
* @param \Drupal\state_machine\Plugin\Workflow\WorkflowState $state
* The state to check.
* @param \Drupal\state_machine\Plugin\Workflow\WorkflowInterface $workflow
* The workflow the state belongs to.
*
* @return bool
* TRUE if the state is set as published in the workflow, FALSE otherwise.
*/
protected function isPublishedState(WorkflowState $state, WorkflowInterface $workflow) {
return $this->workflowHelper->isWorkflowStatePublished($state->getId(), $workflow);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment