From 28e6f6f72cbd7f8569f9e0a19c68bb97985ad35d Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Tue, 16 Jun 2020 01:07:23 +0200 Subject: [PATCH] Move event alias mappings to their components. --- .../Resources/config/services.php | 58 +++---------- .../Bundle/FrameworkBundle/composer.json | 10 +-- .../Bundle/SecurityBundle/SecurityBundle.php | 14 +-- .../Bundle/SecurityBundle/composer.json | 4 +- .../Component/Console/ConsoleEvents.php | 15 ++++ .../Console/Tests/ConsoleEventsTest.php | 86 +++++++++++++++++++ src/Symfony/Component/Form/FormEvents.php | 19 ++++ .../Component/HttpKernel/KernelEvents.php | 25 ++++++ .../Security/Core/AuthenticationEvents.php | 13 +++ .../Security/Http/SecurityEvents.php | 13 +++ .../Component/Workflow/WorkflowEvents.php | 23 +++++ 11 files changed, 215 insertions(+), 65 deletions(-) create mode 100644 src/Symfony/Component/Console/Tests/ConsoleEventsTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php index 680afbcf77172..a5ffe1c072400 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php @@ -14,9 +14,7 @@ use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache; use Symfony\Component\Config\Resource\SelfCheckingResourceChecker; use Symfony\Component\Config\ResourceCheckerConfigCacheFactory; -use Symfony\Component\Console\Event\ConsoleCommandEvent; -use Symfony\Component\Console\Event\ConsoleErrorEvent; -use Symfony\Component\Console\Event\ConsoleTerminateEvent; +use Symfony\Component\Console\ConsoleEvents; use Symfony\Component\DependencyInjection\Config\ContainerParametersResourceChecker; use Symfony\Component\DependencyInjection\EnvVarProcessor; use Symfony\Component\DependencyInjection\ParameterBag\ContainerBag; @@ -26,70 +24,34 @@ use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface as EventDispatcherInterfaceComponentAlias; use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Form\Event\PostSetDataEvent; -use Symfony\Component\Form\Event\PostSubmitEvent; -use Symfony\Component\Form\Event\PreSetDataEvent; -use Symfony\Component\Form\Event\PreSubmitEvent; -use Symfony\Component\Form\Event\SubmitEvent; +use Symfony\Component\Form\FormEvents; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\UrlHelper; use Symfony\Component\HttpKernel\CacheClearer\ChainCacheClearer; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate; use Symfony\Component\HttpKernel\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter; -use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; -use Symfony\Component\HttpKernel\Event\ControllerEvent; -use Symfony\Component\HttpKernel\Event\ExceptionEvent; -use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\Event\TerminateEvent; -use Symfony\Component\HttpKernel\Event\ViewEvent; use Symfony\Component\HttpKernel\EventListener\LocaleAwareListener; use Symfony\Component\HttpKernel\HttpCache\Store; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\HttpKernel\UriSigner; use Symfony\Component\String\LazyString; use Symfony\Component\String\Slugger\AsciiSlugger; use Symfony\Component\String\Slugger\SluggerInterface; -use Symfony\Component\Workflow\Event\AnnounceEvent; -use Symfony\Component\Workflow\Event\CompletedEvent; -use Symfony\Component\Workflow\Event\EnteredEvent; -use Symfony\Component\Workflow\Event\EnterEvent; -use Symfony\Component\Workflow\Event\GuardEvent; -use Symfony\Component\Workflow\Event\LeaveEvent; -use Symfony\Component\Workflow\Event\TransitionEvent; +use Symfony\Component\Workflow\WorkflowEvents; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; return static function (ContainerConfigurator $container) { // this parameter is used at compile time in RegisterListenersPass - $container->parameters()->set('event_dispatcher.event_aliases', [ - ConsoleCommandEvent::class => 'console.command', - ConsoleErrorEvent::class => 'console.error', - ConsoleTerminateEvent::class => 'console.terminate', - PreSubmitEvent::class => 'form.pre_submit', - SubmitEvent::class => 'form.submit', - PostSubmitEvent::class => 'form.post_submit', - PreSetDataEvent::class => 'form.pre_set_data', - PostSetDataEvent::class => 'form.post_set_data', - ControllerArgumentsEvent::class => 'kernel.controller_arguments', - ControllerEvent::class => 'kernel.controller', - ResponseEvent::class => 'kernel.response', - FinishRequestEvent::class => 'kernel.finish_request', - RequestEvent::class => 'kernel.request', - ViewEvent::class => 'kernel.view', - ExceptionEvent::class => 'kernel.exception', - TerminateEvent::class => 'kernel.terminate', - GuardEvent::class => 'workflow.guard', - LeaveEvent::class => 'workflow.leave', - TransitionEvent::class => 'workflow.transition', - EnterEvent::class => 'workflow.enter', - EnteredEvent::class => 'workflow.entered', - CompletedEvent::class => 'workflow.completed', - AnnounceEvent::class => 'workflow.announce', - ]); + $container->parameters()->set('event_dispatcher.event_aliases', array_merge( + class_exists(ConsoleEvents::class) ? ConsoleEvents::ALIASES : [], + class_exists(FormEvents::class) ? FormEvents::ALIASES : [], + KernelEvents::ALIASES, + class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : [] + )); $container->services() diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 861df75f0bb85..0d84c344aa422 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -36,12 +36,12 @@ "doctrine/cache": "~1.0", "symfony/asset": "^5.1", "symfony/browser-kit": "^4.4|^5.0", - "symfony/console": "^4.4|^5.0", + "symfony/console": "^5.2", "symfony/css-selector": "^4.4|^5.0", "symfony/dom-crawler": "^4.4|^5.0", "symfony/dotenv": "^5.1", "symfony/polyfill-intl-icu": "~1.0", - "symfony/form": "^4.4|^5.0", + "symfony/form": "^5.2", "symfony/expression-language": "^4.4|^5.0", "symfony/http-client": "^4.4|^5.0", "symfony/lock": "^4.4|^5.0", @@ -58,7 +58,7 @@ "symfony/translation": "^5.0", "symfony/twig-bundle": "^4.4|^5.0", "symfony/validator": "^4.4|^5.0", - "symfony/workflow": "^4.4|^5.0", + "symfony/workflow": "^5.2", "symfony/yaml": "^4.4|^5.0", "symfony/property-info": "^4.4|^5.0", "symfony/web-link": "^4.4|^5.0", @@ -73,7 +73,7 @@ "phpunit/phpunit": "<5.4.3", "symfony/asset": "<5.1", "symfony/browser-kit": "<4.4", - "symfony/console": "<4.4", + "symfony/console": "<5.2", "symfony/dotenv": "<5.1", "symfony/dom-crawler": "<4.4", "symfony/http-client": "<4.4", @@ -90,7 +90,7 @@ "symfony/twig-bundle": "<4.4", "symfony/validator": "<4.4", "symfony/web-profiler-bundle": "<4.4", - "symfony/workflow": "<4.4" + "symfony/workflow": "<5.2" }, "suggest": { "ext-apcu": "For best performance of the system caches", diff --git a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php index 9388ec3331f14..58b7d479170a0 100644 --- a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php +++ b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php @@ -37,10 +37,6 @@ use Symfony\Component\EventDispatcher\DependencyInjection\AddEventAliasesPass; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\Security\Core\AuthenticationEvents; -use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent; -use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent; -use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; -use Symfony\Component\Security\Http\Event\SwitchUserEvent; use Symfony\Component\Security\Http\SecurityEvents; /** @@ -79,11 +75,9 @@ public function build(ContainerBuilder $container) // must be registered after RegisterListenersPass (in the FrameworkBundle) $container->addCompilerPass(new RegisterGlobalSecurityEventListenersPass(), PassConfig::TYPE_BEFORE_REMOVING, -200); - $container->addCompilerPass(new AddEventAliasesPass([ - AuthenticationSuccessEvent::class => AuthenticationEvents::AUTHENTICATION_SUCCESS, - AuthenticationFailureEvent::class => AuthenticationEvents::AUTHENTICATION_FAILURE, - InteractiveLoginEvent::class => SecurityEvents::INTERACTIVE_LOGIN, - SwitchUserEvent::class => SecurityEvents::SWITCH_USER, - ])); + $container->addCompilerPass(new AddEventAliasesPass(array_merge( + AuthenticationEvents::ALIASES, + SecurityEvents::ALIASES + ))); } } diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 7c7c3a992b2b5..6e93ae9266558 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -23,10 +23,10 @@ "symfony/event-dispatcher": "^5.1", "symfony/http-kernel": "^5.0", "symfony/polyfill-php80": "^1.15", - "symfony/security-core": "^5.1", + "symfony/security-core": "^5.2", "symfony/security-csrf": "^4.4|^5.0", "symfony/security-guard": "^5.1", - "symfony/security-http": "^5.1,>=5.1.2" + "symfony/security-http": "^5.2" }, "require-dev": { "doctrine/doctrine-bundle": "^2.0", diff --git a/src/Symfony/Component/Console/ConsoleEvents.php b/src/Symfony/Component/Console/ConsoleEvents.php index 4975643aedf2b..2c1bb46cdeefb 100644 --- a/src/Symfony/Component/Console/ConsoleEvents.php +++ b/src/Symfony/Component/Console/ConsoleEvents.php @@ -11,6 +11,10 @@ namespace Symfony\Component\Console; +use Symfony\Component\Console\Event\ConsoleCommandEvent; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Event\ConsoleTerminateEvent; + /** * Contains all events dispatched by an Application. * @@ -44,4 +48,15 @@ final class ConsoleEvents * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent") */ const ERROR = 'console.error'; + + /** + * Event aliases. + * + * These aliases can be consumed by RegisterListenersPass. + */ + const ALIASES = [ + ConsoleCommandEvent::class => self::COMMAND, + ConsoleErrorEvent::class => self::ERROR, + ConsoleTerminateEvent::class => self::TERMINATE, + ]; } diff --git a/src/Symfony/Component/Console/Tests/ConsoleEventsTest.php b/src/Symfony/Component/Console/Tests/ConsoleEventsTest.php new file mode 100644 index 0000000000000..45eb2220d1743 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/ConsoleEventsTest.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\ConsoleEvents; +use Symfony\Component\Console\Event\ConsoleCommandEvent; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Event\ConsoleTerminateEvent; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Tester\ApplicationTester; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +class ConsoleEventsTest extends TestCase +{ + public function testEventAliases() + { + $container = new ContainerBuilder(); + $container->setParameter('event_dispatcher.event_aliases', ConsoleEvents::ALIASES); + $container->addCompilerPass(new RegisterListenersPass()); + + $container->register('event_dispatcher', EventDispatcher::class); + $container->register('tracer', EventTraceSubscriber::class) + ->setPublic(true) + ->addTag('kernel.event_subscriber'); + $container->register('failing_command', FailingCommand::class); + $container->register('application', Application::class) + ->setPublic(true) + ->addMethodCall('setAutoExit', [false]) + ->addMethodCall('setDispatcher', [new Reference('event_dispatcher')]) + ->addMethodCall('add', [new Reference('failing_command')]) + ; + + $container->compile(); + + $tester = new ApplicationTester($container->get('application')); + $tester->run(['fail']); + + $this->assertSame([ConsoleCommandEvent::class, ConsoleErrorEvent::class, ConsoleTerminateEvent::class], $container->get('tracer')->observedEvents); + } +} + +class EventTraceSubscriber implements EventSubscriberInterface +{ + public $observedEvents = []; + + public static function getSubscribedEvents(): array + { + return [ + ConsoleCommandEvent::class => 'observe', + ConsoleErrorEvent::class => 'observe', + ConsoleTerminateEvent::class => 'observe', + ]; + } + + public function observe(object $event): void + { + $this->observedEvents[] = get_debug_type($event); + } +} + +class FailingCommand extends Command +{ + protected static $defaultName = 'fail'; + + protected function execute(InputInterface $input, OutputInterface $output): int + { + throw new \RuntimeException('I failed. Sorry.'); + } +} diff --git a/src/Symfony/Component/Form/FormEvents.php b/src/Symfony/Component/Form/FormEvents.php index 2dc47e6a634b6..f7ca06c37a59c 100644 --- a/src/Symfony/Component/Form/FormEvents.php +++ b/src/Symfony/Component/Form/FormEvents.php @@ -11,6 +11,12 @@ namespace Symfony\Component\Form; +use Symfony\Component\Form\Event\PostSetDataEvent; +use Symfony\Component\Form\Event\PostSubmitEvent; +use Symfony\Component\Form\Event\PreSetDataEvent; +use Symfony\Component\Form\Event\PreSubmitEvent; +use Symfony\Component\Form\Event\SubmitEvent; + /** * To learn more about how form events work check the documentation * entry at {@link https://symfony.com/doc/any/components/form/form_events.html}. @@ -88,6 +94,19 @@ final class FormEvents */ const POST_SET_DATA = 'form.post_set_data'; + /** + * Event aliases. + * + * These aliases can be consumed by RegisterListenersPass. + */ + const ALIASES = [ + PreSubmitEvent::class => self::PRE_SUBMIT, + SubmitEvent::class => self::SUBMIT, + PostSubmitEvent::class => self::POST_SUBMIT, + PreSetDataEvent::class => self::PRE_SET_DATA, + PostSetDataEvent::class => self::POST_SET_DATA, + ]; + private function __construct() { } diff --git a/src/Symfony/Component/HttpKernel/KernelEvents.php b/src/Symfony/Component/HttpKernel/KernelEvents.php index 0e1c9083e53af..848990cb9a3c0 100644 --- a/src/Symfony/Component/HttpKernel/KernelEvents.php +++ b/src/Symfony/Component/HttpKernel/KernelEvents.php @@ -11,6 +11,15 @@ namespace Symfony\Component\HttpKernel; +use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; +use Symfony\Component\HttpKernel\Event\ControllerEvent; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; +use Symfony\Component\HttpKernel\Event\FinishRequestEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\Event\TerminateEvent; +use Symfony\Component\HttpKernel\Event\ViewEvent; + /** * Contains all events thrown in the HttpKernel component. * @@ -100,4 +109,20 @@ final class KernelEvents * @Event("Symfony\Component\HttpKernel\Event\TerminateEvent") */ const TERMINATE = 'kernel.terminate'; + + /** + * Event aliases. + * + * These aliases can be consumed by RegisterListenersPass. + */ + const ALIASES = [ + ControllerArgumentsEvent::class => self::CONTROLLER_ARGUMENTS, + ControllerEvent::class => self::CONTROLLER, + ResponseEvent::class => self::RESPONSE, + FinishRequestEvent::class => self::FINISH_REQUEST, + RequestEvent::class => self::REQUEST, + ViewEvent::class => self::VIEW, + ExceptionEvent::class => self::EXCEPTION, + TerminateEvent::class => self::TERMINATE, + ]; } diff --git a/src/Symfony/Component/Security/Core/AuthenticationEvents.php b/src/Symfony/Component/Security/Core/AuthenticationEvents.php index 06358275f7310..75b932d1d0884 100644 --- a/src/Symfony/Component/Security/Core/AuthenticationEvents.php +++ b/src/Symfony/Component/Security/Core/AuthenticationEvents.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Security\Core; +use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent; +use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent; + final class AuthenticationEvents { /** @@ -28,4 +31,14 @@ final class AuthenticationEvents * @Event("Symfony\Component\Security\Core\Event\AuthenticationFailureEvent") */ const AUTHENTICATION_FAILURE = 'security.authentication.failure'; + + /** + * Event aliases. + * + * These aliases can be consumed by RegisterListenersPass. + */ + const ALIASES = [ + AuthenticationSuccessEvent::class => self::AUTHENTICATION_SUCCESS, + AuthenticationFailureEvent::class => self::AUTHENTICATION_FAILURE, + ]; } diff --git a/src/Symfony/Component/Security/Http/SecurityEvents.php b/src/Symfony/Component/Security/Http/SecurityEvents.php index 5c866f36555b4..6a7247f43f32b 100644 --- a/src/Symfony/Component/Security/Http/SecurityEvents.php +++ b/src/Symfony/Component/Security/Http/SecurityEvents.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Security\Http; +use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; +use Symfony\Component\Security\Http\Event\SwitchUserEvent; + final class SecurityEvents { /** @@ -31,4 +34,14 @@ final class SecurityEvents * @Event("Symfony\Component\Security\Http\Event\SwitchUserEvent") */ const SWITCH_USER = 'security.switch_user'; + + /** + * Event aliases. + * + * These aliases can be consumed by RegisterListenersPass. + */ + const ALIASES = [ + InteractiveLoginEvent::class => self::INTERACTIVE_LOGIN, + SwitchUserEvent::class => self::SWITCH_USER, + ]; } diff --git a/src/Symfony/Component/Workflow/WorkflowEvents.php b/src/Symfony/Component/Workflow/WorkflowEvents.php index 44678dcb88b7d..d647830540698 100644 --- a/src/Symfony/Component/Workflow/WorkflowEvents.php +++ b/src/Symfony/Component/Workflow/WorkflowEvents.php @@ -11,6 +11,14 @@ namespace Symfony\Component\Workflow; +use Symfony\Component\Workflow\Event\AnnounceEvent; +use Symfony\Component\Workflow\Event\CompletedEvent; +use Symfony\Component\Workflow\Event\EnteredEvent; +use Symfony\Component\Workflow\Event\EnterEvent; +use Symfony\Component\Workflow\Event\GuardEvent; +use Symfony\Component\Workflow\Event\LeaveEvent; +use Symfony\Component\Workflow\Event\TransitionEvent; + /** * To learn more about how workflow events work, check the documentation * entry at {@link https://symfony.com/doc/current/workflow/usage.html#using-events}. @@ -52,6 +60,21 @@ final class WorkflowEvents */ const TRANSITION = 'workflow.transition'; + /** + * Event aliases. + * + * These aliases can be consumed by RegisterListenersPass. + */ + const ALIASES = [ + GuardEvent::class => self::GUARD, + LeaveEvent::class => self::LEAVE, + TransitionEvent::class => self::TRANSITION, + EnterEvent::class => self::ENTER, + EnteredEvent::class => self::ENTERED, + CompletedEvent::class => self::COMPLETED, + AnnounceEvent::class => self::ANNOUNCE, + ]; + private function __construct() { }