Skip to content

Commit 07ada7f

Browse files
noniagriconomiejaviereguiluz
authored andcommitted
[Workflow] Guard documentation
1 parent f866de7 commit 07ada7f

File tree

1 file changed

+65
-20
lines changed

1 file changed

+65
-20
lines changed

workflow/usage.rst

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ A set of places and transitions creates a **definition**. A workflow needs
1414
a ``Definition`` and a way to write the states to the objects (i.e. an
1515
instance of a :class:`Symfony\\Component\\Workflow\\MarkingStore\\MarkingStoreInterface`.)
1616

17-
Consider the following example for a blog post. A post can have places:
18-
'draft', 'review', 'rejected', 'published'. You can define the workflow
17+
Consider the following example for a blog post. A post can have these places:
18+
``draft``, ``reviewed``, ``rejected``, ``published``. You can define the workflow
1919
like this:
2020

2121
.. configuration-block::
@@ -38,18 +38,18 @@ like this:
3838
initial_place: draft
3939
places:
4040
- draft
41-
- review
41+
- reviewed
4242
- rejected
4343
- published
4444
transitions:
4545
to_review:
4646
from: draft
47-
to: review
47+
to: reviewed
4848
publish:
49-
from: review
49+
from: reviewed
5050
to: published
5151
reject:
52-
from: review
52+
from: reviewed
5353
to: rejected
5454
5555
.. code-block:: xml
@@ -74,24 +74,24 @@ like this:
7474
<framework:support>AppBundle\Entity\BlogPost</framework:support>
7575
7676
<framework:place>draft</framework:place>
77-
<framework:place>review</framework:place>
77+
<framework:place>reviewed</framework:place>
7878
<framework:place>rejected</framework:place>
7979
<framework:place>published</framework:place>
8080
8181
<framework:transition name="to_review">
8282
<framework:from>draft</framework:from>
8383
84-
<framework:to>review</framework:to>
84+
<framework:to>reviewed</framework:to>
8585
</framework:transition>
8686
8787
<framework:transition name="publish">
88-
<framework:from>review</framework:from>
88+
<framework:from>reviewed</framework:from>
8989
9090
<framework:to>published</framework:to>
9191
</framework:transition>
9292
9393
<framework:transition name="reject">
94-
<framework:from>review</framework:from>
94+
<framework:from>reviewed</framework:from>
9595
9696
<framework:to>rejected</framework:to>
9797
</framework:transition>
@@ -119,21 +119,21 @@ like this:
119119
'supports' => ['AppBundle\Entity\BlogPost'],
120120
'places' => [
121121
'draft',
122-
'review',
122+
'reviewed',
123123
'rejected',
124124
'published',
125125
],
126126
'transitions' => [
127127
'to_review' => [
128128
'from' => 'draft',
129-
'to' => 'review',
129+
'to' => 'reviewed',
130130
],
131131
'publish' => [
132-
'from' => 'review',
132+
'from' => 'reviewed',
133133
'to' => 'published',
134134
],
135135
'reject' => [
136-
'from' => 'review',
136+
'from' => 'reviewed',
137137
'to' => 'rejected',
138138
],
139139
],
@@ -210,7 +210,7 @@ When a state transition is initiated, the events are dispatched in the following
210210
order:
211211

212212
``workflow.guard``
213-
Validate whether the transition is allowed at all (:ref:`see below <workflow-usage-guard-events>`).
213+
Validate whether the transition is blocked or not (:ref:`see below <workflow-usage-guard-events>` and :ref:`using guards <workflow-usage-using-guards>`).
214214

215215
The three events being dispatched are:
216216

@@ -322,14 +322,14 @@ Guard Events
322322
There are a special kind of events called "Guard events". Their event listeners
323323
are invoked every time a call to ``Workflow::can``, ``Workflow::apply`` or
324324
``Workflow::getEnabledTransitions`` is executed. With the guard events you may
325-
add custom logic to decide what transitions are valid or not. Here is a list
325+
add custom logic to decide which transitions should be blocked or not. Here is a list
326326
of the guard event names.
327327

328328
* ``workflow.guard``
329329
* ``workflow.[workflow name].guard``
330330
* ``workflow.[workflow name].guard.[transition name]``
331331

332-
See example to make sure no blog post without title is moved to "review"::
332+
This example stops any blog post being transitioned to "reviewed" if it is missing a title::
333333

334334
use Symfony\Component\Workflow\Event\GuardEvent;
335335
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -343,8 +343,8 @@ See example to make sure no blog post without title is moved to "review"::
343343
$title = $post->title;
344344

345345
if (empty($title)) {
346-
// Posts without title are not allowed
347-
// to perform the transition "to_review"
346+
// Block the transition "to_review"
347+
// if the post has no title
348348
$event->setBlocked(true);
349349
}
350350
}
@@ -388,6 +388,51 @@ This class has two more methods:
388388
:method:`Symfony\\Component\\Workflow\\Event\\GuardEvent::setBlocked`
389389
Sets the blocked value.
390390

391+
.. _workflow-usage-using-guards:
392+
393+
Using Guards
394+
------------
395+
396+
The component has a guard logic to control the execution of your workflow on top of your configuration.
397+
398+
It allows you to execute your custom logic to decide if the transition is blocked or not, before actually
399+
applying this transition.
400+
401+
You have multiple optional ways to use guards in your workflow.
402+
403+
The first way is :ref:`with the guard event <workflow-usage-guard-events>`, which allows you to implement
404+
any desired feature.
405+
406+
Another one is via the configuration and its specific entry ``guard`` on a transition.
407+
408+
This ``guard`` entry allows any expression that is valid for the Expression Language component:
409+
410+
.. configuration-block::
411+
412+
.. code-block:: yaml
413+
414+
# config/packages/workflow.yaml
415+
framework:
416+
workflows:
417+
blog_publishing:
418+
# previous configuration
419+
transitions:
420+
to_review:
421+
# the transition is allowed only if the current user has the ROLE_REVIEWER role.
422+
guard: "is_granted('ROLE_REVIEWER')"
423+
from: draft
424+
to: reviewed
425+
publish:
426+
# or "is_anonymous", "is_remember_me", "is_fully_authenticated", "is_granted"
427+
guard: "is_authenticated"
428+
from: reviewed
429+
to: published
430+
reject:
431+
# or any valid expression language with "subject" refering to the post
432+
guard: "has_role("ROLE_ADMIN") and subject.isStatusReviewed()"
433+
from: reviewed
434+
to: rejected
435+
391436
Usage in Twig
392437
-------------
393438

@@ -434,7 +479,7 @@ The following example shows these functions in action:
434479
{% endfor %}
435480

436481
{# Check if the object is in some specific place #}
437-
{% if workflow_has_marked_place(post, 'review') %}
482+
{% if workflow_has_marked_place(post, 'reviewed') %}
438483
<p>This post is ready for review.</p>
439484
{% endif %}
440485

0 commit comments

Comments
 (0)