@@ -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
],
@@ -327,7 +327,9 @@ When a state transition is initiated, the events are dispatched in the following
327
327
order:
328
328
329
329
``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 >`).
331
333
332
334
The three events being dispatched are:
333
335
@@ -439,14 +441,15 @@ Guard Events
439
441
There are a special kind of events called "Guard events". Their event listeners
440
442
are invoked every time a call to ``Workflow::can ``, ``Workflow::apply `` or
441
443
``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
443
445
of the guard event names.
444
446
445
447
* ``workflow.guard ``
446
448
* ``workflow.[workflow name].guard ``
447
449
* ``workflow.[workflow name].guard.[transition name] ``
448
450
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::
450
453
451
454
use Symfony\Component\Workflow\Event\GuardEvent;
452
455
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -460,8 +463,7 @@ See example to make sure no blog post without title is moved to "review"::
460
463
$title = $post->title;
461
464
462
465
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
465
467
$event->setBlocked(true);
466
468
}
467
469
}
@@ -501,6 +503,46 @@ This class has two more methods:
501
503
:method: `Symfony\\ Component\\ Workflow\\ Event\\ GuardEvent::setBlocked `
502
504
Sets the blocked value.
503
505
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
+
504
546
Usage in Twig
505
547
-------------
506
548
@@ -542,7 +584,7 @@ The following example shows these functions in action:
542
584
{% endfor %}
543
585
544
586
{# 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 ') %}
546
588
<p>This post is ready for review.</p>
547
589
{% endif %}
548
590
0 commit comments