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 07ada7f

Browse filesBrowse files
noniagriconomiejaviereguiluz
authored andcommitted
[Workflow] Guard documentation
1 parent f866de7 commit 07ada7f
Copy full SHA for 07ada7f

File tree

Expand file treeCollapse file tree

1 file changed

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

1 file changed

+65
-20
lines changed

‎workflow/usage.rst

Copy file name to clipboardExpand all lines: workflow/usage.rst
+65-20Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ A set of places and transitions creates a **definition**. A workflow needs
1414
a ``Definition`` and a way to write the states to the objects (i.e. an
1515
instance of a :class:`Symfony\\Component\\Workflow\\MarkingStore\\MarkingStoreInterface`.)
1616

17-
Consider the following example for a blog post. A post can have places:
18-
'draft', 'review', 'rejected', 'published'. You can define the workflow
17+
Consider the following example for a blog post. A post can have these places:
18+
``draft``, ``reviewed``, ``rejected``, ``published``. You can define the workflow
1919
like this:
2020

2121
.. configuration-block::
@@ -38,18 +38,18 @@ like this:
3838
initial_place: draft
3939
places:
4040
- draft
41-
- review
41+
- reviewed
4242
- rejected
4343
- published
4444
transitions:
4545
to_review:
4646
from: draft
47-
to: review
47+
to: reviewed
4848
publish:
49-
from: review
49+
from: reviewed
5050
to: published
5151
reject:
52-
from: review
52+
from: reviewed
5353
to: rejected
5454
5555
.. code-block:: xml
@@ -74,24 +74,24 @@ like this:
7474
<framework:support>AppBundle\Entity\BlogPost</framework:support>
7575
7676
<framework:place>draft</framework:place>
77-
<framework:place>review</framework:place>
77+
<framework:place>reviewed</framework:place>
7878
<framework:place>rejected</framework:place>
7979
<framework:place>published</framework:place>
8080
8181
<framework:transition name="to_review">
8282
<framework:from>draft</framework:from>
8383
84-
<framework:to>review</framework:to>
84+
<framework:to>reviewed</framework:to>
8585
</framework:transition>
8686
8787
<framework:transition name="publish">
88-
<framework:from>review</framework:from>
88+
<framework:from>reviewed</framework:from>
8989
9090
<framework:to>published</framework:to>
9191
</framework:transition>
9292
9393
<framework:transition name="reject">
94-
<framework:from>review</framework:from>
94+
<framework:from>reviewed</framework:from>
9595
9696
<framework:to>rejected</framework:to>
9797
</framework:transition>
@@ -119,21 +119,21 @@ like this:
119119
'supports' => ['AppBundle\Entity\BlogPost'],
120120
'places' => [
121121
'draft',
122-
'review',
122+
'reviewed',
123123
'rejected',
124124
'published',
125125
],
126126
'transitions' => [
127127
'to_review' => [
128128
'from' => 'draft',
129-
'to' => 'review',
129+
'to' => 'reviewed',
130130
],
131131
'publish' => [
132-
'from' => 'review',
132+
'from' => 'reviewed',
133133
'to' => 'published',
134134
],
135135
'reject' => [
136-
'from' => 'review',
136+
'from' => 'reviewed',
137137
'to' => 'rejected',
138138
],
139139
],
@@ -210,7 +210,7 @@ When a state transition is initiated, the events are dispatched in the following
210210
order:
211211

212212
``workflow.guard``
213-
Validate whether the transition is allowed at all (:ref:`see below <workflow-usage-guard-events>`).
213+
Validate whether the transition is blocked or not (:ref:`see below <workflow-usage-guard-events>` and :ref:`using guards <workflow-usage-using-guards>`).
214214

215215
The three events being dispatched are:
216216

@@ -322,14 +322,14 @@ Guard Events
322322
There are a special kind of events called "Guard events". Their event listeners
323323
are invoked every time a call to ``Workflow::can``, ``Workflow::apply`` or
324324
``Workflow::getEnabledTransitions`` is executed. With the guard events you may
325-
add custom logic to decide what transitions are valid or not. Here is a list
325+
add custom logic to decide which transitions should be blocked or not. Here is a list
326326
of the guard event names.
327327

328328
* ``workflow.guard``
329329
* ``workflow.[workflow name].guard``
330330
* ``workflow.[workflow name].guard.[transition name]``
331331

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

334334
use Symfony\Component\Workflow\Event\GuardEvent;
335335
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -343,8 +343,8 @@ See example to make sure no blog post without title is moved to "review"::
343343
$title = $post->title;
344344

345345
if (empty($title)) {
346-
// Posts without title are not allowed
347-
// to perform the transition "to_review"
346+
// Block the transition "to_review"
347+
// if the post has no title
348348
$event->setBlocked(true);
349349
}
350350
}
@@ -388,6 +388,51 @@ This class has two more methods:
388388
:method:`Symfony\\Component\\Workflow\\Event\\GuardEvent::setBlocked`
389389
Sets the blocked value.
390390

391+
.. _workflow-usage-using-guards:
392+
393+
Using Guards
394+
------------
395+
396+
The component has a guard logic to control the execution of your workflow on top of your configuration.
397+
398+
It allows you to execute your custom logic to decide if the transition is blocked or not, before actually
399+
applying this transition.
400+
401+
You have multiple optional ways to use guards in your workflow.
402+
403+
The first way is :ref:`with the guard event <workflow-usage-guard-events>`, which allows you to implement
404+
any desired feature.
405+
406+
Another one is via the configuration and its specific entry ``guard`` on a transition.
407+
408+
This ``guard`` entry allows any expression that is valid for the Expression Language component:
409+
410+
.. configuration-block::
411+
412+
.. code-block:: yaml
413+
414+
# config/packages/workflow.yaml
415+
framework:
416+
workflows:
417+
blog_publishing:
418+
# previous configuration
419+
transitions:
420+
to_review:
421+
# the transition is allowed only if the current user has the ROLE_REVIEWER role.
422+
guard: "is_granted('ROLE_REVIEWER')"
423+
from: draft
424+
to: reviewed
425+
publish:
426+
# or "is_anonymous", "is_remember_me", "is_fully_authenticated", "is_granted"
427+
guard: "is_authenticated"
428+
from: reviewed
429+
to: published
430+
reject:
431+
# or any valid expression language with "subject" refering to the post
432+
guard: "has_role("ROLE_ADMIN") and subject.isStatusReviewed()"
433+
from: reviewed
434+
to: rejected
435+
391436
Usage in Twig
392437
-------------
393438

@@ -434,7 +479,7 @@ The following example shows these functions in action:
434479
{% endfor %}
435480

436481
{# Check if the object is in some specific place #}
437-
{% if workflow_has_marked_place(post, 'review') %}
482+
{% if workflow_has_marked_place(post, 'reviewed') %}
438483
<p>This post is ready for review.</p>
439484
{% endif %}
440485

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.