Skip to content

Commit d86dc6d

Browse files
Workflow Guard documentation
1 parent 3f5a2bb commit d86dc6d

File tree

1 file changed

+61
-19
lines changed

1 file changed

+61
-19
lines changed

workflow/usage.rst

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ a ``Definition`` and a way to write the states to the objects (i.e. an
2828
instance of a :class:`Symfony\\Component\\Workflow\\MarkingStore\\MarkingStoreInterface`.)
2929

3030
Consider the following example for a blog post that can have these places:
31-
``draft``, ``review``, ``rejected``, ``published``. You can define the workflow
31+
``draft``, ``reviewed``, ``rejected``, ``published``. You can define the workflow
3232
like this:
3333

3434
.. configuration-block::
@@ -51,18 +51,18 @@ like this:
5151
initial_place: draft
5252
places:
5353
- draft
54-
- review
54+
- reviewed
5555
- rejected
5656
- published
5757
transitions:
5858
to_review:
5959
from: draft
60-
to: review
60+
to: reviewed
6161
publish:
62-
from: review
62+
from: reviewed
6363
to: published
6464
reject:
65-
from: review
65+
from: reviewed
6666
to: rejected
6767
6868
.. code-block:: xml
@@ -87,24 +87,24 @@ like this:
8787
<framework:support>App\Entity\BlogPost</framework:support>
8888
8989
<framework:place>draft</framework:place>
90-
<framework:place>review</framework:place>
90+
<framework:place>reviewed</framework:place>
9191
<framework:place>rejected</framework:place>
9292
<framework:place>published</framework:place>
9393
9494
<framework:transition name="to_review">
9595
<framework:from>draft</framework:from>
9696
97-
<framework:to>review</framework:to>
97+
<framework:to>reviewed</framework:to>
9898
</framework:transition>
9999
100100
<framework:transition name="publish">
101-
<framework:from>review</framework:from>
101+
<framework:from>reviewed</framework:from>
102102
103103
<framework:to>published</framework:to>
104104
</framework:transition>
105105
106106
<framework:transition name="reject">
107-
<framework:from>review</framework:from>
107+
<framework:from>reviewed</framework:from>
108108
109109
<framework:to>rejected</framework:to>
110110
</framework:transition>
@@ -132,21 +132,21 @@ like this:
132132
'supports' => ['App\Entity\BlogPost'],
133133
'places' => [
134134
'draft',
135-
'review',
135+
'reviewed',
136136
'rejected',
137137
'published',
138138
],
139139
'transitions' => [
140140
'to_review' => [
141141
'from' => 'draft',
142-
'to' => 'review',
142+
'to' => 'reviewed',
143143
],
144144
'publish' => [
145-
'from' => 'review',
145+
'from' => 'reviewed',
146146
'to' => 'published',
147147
],
148148
'reject' => [
149-
'from' => 'review',
149+
'from' => 'reviewed',
150150
'to' => 'rejected',
151151
],
152152
],
@@ -327,7 +327,7 @@ When a state transition is initiated, the events are dispatched in the following
327327
order:
328328

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

332332
The three events being dispatched are:
333333

@@ -439,14 +439,14 @@ Guard Events
439439
There are a special kind of events called "Guard events". Their event listeners
440440
are invoked every time a call to ``Workflow::can``, ``Workflow::apply`` or
441441
``Workflow::getEnabledTransitions`` is executed. With the guard events you may
442-
add custom logic to decide what transitions are valid or not. Here is a list
442+
add custom logic to decide what transitions should be blocked or not. Here is a list
443443
of the guard event names.
444444

445445
* ``workflow.guard``
446446
* ``workflow.[workflow name].guard``
447447
* ``workflow.[workflow name].guard.[transition name]``
448448

449-
See example to make sure no blog post without title is moved to "review"::
449+
See example to make sure no blog post without title is moved to "reviewed"::
450450

451451
use Symfony\Component\Workflow\Event\GuardEvent;
452452
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -460,8 +460,8 @@ See example to make sure no blog post without title is moved to "review"::
460460
$title = $post->title;
461461

462462
if (empty($title)) {
463-
// Posts without title are not allowed
464-
// to perform the transition "to_review"
463+
// Block the transition "to_review"
464+
// if the post has no title defined
465465
$event->setBlocked(true);
466466
}
467467
}
@@ -501,6 +501,48 @@ This class has two more methods:
501501
:method:`Symfony\\Component\\Workflow\\Event\\GuardEvent::setBlocked`
502502
Sets the blocked value.
503503

504+
.. _workflow-usage-using-guards:
505+
506+
Using Guards
507+
------------
508+
509+
The component has a guard logic to control the execution of your workflow on top of your configuration.
510+
511+
It allows you to execute your custom logic to decide if the transition is blocked or not, before actually
512+
applying this transition.
513+
514+
You have multiple optional ways to use guards in your workflow.
515+
516+
The first way is :ref:`with the guard event <workflow-usage-guard-events>`, which allows you to implement
517+
any desired feature.
518+
519+
Another one is via the configuration and its specific entry `guard` on a transition.
520+
521+
This `guard` entry allows any expression that is valid for the Expression Language component:
522+
523+
.. configuration-block::
524+
525+
.. code-block:: yaml
526+
527+
# config/packages/workflow.yaml
528+
framework:
529+
workflows:
530+
blog_publishing:
531+
# previous configuration
532+
transitions:
533+
to_review:
534+
guard: "is_granted('ROLE_REVIEWER')" # the transition is allowed only if the current user has the ROLE_REVIEWER role.
535+
from: draft
536+
to: reviewed
537+
publish:
538+
guard: "is_authenticated" # or "is_anonymous", "is_remember_me", "is_fully_authenticated", "is_granted"
539+
from: reviewed
540+
to: published
541+
reject:
542+
guard: "has_role("ROLE_ADMIN") and subject.isStatusReviewed()" # or any valid expression language with "subject" refering to the post
543+
from: reviewed
544+
to: rejected
545+
504546
Usage in Twig
505547
-------------
506548

@@ -542,7 +584,7 @@ The following example shows these functions in action:
542584
{% endfor %}
543585

544586
{# Check if the object is in some specific place #}
545-
{% if workflow_has_marked_place(post, 'review') %}
587+
{% if workflow_has_marked_place(post, 'reviewed') %}
546588
<p>This post is ready for review.</p>
547589
{% endif %}
548590

0 commit comments

Comments
 (0)