@@ -14,6 +14,15 @@ install the workflow feature before using it:
1414
1515 $ composer require symfony/workflow
1616
17+ Configuration
18+ -------------
19+
20+ To see all configuration options, if you are using the component inside a Symfony project run this command:
21+
22+ .. code-block :: terminal
23+
24+ $ bin/console config:dump-reference framework workflows
25+
1726 Creating a Workflow
1827-------------------
1928
@@ -552,3 +561,224 @@ Don't need a human-readable message? You can also block a transition via a guard
552561event using::
553562
554563 $event->setBlocked('true');
564+
565+ Storing Metadata
566+ ----------------
567+
568+ .. versionadded :: 4.1
569+
570+ The feature to store metadata in workflows was introduced in Symfony 4.1.
571+
572+ In case you need it, you can store arbitrary metadata in workflows, their
573+ places, and their transitions using the ``metadata `` option. This metadata can
574+ be as simple as the title of the workflow or as complex as your own application
575+ requires:
576+
577+ .. configuration-block ::
578+
579+ .. code-block :: yaml
580+
581+ # config/packages/workflow.yaml
582+ framework :
583+ workflows :
584+ blog_publishing :
585+ metadata :
586+ title : ' Blog Publishing Workflow'
587+ # ...
588+ places :
589+ draft :
590+ metadata :
591+ max_num_of_words : 500
592+ # ...
593+ transitions :
594+ to_review :
595+ from : draft
596+ to : review
597+ metadata :
598+ priority : 0.5
599+ # ...
600+
601+ .. code-block :: xml
602+
603+ <!-- config/packages/workflow.xml -->
604+ <?xml version =" 1.0" encoding =" UTF-8" ?>
605+ <container xmlns =" http://symfony.com/schema/dic/services"
606+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
607+ xmlns : framework =" http://symfony.com/schema/dic/symfony"
608+ xsi : schemaLocation =" http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
609+ http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"
610+ >
611+
612+ <framework : config >
613+ <framework : workflow name =" blog_publishing" >
614+ <framework : metadata >
615+ <framework : title >Blog Publishing Workflow</framework : title >
616+ </framework : metadata >
617+ <!-- ... -->
618+
619+ <framework : place name =" draft" >
620+ <framework : metadata >
621+ <framework : max-num-of-words >500</framework : max-num-of-words >
622+ </framework : metadata >
623+ </framework : place >
624+ <!-- ... -->
625+
626+ <framework : transition name =" to_review" >
627+ <framework : from >draft</framework : from >
628+ <framework : to >review</framework : to >
629+ <framework : metadata >
630+ <framework : priority >0.5</framework : priority >
631+ </framework : metadata >
632+ </framework : transition >
633+ <!-- ... -->
634+ </framework : workflow >
635+ </framework : config >
636+ </container >
637+
638+ .. code-block :: php
639+
640+ // config/packages/workflow.php
641+
642+ $container->loadFromExtension('framework', [
643+ // ...
644+ 'workflows' => [
645+ 'blog_publishing' => [
646+ 'metadata' => [
647+ 'title' => 'Blog Publishing Workflow',
648+ ],
649+ // ...
650+ 'places' => [
651+ 'draft' => [
652+ 'metadata' => [
653+ 'max_num_of_words' => 500,
654+ ],
655+ ],
656+ // ...
657+ ],
658+ 'transitions' => [
659+ 'to_review' => [
660+ 'from' => 'draft',
661+ 'to' => 'review',
662+ 'metadata' => [
663+ 'priority' => 0.5,
664+ ],
665+ ],
666+ ],
667+ ],
668+ ],
669+ ]);
670+
671+ Then you can access this metadata in your controller as follows::
672+
673+ public function myControllerAction(Registry $registry, Article $article)
674+ {
675+ $workflow = $registry->get($article);
676+
677+ $workflow
678+ ->getMetadataStore()
679+ ->getWorkflowMetadata()['title'] ?? false
680+ ;
681+
682+ // or
683+ $workflow->getMetadataStore()
684+ ->getWorkflowMetadata()['title'] ?? false
685+ ;
686+
687+ // or
688+ $aTransition = $workflow->getDefinition()->getTransitions()[0];
689+ $workflow
690+ ->getMetadataStore()
691+ ->getTransitionMetadata($aTransition)['title'] ?? false
692+ ;
693+ }
694+
695+ There is a shortcut that works with everything::
696+
697+ $workflow
698+ ->getMetadataStore()
699+ ->getMetadata('title')
700+ ;
701+
702+ In a Flash message in your Controller::
703+
704+ // $transition = ...; (an instance of Transition)
705+
706+ // $workflow is a Workflow instance retrieved from the Registry (see above)
707+ $title = $workflow->getMetadataStore()->getMetadata('title', $transition);
708+ $this->addFlash('info', "You have successfully applied the transition with title: '$title'");
709+
710+ Metadata can also be accessed in a Listener, from the Event object.
711+
712+ Using transition blockers you can
713+ return a user-friendly error message when you stop a transition from happening. In the example we
714+ get this message from the :class: `Symfony\\ Component\\ Workflow\\ Event\\ Event `'s metadata, giving
715+ you a central place to manage the text.
716+
717+ .. tip ::
718+
719+ This example has been simplified; in production you may prefer to use the :doc: `Translation </components/translation >`
720+ component to manage messages in one place::
721+
722+ namespace App\Listener\Workflow\Task;
723+
724+ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
725+ use Symfony\Component\Workflow\Event\GuardEvent;
726+ use Symfony\Component\Workflow\TransitionBlocker;
727+
728+ class OverdueGuard implements EventSubscriberInterface
729+ {
730+ public function guardPublish(GuardEvent $event)
731+ {
732+ $timeLimit = $event->getMetadata('time_limit', $event->getTransition());
733+
734+ if (date('Hi') <= $timeLimit) {
735+ return;
736+ }
737+
738+ $explanation = $event->getMetadata('explanation', $event->getTransition());
739+ $event->addTransitionBlocker(new TransitionBlocker($explanation , 0));
740+ }
741+
742+ public static function getSubscribedEvents()
743+ {
744+ return [
745+ 'workflow.task.guard.done' => 'guardPublish',
746+ ];
747+ }
748+ }
749+
750+ .. versionadded :: 4.1
751+
752+ The transition blockers were introduced in Symfony 4.1.
753+
754+ In Twig templates, metadata is available via the ``workflow_metadata() `` function:
755+
756+ .. code-block :: html+twig
757+
758+ <h2>Metadata</h2>
759+ <p>
760+ <strong>Workflow</strong>:<br >
761+ <code>{{ workflow_metadata(article, 'title') }}</code>
762+ </p>
763+ <p>
764+ <strong>Current place(s)</strong>
765+ <ul>
766+ {% for place in workflow_marked_places(article) %}
767+ <li>
768+ {{ place }}:
769+ <code>{{ workflow_metadata(article, 'max_num_of_words', place) ?: 'Unlimited'}}</code>
770+ </li>
771+ {% endfor %}
772+ </ul>
773+ </p>
774+ <p>
775+ <strong>Enabled transition(s)</strong>
776+ <ul>
777+ {% for transition in workflow_transitions(article) %}
778+ <li>
779+ {{ transition.name }}:
780+ <code>{{ workflow_metadata(article, 'priority', transition) ?: '0' }}</code>
781+ </li>
782+ {% endfor %}
783+ </ul>
784+ </p>
0 commit comments