@@ -185,7 +185,10 @@ As configured, the following property is used by the marking store::
185185With this workflow named ``blog_publishing ``, you can get help to decide
186186what actions are allowed on a blog post::
187187
188- $post = new App\Entity\BlogPost();
188+ use Symfony\Component\Workflow\Exception\LogicException;
189+ use App\Entity\BlogPost;
190+
191+ $post = BlogPost();
189192
190193 $workflow = $this->container->get('workflow.blog_publishing');
191194 $workflow->can($post, 'publish'); // False
@@ -389,6 +392,9 @@ This means that each event has access to the following information:
389392:method: `Symfony\\ Component\\ Workflow\\ Event\\ Event::getWorkflowName `
390393 Returns a string with the name of the workflow that triggered the event.
391394
395+ :method: `Symfony\\ Component\\ Workflow\\ Event\\ Event::getMetadata `
396+ Returns a metadata.
397+
392398For Guard Events, there is an extended class :class: `Symfony\\ Component\\ Workflow\\ Event\\ GuardEvent `.
393399This class has two more methods:
394400
@@ -398,6 +404,13 @@ This class has two more methods:
398404:method: `Symfony\\ Component\\ Workflow\\ Event\\ GuardEvent::setBlocked `
399405 Sets the blocked value.
400406
407+ :method: `Symfony\\ Component\\ Workflow\\ Event\\ GuardEvent::getTransitionBlockerList `
408+ Returns the event :class: `Symfony\\ Component\\ Workflow\\ TransitionBlockerList `.
409+ See :ref: `blocking transitions <workflow-blocking-transitions >`.
410+
411+ :method: `Symfony\\ Component\\ Workflow\\ Event\\ GuardEvent::addTransitionBlocker `
412+ Add a :class: `Symfony\\ Component\\ Workflow\\ TransitionBlocker ` instance.
413+
401414.. _workflow-blocking-transitions :
402415
403416Blocking Transitions
@@ -426,16 +439,61 @@ transition. The value of this option is any valid expression created with the
426439 from : draft
427440 to : reviewed
428441 publish :
429- # or "is_anonymous", "is_remember_me", "is_fully_authenticated", "is_granted"
442+ # or "is_anonymous", "is_remember_me", "is_fully_authenticated", "is_granted", "is_valid"
430443 guard : " is_authenticated"
431444 from : reviewed
432445 to : published
433446 reject :
434- # or any valid expression language with "subject" referring to the post
435- guard : " has_role('ROLE_ADMIN') and subject.isStatusReviewed ()"
447+ # or any valid expression language with "subject" referring to the supported object
448+ guard : " has_role('ROLE_ADMIN') and subject.isRejectable ()"
436449 from : reviewed
437450 to : rejected
438451
452+ You can also use transition blockers to block and return a user-friendly error
453+ message when you stop a transition from happening.
454+ In the example we get this message from the
455+ :class: `Symfony\\ Component\\ Workflow\\ Event\\ Event `'s metadata, giving you a
456+ central place to manage the text.
457+
458+ This example has been simplified; in production you may prefer to use the
459+ :doc: `Translation </components/translation >` component to manage messages in one
460+ place::
461+
462+ namespace App\Listener\Workflow\Task;
463+
464+ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
465+ use Symfony\Component\Workflow\Event\GuardEvent;
466+ use Symfony\Component\Workflow\TransitionBlocker;
467+
468+ class BlogPostPublishListener implements EventSubscriberInterface
469+ {
470+ public function guardPublish(GuardEvent $event)
471+ {
472+ $eventTransition = $event->getTransition();
473+ $hourLimit = $event->getMetadata('hour_limit', $eventTransition);
474+
475+ if (date('H') <= $hourLimit) {
476+ return;
477+ }
478+
479+ // Block the transition "publish" if it is more than 8 PM
480+ // with the message for end user
481+ $explanation = $event->getMetadata('explanation', $eventTransition);
482+ $event->addTransitionBlocker(new TransitionBlocker($explanation , 0));
483+ }
484+
485+ public static function getSubscribedEvents()
486+ {
487+ return [
488+ 'workflow.blog_publishing.guard.publish' => ['guardPublish'],
489+ ];
490+ }
491+ }
492+
493+ .. versionadded :: 4.1
494+
495+ The transition blockers were introduced in Symfony 4.1.
496+
439497Usage in Twig
440498-------------
441499
@@ -458,15 +516,15 @@ The following example shows these functions in action:
458516
459517.. code-block :: html+twig
460518
461- <h3>Actions</h3>
519+ <h3>Actions on Blog Post </h3>
462520 {% if workflow_can(post, 'publish') %}
463- <a href="...">Publish article </a>
521+ <a href="...">Publish</a>
464522 {% endif %}
465523 {% if workflow_can(post, 'to_review') %}
466524 <a href="...">Submit to review</a>
467525 {% endif %}
468526 {% if workflow_can(post, 'reject') %}
469- <a href="...">Reject article </a>
527+ <a href="...">Reject</a>
470528 {% endif %}
471529
472530 {# Or loop through the enabled transitions #}
@@ -482,8 +540,8 @@ The following example shows these functions in action:
482540 {% endif %}
483541
484542 {# Check if some place has been marked on the object #}
485- {% if 'waiting_some_approval ' in workflow_marked_places(post) %}
486- <span class="label">PENDING </span>
543+ {% if 'reviewed ' in workflow_marked_places(post) %}
544+ <span class="label">Reviewed </span>
487545 {% endif %}
488546
489547Storing Metadata
@@ -520,7 +578,12 @@ requires:
520578 to : review
521579 metadata :
522580 priority : 0.5
523- # ...
581+ publish :
582+ from : reviewed
583+ to : published
584+ metadata :
585+ hour_limit : 20
586+ explanation : ' You can not publish after 8 PM.'
524587
525588 .. code-block :: xml
526589
@@ -551,7 +614,14 @@ requires:
551614 <framework : priority >0.5</framework : priority >
552615 </framework : metadata >
553616 </framework : transition >
554- <!-- ... -->
617+ <framework : transition name =" publish" >
618+ <framework : from >reviewed</framework : from >
619+ <framework : to >published</framework : to >
620+ <framework : metadata >
621+ <framework : hour_limit >20</framework : priority >
622+ <framework : explanation >You can not publish after 8 PM.</framework : priority >
623+ </framework : metadata >
624+ </framework : transition >
555625 </framework : workflow >
556626 </framework : config >
557627 </container >
@@ -583,6 +653,14 @@ requires:
583653 'priority' => 0.5,
584654 ],
585655 ],
656+ 'publish' => [
657+ 'from' => 'reviewed',
658+ 'to' => 'published',
659+ 'metadata' => [
660+ 'hour_limit' => 20,
661+ 'explanation' => 'You can not publish after 8 PM.',
662+ ],
663+ ],
586664 ],
587665 ],
588666 ],
@@ -591,27 +669,29 @@ requires:
591669 Then you can access this metadata in your controller as follows::
592670
593671 use Symfony\Component\Workflow\Registry;
672+ use App\Entity\BlogPost;
594673
595- public function myController(Registry $registry, Article $article )
674+ public function myController(Registry $registry, BlogPost $post )
596675 {
597- $workflow = $registry->get($article );
676+ $workflow = $registry->get($post );
598677
599678 $title = $workflow
600679 ->getMetadataStore()
601- ->getWorkflowMetadata()['title'] ?? false
680+ ->getWorkflowMetadata()['title'] ?? 'Default title'
602681 ;
603682
604683 // or
605684 $aTransition = $workflow->getDefinition()->getTransitions()[0];
606685 $transitionTitle = $workflow
607686 ->getMetadataStore()
608- ->getTransitionMetadata($aTransition)['title '] ?? false
687+ ->getTransitionMetadata($aTransition)['priority '] ?? 0
609688 ;
610689 }
611690
612- There is a shortcut that works with everything ::
691+ There is a shortcut that works with every metadata level ::
613692
614693 $title = $workflow->getMetadataStore()->getMetadata('title');
694+ $priority = $workflow->getMetadataStore()->getMetadata('priority');
615695
616696In a :ref: `flash message <flash-messages >` in your controller::
617697
@@ -621,76 +701,35 @@ In a :ref:`flash message <flash-messages>` in your controller::
621701 $title = $workflow->getMetadataStore()->getMetadata('title', $transition);
622702 $this->addFlash('info', "You have successfully applied the transition with title: '$title'");
623703
624- Metadata can also be accessed in a Listener, from the Event object.
625-
626- Using transition blockers you can return a user-friendly error message when you
627- stop a transition from happening. In the example we get this message from the
628- :class: `Symfony\\ Component\\ Workflow\\ Event\\ Event `'s metadata, giving you a
629- central place to manage the text.
630-
631- This example has been simplified; in production you may prefer to use the
632- :doc: `Translation </components/translation >` component to manage messages in one
633- place::
634-
635- namespace App\Listener\Workflow\Task;
636-
637- use Symfony\Component\EventDispatcher\EventSubscriberInterface;
638- use Symfony\Component\Workflow\Event\GuardEvent;
639- use Symfony\Component\Workflow\TransitionBlocker;
640-
641- class OverdueGuard implements EventSubscriberInterface
642- {
643- public function guardPublish(GuardEvent $event)
644- {
645- $timeLimit = $event->getMetadata('time_limit', $event->getTransition());
646-
647- if (date('Hi') <= $timeLimit) {
648- return;
649- }
650-
651- $explanation = $event->getMetadata('explanation', $event->getTransition());
652- $event->addTransitionBlocker(new TransitionBlocker($explanation , 0));
653- }
654-
655- public static function getSubscribedEvents()
656- {
657- return [
658- 'workflow.task.guard.done' => 'guardPublish',
659- ];
660- }
661- }
662-
663- .. versionadded :: 4.1
664-
665- The transition blockers were introduced in Symfony 4.1.
704+ Metadata can also be accessed in a Listener, from the :class: `Symfony\\ Component\\ Workflow\\ Event\\ Event ` object.
666705
667706In Twig templates, metadata is available via the ``workflow_metadata() `` function:
668707
669708.. code-block :: html+twig
670709
671- <h2>Metadata</h2>
710+ <h2>Metadata of Blog Post </h2>
672711 <p>
673- <strong>Workflow</strong>:<br >
674- <code>{{ workflow_metadata(article , 'title') }}</code>
712+ <strong>Workflow</strong>:<br>
713+ <code>{{ workflow_metadata(blog_post , 'title') }}</code>
675714 </p>
676715 <p>
677716 <strong>Current place(s)</strong>
678717 <ul>
679- {% for place in workflow_marked_places(article ) %}
718+ {% for place in workflow_marked_places(blog_post ) %}
680719 <li>
681720 {{ place }}:
682- <code>{{ workflow_metadata(article , 'max_num_of_words', place) ?: 'Unlimited'}}</code>
721+ <code>{{ workflow_metadata(blog_post , 'max_num_of_words', place) ?: 'Unlimited'}}</code>
683722 </li>
684723 {% endfor %}
685724 </ul>
686725 </p>
687726 <p>
688727 <strong>Enabled transition(s)</strong>
689728 <ul>
690- {% for transition in workflow_transitions(article ) %}
729+ {% for transition in workflow_transitions(blog_post ) %}
691730 <li>
692731 {{ transition.name }}:
693- <code>{{ workflow_metadata(article , 'priority', transition) ?: '0' }}</code>
732+ <code>{{ workflow_metadata(blog_post , 'priority', transition) ?: '0' }}</code>
694733 </li>
695734 {% endfor %}
696735 </ul>
0 commit comments