@@ -602,15 +602,44 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
602602 @trigger_error (sprintf ('The "type" option of the "framework.workflows.%s" configuration entry must be defined since Symfony 3.3. The default value will be "state_machine" in Symfony 4.0. ' , $ name ), E_USER_DEPRECATED );
603603 }
604604 $ type = $ workflow ['type ' ];
605+ $ workflowId = sprintf ('%s.%s ' , $ type , $ name );
605606
607+ // Create transitions
606608 $ transitions = array ();
609+ $ guardsConfiguration = array ();
610+ // Global transition counter per workflow
611+ $ transitionCounter = 0 ;
607612 foreach ($ workflow ['transitions ' ] as $ transition ) {
608613 if ('workflow ' === $ type ) {
609- $ transitions [] = new Definition (Workflow \Transition::class, array ($ transition ['name ' ], $ transition ['from ' ], $ transition ['to ' ]));
614+ $ transitionDefinition = new Definition (Workflow \Transition::class, array ($ transition ['name ' ], $ transition ['from ' ], $ transition ['to ' ]));
615+ $ transitionDefinition ->setPublic (false );
616+ $ transitionId = sprintf ('%s.transition.%s ' , $ workflowId , $ transitionCounter ++);
617+ $ container ->setDefinition ($ transitionId , $ transitionDefinition );
618+ $ transitions [] = new Reference ($ transitionId );
619+ if (isset ($ transition ['guard ' ])) {
620+ $ configuration = new Definition (Workflow \EventListener \GuardExpression::class);
621+ $ configuration ->addArgument (new Reference ($ transitionId ));
622+ $ configuration ->addArgument ($ transition ['guard ' ]);
623+ $ configuration ->setPublic (false );
624+ $ eventName = sprintf ('workflow.%s.guard.%s ' , $ name , $ transition ['name ' ]);
625+ $ guardsConfiguration [$ eventName ][] = $ configuration ;
626+ }
610627 } elseif ('state_machine ' === $ type ) {
611628 foreach ($ transition ['from ' ] as $ from ) {
612629 foreach ($ transition ['to ' ] as $ to ) {
613- $ transitions [] = new Definition (Workflow \Transition::class, array ($ transition ['name ' ], $ from , $ to ));
630+ $ transitionDefinition = new Definition (Workflow \Transition::class, array ($ transition ['name ' ], $ from , $ to ));
631+ $ transitionDefinition ->setPublic (false );
632+ $ transitionId = sprintf ('%s.transition.%s ' , $ workflowId , $ transitionCounter ++);
633+ $ container ->setDefinition ($ transitionId , $ transitionDefinition );
634+ $ transitions [] = new Reference ($ transitionId );
635+ if (isset ($ transition ['guard ' ])) {
636+ $ configuration = new Definition (Workflow \EventListener \GuardExpression::class);
637+ $ configuration ->addArgument (new Reference ($ transitionId ));
638+ $ configuration ->addArgument ($ transition ['guard ' ]);
639+ $ configuration ->setPublic (false );
640+ $ eventName = sprintf ('workflow.%s.guard.%s ' , $ name , $ transition ['name ' ]);
641+ $ guardsConfiguration [$ eventName ][] = $ configuration ;
642+ }
614643 }
615644 }
616645 }
@@ -641,7 +670,6 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
641670 }
642671
643672 // Create Workflow
644- $ workflowId = sprintf ('%s.%s ' , $ type , $ name );
645673 $ workflowDefinition = new ChildDefinition (sprintf ('%s.abstract ' , $ type ));
646674 $ workflowDefinition ->replaceArgument (0 , new Reference (sprintf ('%s.definition ' , $ workflowId )));
647675 if (isset ($ markingStoreDefinition )) {
@@ -677,16 +705,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
677705 }
678706
679707 // Add Guard Listener
680- $ guard = new Definition (Workflow \EventListener \GuardListener::class);
681- $ guard ->setPrivate (true );
682- $ configuration = array ();
683- foreach ($ workflow ['transitions ' ] as $ config ) {
684- $ transitionName = $ config ['name ' ];
685-
686- if (!isset ($ config ['guard ' ])) {
687- continue ;
688- }
689-
708+ if ($ guardsConfiguration ) {
690709 if (!class_exists (ExpressionLanguage::class)) {
691710 throw new LogicException ('Cannot guard workflows as the ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language". ' );
692711 }
@@ -695,20 +714,21 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
695714 throw new LogicException ('Cannot guard workflows as the Security component is not installed. Try running "composer require symfony/security". ' );
696715 }
697716
698- $ eventName = sprintf ('workflow.%s.guard.%s ' , $ name , $ transitionName );
699- $ guard ->addTag ('kernel.event_listener ' , array ('event ' => $ eventName , 'method ' => 'onTransition ' ));
700- $ configuration [$ eventName ] = $ config ['guard ' ];
701- }
702- if ($ configuration ) {
717+ $ guard = new Definition (Workflow \EventListener \GuardListener::class);
718+ $ guard ->setPrivate (true );
719+
703720 $ guard ->setArguments (array (
704- $ configuration ,
721+ $ guardsConfiguration ,
705722 new Reference ('workflow.security.expression_language ' ),
706723 new Reference ('security.token_storage ' ),
707724 new Reference ('security.authorization_checker ' ),
708725 new Reference ('security.authentication.trust_resolver ' ),
709726 new Reference ('security.role_hierarchy ' ),
710727 new Reference ('validator ' , ContainerInterface::NULL_ON_INVALID_REFERENCE ),
711728 ));
729+ foreach ($ guardsConfiguration as $ eventName => $ config ) {
730+ $ guard ->addTag ('kernel.event_listener ' , array ('event ' => $ eventName , 'method ' => 'onTransition ' ));
731+ }
712732
713733 $ container ->setDefinition (sprintf ('%s.listener.guard ' , $ workflowId ), $ guard );
714734 $ container ->setParameter ('workflow.has_guard_listeners ' , true );
0 commit comments