Skip to content

Commit 44eaa4d

Browse files
committed
Merge branch '4.2'
* 4.2: [Workflow] Guard documentation
2 parents 0ddc9eb + c328657 commit 44eaa4d

File tree

1 file changed

+62
-20
lines changed

1 file changed

+62
-20
lines changed

workflow/usage.rst

Lines changed: 62 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ A set of places and transitions creates a **definition**. A workflow needs
2727
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

30-
Consider the following example for a blog post that can have these places:
31-
``draft``, ``review``, ``rejected``, ``published``. You can define the workflow
30+
Consider the following example for a blog post. A post can have these places:
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,9 @@ 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 (see
331+
:ref:`guard events <workflow-usage-guard-events>` and
332+
:ref:`blocking transitions <workflow-blocking-transitions>`).
331333

332334
The three events being dispatched are:
333335

@@ -439,14 +441,15 @@ Guard Events
439441
There are a special kind of events called "Guard events". Their event listeners
440442
are invoked every time a call to ``Workflow::can``, ``Workflow::apply`` or
441443
``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
444+
add custom logic to decide which transitions should be blocked or not. Here is a list
443445
of the guard event names.
444446

445447
* ``workflow.guard``
446448
* ``workflow.[workflow name].guard``
447449
* ``workflow.[workflow name].guard.[transition name]``
448450

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

451454
use Symfony\Component\Workflow\Event\GuardEvent;
452455
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -460,8 +463,7 @@ See example to make sure no blog post without title is moved to "review"::
460463
$title = $post->title;
461464

462465
if (empty($title)) {
463-
// Posts without title are not allowed
464-
// to perform the transition "to_review"
466+
// Block the transition "to_review" if the post has no title
465467
$event->setBlocked(true);
466468
}
467469
}
@@ -501,6 +503,46 @@ This class has two more methods:
501503
:method:`Symfony\\Component\\Workflow\\Event\\GuardEvent::setBlocked`
502504
Sets the blocked value.
503505

506+
.. _workflow-blocking-transitions:
507+
508+
Blocking Transitions
509+
--------------------
510+
511+
The execution of the workflow can be controlled by executing custom logic to
512+
decide if the current transition is blocked or allowed before applying it. This
513+
feature is provided by "guards", which can be used in two ways.
514+
515+
First, you can listen to :ref:`the guard events <workflow-usage-guard-events>`.
516+
Alternatively, you can define a ``guard`` configuration option for the
517+
transition. The value of this option is any valid expression created with the
518+
:doc:`ExpressionLanguage component </components/expression_language>`:
519+
520+
.. configuration-block::
521+
522+
.. code-block:: yaml
523+
524+
# config/packages/workflow.yaml
525+
framework:
526+
workflows:
527+
blog_publishing:
528+
# previous configuration
529+
transitions:
530+
to_review:
531+
# the transition is allowed only if the current user has the ROLE_REVIEWER role.
532+
guard: "is_granted('ROLE_REVIEWER')"
533+
from: draft
534+
to: reviewed
535+
publish:
536+
# or "is_anonymous", "is_remember_me", "is_fully_authenticated", "is_granted"
537+
guard: "is_authenticated"
538+
from: reviewed
539+
to: published
540+
reject:
541+
# or any valid expression language with "subject" referring to the post
542+
guard: "has_role("ROLE_ADMIN") and subject.isStatusReviewed()"
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)