In Symfony 4.3 we improved the Workflow component with lots of major and minor features. This blog post summarizes the most important ones.
Added a context to Workflow::apply()
When applying a transition, now it's possible to pass a custom $context
(e.g. the user who performed the transition or the current date):
1 2 3
$workflow->apply($article, $request->request->get('transition'), [
'time' => date('y-m-d H:i:s'),
]);
Before using this feature, update your entity or any other object supported by the workflow as follows:
1 2 3 4
class Article
{
- public function setMarking($marking)
+ public function setMarking($marking, $context = [])
Then, update the configuration of the workflow to use the MethodMarkingStore
:
1 2 3 4 5 6 7
framework:
workflows:
article:
type: workflow
marking_store:
- type: multiple_state
+ type: method
Allow to modify the context in a listener
Passing the context on every call to ->apply()
could be annoying and will
lead to duplicated code.
Now you can create a listener that does that for you:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
class TransitionEventSubscriber implements EventSubscriberInterface
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function onWorkflowArticleTransition(TransitionEvent $event)
{
$context = $event->getContext();
$token = $this->tokenStorage->getToken();
if ($token instanceof TokenInterface) {
$user = $token->getUser();
if ($user instanceof UserInterface) {
$context['user'] = $user->getUsername();
}
}
$event->setContext($context);
}
public static function getSubscribedEvents()
{
return [
TransitionEvent::class => 'onWorkflowArticleTransition',
];
}
}
Added color to dumped workflow
It's now possible to configure how a workflow will be rendered thanks to the
dump_style
metadata config option:
1 2 3 4 5 6 7 8 9 10
transitions:
submit:
from: start
to: travis
metadata:
title: transition submit title
dump_style:
label: 'My custom label'
arrow_color: '#0088FF'
label_color: 'Red'
And this is how the custom style would look like:
Allow to configure many initial places
Unlike state machines, when using a workflow it's possible to have a subject in many places. That's why the component now allows to configure multiple initial places:
1 2 3 4 5
workflows:
article:
type: workflow
initial_marking: [foo, bar]
places: [foo, bar, a, b, c, d]
Simpler configuration
As mentioned above, subjects can only be in one place in state machines but they can be in one or more states when using a workflow. However, the initial design of the Workflow component allowed to use a workflow with a Single State Marking Store. This wasn't the best decision and it added some unnecessary complexity.
Starting from Symfony 4.3, if your subject can be only in one state, use a state
machine. In that case, the property (called marking
by default) will be a
string. If the subject can be in many places, use a workflow. In that case, the
property will be an array.
Thanks to this simplification, we've improved the DX (developer experience):
1 2 3 4 5 6 7 8 9 10 11 12
framework:
workflows:
article:
type: workflow
marking_store:
type: method # This will be the default value in Symfony 5.0
property: marking # This is the default value, it could be omitted
task:
type: state_machine
marking_store:
type: method # This will be the default value in Symfony 5.0
property: state
Added workflow_transition_blockers()
Twig function
In Symfony 4.1 we added a feature to know why a transition is blocked.
In Symfony 4.3 we're adding a Twig function to build the blocker list:
1 2 3 4 5 6 7 8 9 10 11 12
<h2>Publication was blocked because:</h2>
<ul>
{% for blocker in workflow_transition_blockers(article, 'publish') %}
<li>
{{ blocker.message }}
{# Display the guard expression #}
{% if blocker.parameters.expression is defined %}
<code>{{ blocker.parameters.expression }}</code>
{% endif %}
</li>
{% endfor %}
<ul>
Wow! So many improvements! 👍
Very appreciated :)
woww terrible !
GG ! Can't wait to use these improvments :)
I love workflow so much! This is a nice improvement! :)
Thanks for workflow improvements! I'll use these in my project.