@@ -27,8 +27,8 @@ A set of places and transitions creates a **definition**. A workflow needs
27
27
a ``Definition `` and a way to write the states to the objects (i.e. an
28
28
instance of a :class: `Symfony\\ Component\\ Workflow\\ MarkingStore\\ MarkingStoreInterface `.)
29
29
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
32
32
like this:
33
33
34
34
.. configuration-block ::
@@ -51,18 +51,18 @@ like this:
51
51
initial_place : draft
52
52
places :
53
53
- draft
54
- - review
54
+ - reviewed
55
55
- rejected
56
56
- published
57
57
transitions :
58
58
to_review :
59
59
from : draft
60
- to : review
60
+ to : reviewed
61
61
publish :
62
- from : review
62
+ from : reviewed
63
63
to : published
64
64
reject :
65
- from : review
65
+ from : reviewed
66
66
to : rejected
67
67
68
68
.. code-block :: xml
@@ -87,24 +87,24 @@ like this:
87
87
<framework : support >App\Entity\BlogPost</framework : support >
88
88
89
89
<framework : place >draft</framework : place >
90
- <framework : place >review </framework : place >
90
+ <framework : place >reviewed </framework : place >
91
91
<framework : place >rejected</framework : place >
92
92
<framework : place >published</framework : place >
93
93
94
94
<framework : transition name =" to_review" >
95
95
<framework : from >draft</framework : from >
96
96
97
- <framework : to >review </framework : to >
97
+ <framework : to >reviewed </framework : to >
98
98
</framework : transition >
99
99
100
100
<framework : transition name =" publish" >
101
- <framework : from >review </framework : from >
101
+ <framework : from >reviewed </framework : from >
102
102
103
103
<framework : to >published</framework : to >
104
104
</framework : transition >
105
105
106
106
<framework : transition name =" reject" >
107
- <framework : from >review </framework : from >
107
+ <framework : from >reviewed </framework : from >
108
108
109
109
<framework : to >rejected</framework : to >
110
110
</framework : transition >
@@ -132,21 +132,21 @@ like this:
132
132
'supports' => ['App\Entity\BlogPost'],
133
133
'places' => [
134
134
'draft',
135
- 'review ',
135
+ 'reviewed ',
136
136
'rejected',
137
137
'published',
138
138
],
139
139
'transitions' => [
140
140
'to_review' => [
141
141
'from' => 'draft',
142
- 'to' => 'review ',
142
+ 'to' => 'reviewed ',
143
143
],
144
144
'publish' => [
145
- 'from' => 'review ',
145
+ 'from' => 'reviewed ',
146
146
'to' => 'published',
147
147
],
148
148
'reject' => [
149
- 'from' => 'review ',
149
+ 'from' => 'reviewed ',
150
150
'to' => 'rejected',
151
151
],
152
152
],
@@ -244,7 +244,9 @@ When a state transition is initiated, the events are dispatched in the following
244
244
order:
245
245
246
246
``workflow.guard ``
247
- Validate whether the transition is allowed at all (:ref: `see below <workflow-usage-guard-events >`).
247
+ Validate whether the transition is blocked or not (see
248
+ :ref: `guard events <workflow-usage-guard-events >` and
249
+ :ref: `blocking transitions <workflow-blocking-transitions >`).
248
250
249
251
The three events being dispatched are:
250
252
@@ -356,14 +358,15 @@ Guard Events
356
358
There are a special kind of events called "Guard events". Their event listeners
357
359
are invoked every time a call to ``Workflow::can ``, ``Workflow::apply `` or
358
360
``Workflow::getEnabledTransitions `` is executed. With the guard events you may
359
- add custom logic to decide what transitions are valid or not. Here is a list
361
+ add custom logic to decide which transitions should be blocked or not. Here is a list
360
362
of the guard event names.
361
363
362
364
* ``workflow.guard ``
363
365
* ``workflow.[workflow name].guard ``
364
366
* ``workflow.[workflow name].guard.[transition name] ``
365
367
366
- See example to make sure no blog post without title is moved to "review"::
368
+ This example stops any blog post being transitioned to "reviewed" if it is
369
+ missing a title::
367
370
368
371
use Symfony\Component\Workflow\Event\GuardEvent;
369
372
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -377,8 +380,7 @@ See example to make sure no blog post without title is moved to "review"::
377
380
$title = $post->title;
378
381
379
382
if (empty($title)) {
380
- // Posts without title are not allowed
381
- // to perform the transition "to_review"
383
+ // Block the transition "to_review" if the post has no title
382
384
$event->setBlocked(true);
383
385
}
384
386
}
@@ -418,6 +420,46 @@ This class has two more methods:
418
420
:method: `Symfony\\ Component\\ Workflow\\ Event\\ GuardEvent::setBlocked `
419
421
Sets the blocked value.
420
422
423
+ .. _workflow-blocking-transitions :
424
+
425
+ Blocking Transitions
426
+ --------------------
427
+
428
+ The execution of the workflow can be controlled by executing custom logic to
429
+ decide if the current transition is blocked or allowed before applying it. This
430
+ feature is provided by "guards", which can be used in two ways.
431
+
432
+ First, you can listen to :ref: `the guard events <workflow-usage-guard-events >`.
433
+ Alternatively, you can define a ``guard `` configuration option for the
434
+ transition. The value of this option is any valid expression created with the
435
+ :doc: `ExpressionLanguage component </components/expression_language >`:
436
+
437
+ .. configuration-block ::
438
+
439
+ .. code-block :: yaml
440
+
441
+ # config/packages/workflow.yaml
442
+ framework :
443
+ workflows :
444
+ blog_publishing :
445
+ # previous configuration
446
+ transitions :
447
+ to_review :
448
+ # the transition is allowed only if the current user has the ROLE_REVIEWER role.
449
+ guard : " is_granted('ROLE_REVIEWER')"
450
+ from : draft
451
+ to : reviewed
452
+ publish :
453
+ # or "is_anonymous", "is_remember_me", "is_fully_authenticated", "is_granted"
454
+ guard : " is_authenticated"
455
+ from : reviewed
456
+ to : published
457
+ reject :
458
+ # or any valid expression language with "subject" referring to the post
459
+ guard : " has_role(" ROLE_ADMIN") and subject.isStatusReviewed()"
460
+ from : reviewed
461
+ to : rejected
462
+
421
463
Usage in Twig
422
464
-------------
423
465
@@ -459,7 +501,7 @@ The following example shows these functions in action:
459
501
{% endfor %}
460
502
461
503
{# Check if the object is in some specific place #}
462
- {% if workflow_has_marked_place(post, 'review ') %}
504
+ {% if workflow_has_marked_place(post, 'reviewed ') %}
463
505
<p>This post is ready for review.</p>
464
506
{% endif %}
465
507
0 commit comments