@@ -27,8 +27,8 @@ A set of places and transitions creates a **definition**. A workflow needs
2727a ``Definition `` and a way to write the states to the objects (i.e. an
2828instance 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
3232like 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
327327order:
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
439441There are a special kind of events called "Guard events". Their event listeners
440442are 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
443445of 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