@@ -43,8 +43,9 @@ like this:
4343 audit_trail :
4444 enabled : true
4545 marking_store :
46- type : ' multiple_state ' # one of 'single_state', 'multiple_state', ' method'
46+ type : ' method'
4747 arguments :
48+ - false
4849 - ' currentPlace'
4950 supports :
5051 - App\Entity\BlogPost
@@ -68,7 +69,7 @@ like this:
6869 .. code-block :: xml
6970
7071 <!-- config/packages/workflow.xml -->
71- <?xml version =" 1.0" encoding =" UTF -8" ?>
72+ <?xml version =" 1.0" encoding =" utf -8" ?>
7273 <container xmlns =" http://symfony.com/schema/dic/services"
7374 xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
7475 xmlns : framework =" http://symfony.com/schema/dic/symfony"
@@ -80,7 +81,8 @@ like this:
8081 <framework : workflow name =" blog_publishing" type =" workflow" >
8182 <framework : audit-trail enabled =" true" />
8283
83- <framework : marking-store type =" single_state" >
84+ <framework : marking-store type =" method" >
85+ <framework : argument >false</framework : argument >
8486 <framework : argument >currentPlace</framework : argument >
8587 </framework : marking-store >
8688
@@ -117,6 +119,7 @@ like this:
117119 .. code-block :: php
118120
119121 // config/packages/workflow.php
122+
120123 $container->loadFromExtension('framework', [
121124 // ...
122125 'workflows' => [
@@ -126,8 +129,11 @@ like this:
126129 'enabled' => true
127130 ],
128131 'marking_store' => [
129- 'type' => 'multiple_state', // one of 'single_state', 'multiple_state', 'method'
130- 'arguments' => ['currentPlace'],
132+ 'type' => 'method',
133+ 'arguments' => [
134+ false,
135+ 'currentPlace',
136+ ],
131137 ],
132138 'supports' => ['App\Entity\BlogPost'],
133139 'places' => [
@@ -166,18 +172,14 @@ As configured, the following property is used by the marking store::
166172
167173.. note ::
168174
169- The marking store type could be "multiple_state", "single_state" or "method".
170- A single state marking store does not support a model being on multiple places
171- at the same time.
172-
173- versionadded:: 4.3
174-
175- The ``method `` marking store type was introduced in Symfony 4.3.
175+ The Workflow Component supports workflows that can be in one or multiple places
176+ (states) at the same time. To restrict a workflow to a single state, set the first
177+ argument to ``true `` when defining the ``marking_store ``.
176178
177179.. tip ::
178180
179- The ``type `` (default value ``single_state ``) and ``arguments `` (default
180- value ``marking ``) attributes of the ``marking_store `` option are optional.
181+ The ``type `` (default value ``method ``) and ``arguments `` (default
182+ values `` false `` and ``marking ``) attributes of the ``marking_store `` option are optional.
181183 If omitted, their default values will be used.
182184
183185.. tip ::
@@ -224,90 +226,11 @@ you can get the workflow by injecting the Workflow registry service::
224226 // ... if the transition is not allowed
225227 }
226228
227- // Update the currentState on the post passing some contextual data
228- // to the whole workflow process
229- try {
230- $workflow->apply($post, 'publish', [
231- 'log_comment' => 'My logging comment for the publish transition.',
232- ]);
233- } catch (TransitionException $exception) {
234- // ... if the transition is not allowed
235- }
236-
237229 // See all the available transitions for the post in the current state
238230 $transitions = $workflow->getEnabledTransitions($post);
239231 }
240232 }
241233
242- .. versionadded :: 4.1
243-
244- The :class: `Symfony\\ Component\\ Workflow\\ Exception\\ TransitionException `
245- class was introduced in Symfony 4.1.
246-
247- .. versionadded :: 4.1
248-
249- The :method: `Symfony\\ Component\\ Workflow\\ Registry::all ` method was
250- introduced in Symfony 4.1.
251-
252- You can pass some context as the second argument of the ``apply() `` method.
253- This can be useful when the subject not only needs to apply a transition,
254- but for example you also want to log the context in which the switch happened.
255-
256- This context is forwarded to the :method: `Symfony\\ Component\\ Workflow\\ MarkingStore\\ MarkingStoreInterface::setMarking `
257- method of the marking store.
258-
259- .. versionadded :: 4.3
260-
261- The ``$context `` argument of the :method: `Symfony\\ Component\\ Workflow\\ Workflow::apply `
262- method was introduced in Symfony 4.3.
263-
264- .. tip ::
265-
266- Configure the ``type `` as ``method `` of the ``marking_store `` option to use this feature
267- without implementing your own marking store.
268-
269- You can also use this ``$context `` in your own marking store implementation.
270- A simple implementation example is when you want to store the place as integer instead of string in your object.
271-
272- Lets say your object has a status property, stored as an integer in your storage, and you want to log an optional
273- comment any time the status changes::
274-
275- // your own implementation class, to define in the configuration "marking_store"
276-
277- class ObjectMarkingStore implements MarkingStoreInterface
278- {
279- public function getMarking($subject)
280- {
281- $subject->getStatus();
282- // ...
283- // return a marking
284- }
285-
286- public function setMarking($subject, Marking $marking, array $context);
287- {
288- // ...
289- $subject->setStatus($newStatus, $context['log_comment'] ?? null);
290- }
291- }
292-
293- // and in your Object class
294-
295- public function getStatus()
296- {
297- return $this->status;
298- }
299-
300- public function setStatus(int $status, ?string $comment = null)
301- {
302- $this->status = $status;
303- $this->addStatusLogRecord(new StatusLog($this, $comment));
304-
305- return $this;
306- }
307-
308- // the StatusLog class can have a createdAt, a username,
309- // the new status, and finally your optional comment retrieved from the workflow context.
310-
311234Using Events
312235------------
313236
@@ -455,7 +378,7 @@ See example to make sure no blog post without title is moved to "review"::
455378 {
456379 public function guardReview(GuardEvent $event)
457380 {
458- /** @var App\Entity\BlogPost $post */
381+ /** @var \ App\Entity\BlogPost $post */
459382 $post = $event->getSubject();
460383 $title = $post->title;
461384
@@ -549,70 +472,3 @@ The following example shows these functions in action:
549472 {% if 'waiting_some_approval' in workflow_marked_places(post) %}
550473 <span class="label">PENDING</span>
551474 {% endif %}
552-
553- Transition Blockers
554- -------------------
555-
556- .. versionadded :: 4.1
557-
558- Transition Blockers were introduced in Symfony 4.1.
559-
560- Transition Blockers provide a way to return a human-readable message for why a
561- transition was blocked::
562-
563- use Symfony\Component\Workflow\Event\GuardEvent;
564- use Symfony\Component\EventDispatcher\EventSubscriberInterface;
565-
566- class BlogPostPublishListener implements EventSubscriberInterface
567- {
568- public function guardPublish(GuardEvent $event)
569- {
570- /** @var \App\Entity\BlogPost $post */
571- $post = $event->getSubject();
572-
573- // If it's after 9pm, prevent publication
574- if (date('H') > 21) {
575- $event->addTransitionBlocker(
576- new TransitionBlocker(
577- "You can not publish this blog post because it's too late. Try again tomorrow morning."
578- )
579- );
580- }
581- }
582-
583- public static function getSubscribedEvents()
584- {
585- return [
586- 'workflow.blogpost.guard.publish' => ['guardPublish'],
587- ];
588- }
589- }
590-
591- You can access the message from a Twig template as follows:
592-
593- .. code-block :: html+twig
594-
595- <h2>Publication was blocked because:</h2>
596- <ul>
597- {% for transition in workflow_all_transitions(article) %}
598- {% if not workflow_can(article, transition.name) %}
599- <li>
600- <strong>{{ transition.name }}</strong>:
601- <ul>
602- {% for blocker in workflow_build_transition_blocker_list(article, transition.name) %}
603- <li>
604- {{ blocker.message }}
605- {% if blocker.parameters.expression is defined %}
606- <code>{{ blocker.parameters.expression }}</code>
607- {% endif %}
608- </li>
609- {% endfor %}
610- </ul>
611- </li>
612- {% endif %}
613- {% endfor %}
614- </ul>
615-
616- Don't need a human-readable message? You can still use::
617-
618- $event->setBlocked('true');
0 commit comments