@@ -197,7 +197,10 @@ As configured, the following property is used by the marking store::
197
197
With this workflow named ``blog_publishing ``, you can get help to decide
198
198
what actions are allowed on a blog post::
199
199
200
- $post = new App\Entity\BlogPost();
200
+ use Symfony\Component\Workflow\Exception\LogicException;
201
+ use App\Entity\BlogPost;
202
+
203
+ $post = BlogPost();
201
204
202
205
$workflow = $this->container->get('workflow.blog_publishing');
203
206
$workflow->can($post, 'publish'); // False
@@ -401,6 +404,9 @@ This means that each event has access to the following information:
401
404
:method: `Symfony\\ Component\\ Workflow\\ Event\\ Event::getWorkflowName `
402
405
Returns a string with the name of the workflow that triggered the event.
403
406
407
+ :method: `Symfony\\ Component\\ Workflow\\ Event\\ Event::getMetadata `
408
+ Returns a metadata.
409
+
404
410
For Guard Events, there is an extended class :class: `Symfony\\ Component\\ Workflow\\ Event\\ GuardEvent `.
405
411
This class has two more methods:
406
412
@@ -410,6 +416,13 @@ This class has two more methods:
410
416
:method: `Symfony\\ Component\\ Workflow\\ Event\\ GuardEvent::setBlocked `
411
417
Sets the blocked value.
412
418
419
+ :method: `Symfony\\ Component\\ Workflow\\ Event\\ GuardEvent::getTransitionBlockerList `
420
+ Returns the event :class: `Symfony\\ Component\\ Workflow\\ TransitionBlockerList `.
421
+ See :ref: `blocking transitions <workflow-blocking-transitions >`.
422
+
423
+ :method: `Symfony\\ Component\\ Workflow\\ Event\\ GuardEvent::addTransitionBlocker `
424
+ Addes a :class: `Symfony\\ Component\\ Workflow\\ TransitionBlocker `.
425
+
413
426
.. _workflow-blocking-transitions :
414
427
415
428
Blocking Transitions
@@ -438,16 +451,61 @@ transition. The value of this option is any valid expression created with the
438
451
from : draft
439
452
to : reviewed
440
453
publish :
441
- # or "is_anonymous", "is_remember_me", "is_fully_authenticated", "is_granted"
454
+ # or "is_anonymous", "is_remember_me", "is_fully_authenticated", "is_granted", "is_valid"
442
455
guard : " is_authenticated"
443
456
from : reviewed
444
457
to : published
445
458
reject :
446
- # or any valid expression language with "subject" referring to the post
447
- guard : " has_role('ROLE_ADMIN') and subject.isStatusReviewed ()"
459
+ # or any valid expression language with "subject" referring to the supported object
460
+ guard : " has_role('ROLE_ADMIN') and subject.isRejectable ()"
448
461
from : reviewed
449
462
to : rejected
450
463
464
+ You can also use transition blockers to block and return a user-friendly error
465
+ message when you stop a transition from happening.
466
+ In the example we get this message from the
467
+ :class: `Symfony\\ Component\\ Workflow\\ Event\\ Event `'s metadata, giving you a
468
+ central place to manage the text.
469
+
470
+ This example has been simplified; in production you may prefer to use the
471
+ :doc: `Translation </components/translation >` component to manage messages in one
472
+ place::
473
+
474
+ namespace App\Listener\Workflow\Task;
475
+
476
+ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
477
+ use Symfony\Component\Workflow\Event\GuardEvent;
478
+ use Symfony\Component\Workflow\TransitionBlocker;
479
+
480
+ class BlogPostPublishListener implements EventSubscriberInterface
481
+ {
482
+ public function guardPublish(GuardEvent $event)
483
+ {
484
+ $eventTransition = $event->getTransition();
485
+ $hourLimit = $event->getMetadata('hour_limit', $eventTransition);
486
+
487
+ if (date('H') <= $hourLimit) {
488
+ return;
489
+ }
490
+
491
+ // Block the transition "publish" if it is more than 8 PM
492
+ // with the message for end user
493
+ $explanation = $event->getMetadata('explanation', $eventTransition);
494
+ $event->addTransitionBlocker(new TransitionBlocker($explanation , 0));
495
+ }
496
+
497
+ public static function getSubscribedEvents()
498
+ {
499
+ return [
500
+ 'workflow.blog_publishing.guard.publish' => ['guardPublish'],
501
+ ];
502
+ }
503
+ }
504
+
505
+ .. versionadded :: 4.1
506
+
507
+ The transition blockers were introduced in Symfony 4.1.
508
+
451
509
Usage in Twig
452
510
-------------
453
511
@@ -470,15 +528,15 @@ The following example shows these functions in action:
470
528
471
529
.. code-block :: html+twig
472
530
473
- <h3>Actions</h3>
531
+ <h3>Actions on Blog Post </h3>
474
532
{% if workflow_can(post, 'publish') %}
475
- <a href="...">Publish article </a>
533
+ <a href="...">Publish</a>
476
534
{% endif %}
477
535
{% if workflow_can(post, 'to_review') %}
478
536
<a href="...">Submit to review</a>
479
537
{% endif %}
480
538
{% if workflow_can(post, 'reject') %}
481
- <a href="...">Reject article </a>
539
+ <a href="...">Reject</a>
482
540
{% endif %}
483
541
484
542
{# Or loop through the enabled transitions #}
@@ -494,8 +552,8 @@ The following example shows these functions in action:
494
552
{% endif %}
495
553
496
554
{# Check if some place has been marked on the object #}
497
- {% if 'waiting_some_approval ' in workflow_marked_places(post) %}
498
- <span class="label">PENDING </span>
555
+ {% if 'reviewed ' in workflow_marked_places(post) %}
556
+ <span class="label">Reviewed </span>
499
557
{% endif %}
500
558
501
559
Storing Metadata
@@ -532,6 +590,12 @@ requires:
532
590
to : review
533
591
metadata :
534
592
priority : 0.5
593
+ publish :
594
+ from : reviewed
595
+ to : published
596
+ metadata :
597
+ hour_limit : 20
598
+ explanation : ' You can not publish after 8 PM.'
535
599
# ...
536
600
537
601
.. code-block :: xml
@@ -563,6 +627,14 @@ requires:
563
627
<framework : priority >0.5</framework : priority >
564
628
</framework : metadata >
565
629
</framework : transition >
630
+ <framework : transition name =" publish" >
631
+ <framework : from >reviewed</framework : from >
632
+ <framework : to >published</framework : to >
633
+ <framework : metadata >
634
+ <framework : hour_limit >20</framework : priority >
635
+ <framework : explanation >You can not publish after 8 PM.</framework : priority >
636
+ </framework : metadata >
637
+ </framework : transition >
566
638
<!-- ... -->
567
639
</framework : workflow >
568
640
</framework : config >
@@ -595,6 +667,15 @@ requires:
595
667
'priority' => 0.5,
596
668
],
597
669
],
670
+ 'publish' => [
671
+ 'from' => 'reviewed',
672
+ 'to' => 'published',
673
+ 'metadata' => [
674
+ 'hour_limit' => 20,
675
+ 'explanation' => 'You can not publish after 8 PM.',
676
+ ],
677
+ ],
678
+ // ...
598
679
],
599
680
],
600
681
],
@@ -603,25 +684,26 @@ requires:
603
684
Then you can access this metadata in your controller as follows::
604
685
605
686
use Symfony\Component\Workflow\Registry;
687
+ use App\Entity\BlogPost;
606
688
607
- public function myController(Registry $registry, Article $article )
689
+ public function myController(Registry $registry, BlogPost $post )
608
690
{
609
- $workflow = $registry->get($article );
691
+ $workflow = $registry->get($post );
610
692
611
693
$title = $workflow
612
694
->getMetadataStore()
613
- ->getWorkflowMetadata()['title'] ?? false
695
+ ->getWorkflowMetadata()['title'] ?? 'Default title'
614
696
;
615
697
616
698
// or
617
699
$aTransition = $workflow->getDefinition()->getTransitions()[0];
618
700
$transitionTitle = $workflow
619
701
->getMetadataStore()
620
- ->getTransitionMetadata($aTransition)['title '] ?? false
702
+ ->getTransitionMetadata($aTransition)['priority '] ?? 0
621
703
;
622
704
}
623
705
624
- There is a shortcut that works with everything ::
706
+ There is a shortcut that works with every metadata level ::
625
707
626
708
$title = $workflow->getMetadataStore()->getMetadata('title');
627
709
@@ -633,76 +715,35 @@ In a :ref:`flash message <flash-messages>` in your controller::
633
715
$title = $workflow->getMetadataStore()->getMetadata('title', $transition);
634
716
$this->addFlash('info', "You have successfully applied the transition with title: '$title'");
635
717
636
- Metadata can also be accessed in a Listener, from the Event object.
637
-
638
- Using transition blockers you can return a user-friendly error message when you
639
- stop a transition from happening. In the example we get this message from the
640
- :class: `Symfony\\ Component\\ Workflow\\ Event\\ Event `'s metadata, giving you a
641
- central place to manage the text.
642
-
643
- This example has been simplified; in production you may prefer to use the
644
- :doc: `Translation </components/translation >` component to manage messages in one
645
- place::
646
-
647
- namespace App\Listener\Workflow\Task;
648
-
649
- use Symfony\Component\EventDispatcher\EventSubscriberInterface;
650
- use Symfony\Component\Workflow\Event\GuardEvent;
651
- use Symfony\Component\Workflow\TransitionBlocker;
652
-
653
- class OverdueGuard implements EventSubscriberInterface
654
- {
655
- public function guardPublish(GuardEvent $event)
656
- {
657
- $timeLimit = $event->getMetadata('time_limit', $event->getTransition());
658
-
659
- if (date('Hi') <= $timeLimit) {
660
- return;
661
- }
662
-
663
- $explanation = $event->getMetadata('explanation', $event->getTransition());
664
- $event->addTransitionBlocker(new TransitionBlocker($explanation , 0));
665
- }
666
-
667
- public static function getSubscribedEvents()
668
- {
669
- return [
670
- 'workflow.task.guard.done' => 'guardPublish',
671
- ];
672
- }
673
- }
674
-
675
- .. versionadded :: 4.1
676
-
677
- The transition blockers were introduced in Symfony 4.1.
718
+ Metadata can also be accessed in a Listener, from the :class: `Symfony\\ Component\\ Workflow\\ Event\\ Event ` object.
678
719
679
720
In Twig templates, metadata is available via the ``workflow_metadata() `` function:
680
721
681
722
.. code-block :: html+twig
682
723
683
- <h2>Metadata</h2>
724
+ <h2>Metadata of Blog Post </h2>
684
725
<p>
685
726
<strong>Workflow</strong>:<br >
686
- <code>{{ workflow_metadata(article , 'title') }}</code>
727
+ <code>{{ workflow_metadata(blog_post , 'title') }}</code>
687
728
</p>
688
729
<p>
689
730
<strong>Current place(s)</strong>
690
731
<ul>
691
- {% for place in workflow_marked_places(article ) %}
732
+ {% for place in workflow_marked_places(blog_post ) %}
692
733
<li>
693
734
{{ place }}:
694
- <code>{{ workflow_metadata(article , 'max_num_of_words', place) ?: 'Unlimited'}}</code>
735
+ <code>{{ workflow_metadata(blog_post , 'max_num_of_words', place) ?: 'Unlimited'}}</code>
695
736
</li>
696
737
{% endfor %}
697
738
</ul>
698
739
</p>
699
740
<p>
700
741
<strong>Enabled transition(s)</strong>
701
742
<ul>
702
- {% for transition in workflow_transitions(article ) %}
743
+ {% for transition in workflow_transitions(blog_post ) %}
703
744
<li>
704
745
{{ transition.name }}:
705
- <code>{{ workflow_metadata(article , 'priority', transition) ?: '0' }}</code>
746
+ <code>{{ workflow_metadata(blog_post , 'priority', transition) ?: '0' }}</code>
706
747
</li>
707
748
{% endfor %}
708
749
</ul>
0 commit comments