Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 44eaa4d

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

File tree

Expand file treeCollapse file tree

1 file changed

+62
-20
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+62
-20
lines changed

‎workflow/usage.rst

Copy file name to clipboardExpand all lines: workflow/usage.rst
+62-20Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.