diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
index e8a11ad242..02677f149f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
@@ -23,10 +23,6 @@
kernel.view
kernel.exception
kernel.terminate
- security.authentication.success
- security.authentication.failure
- security.interactive_login
- security.switch_user
workflow.guard
workflow.leave
workflow.transition
diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json
index 8b8a56ecaa..d75499f3fa 100644
--- a/src/Symfony/Bundle/FrameworkBundle/composer.json
+++ b/src/Symfony/Bundle/FrameworkBundle/composer.json
@@ -78,6 +78,7 @@
"symfony/messenger": "<4.3",
"symfony/mime": "<4.4",
"symfony/property-info": "<3.4",
+ "symfony/security-bundle": "<4.4",
"symfony/serializer": "<4.2",
"symfony/stopwatch": "<3.4",
"symfony/translation": "<4.4",
diff --git a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
index ee8da39eac..24cf5569b8 100644
--- a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
+++ b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
@@ -33,7 +33,14 @@ use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\InMe
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\LdapFactory;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder;
+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;
/**
* Bundle.
@@ -68,5 +75,12 @@ class SecurityBundle extends Bundle
$container->addCompilerPass(new AddSessionDomainConstraintPass(), PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new RegisterCsrfTokenClearingLogoutHandlerPass());
$container->addCompilerPass(new RegisterTokenUsageTrackingPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 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,
+ ]));
}
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/EventBundle/DependencyInjection/EventExtension.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/EventBundle/DependencyInjection/EventExtension.php
new file mode 100644
index 0000000000..34159fd09b
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/EventBundle/DependencyInjection/EventExtension.php
@@ -0,0 +1,26 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\EventBundle\DependencyInjection;
+
+use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\EventBundle\EventSubscriber\TestSubscriber;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Extension\Extension;
+
+final class EventExtension extends Extension
+{
+ public function load(array $configs, ContainerBuilder $container): void
+ {
+ $container->register('test_subscriber', TestSubscriber::class)
+ ->setPublic(true)
+ ->addTag('kernel.event_subscriber');
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/EventBundle/EventBundle.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/EventBundle/EventBundle.php
new file mode 100644
index 0000000000..5c0ece872e
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/EventBundle/EventBundle.php
@@ -0,0 +1,18 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\EventBundle;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+final class EventBundle extends Bundle
+{
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/EventBundle/EventSubscriber/TestSubscriber.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/EventBundle/EventSubscriber/TestSubscriber.php
new file mode 100644
index 0000000000..0a907008ec
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/EventBundle/EventSubscriber/TestSubscriber.php
@@ -0,0 +1,38 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\EventBundle\EventSubscriber;
+
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+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;
+
+final class TestSubscriber implements EventSubscriberInterface
+{
+ public $calledMethods = [];
+
+ public static function getSubscribedEvents(): array
+ {
+ return [
+ AuthenticationSuccessEvent::class => 'onAuthenticationSuccess',
+ AuthenticationFailureEvent::class => 'onAuthenticationFailure',
+ InteractiveLoginEvent::class => 'onInteractiveLogin',
+ SwitchUserEvent::class => 'onSwitchUser',
+ ];
+ }
+
+ public function __call(string $name, array $arguments)
+ {
+ $this->calledMethods[$name] = ($this->calledMethods[$name] ?? 0) + 1;
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/EventAliasTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/EventAliasTest.php
new file mode 100644
index 0000000000..3e4fa76f2e
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/EventAliasTest.php
@@ -0,0 +1,48 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\Security\Core\AuthenticationEvents;
+use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
+use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
+use Symfony\Component\Security\Core\Exception\AuthenticationException;
+use Symfony\Component\Security\Core\User\UserInterface;
+use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
+use Symfony\Component\Security\Http\Event\SwitchUserEvent;
+use Symfony\Component\Security\Http\SecurityEvents;
+
+final class EventAliasTest extends AbstractWebTestCase
+{
+ public function testAliasedEvents(): void
+ {
+ $client = $this->createClient(['test_case' => 'AliasedEvents', 'root_config' => 'config.yml']);
+ $container = $client->getContainer();
+ $dispatcher = $container->get('event_dispatcher');
+
+ $dispatcher->dispatch(new AuthenticationSuccessEvent($this->createMock(TokenInterface::class)), AuthenticationEvents::AUTHENTICATION_SUCCESS);
+ $dispatcher->dispatch(new AuthenticationFailureEvent($this->createMock(TokenInterface::class), new AuthenticationException()), AuthenticationEvents::AUTHENTICATION_FAILURE);
+ $dispatcher->dispatch(new InteractiveLoginEvent($this->createMock(Request::class), $this->createMock(TokenInterface::class)), SecurityEvents::INTERACTIVE_LOGIN);
+ $dispatcher->dispatch(new SwitchUserEvent($this->createMock(Request::class), $this->createMock(UserInterface::class), $this->createMock(TokenInterface::class)), SecurityEvents::SWITCH_USER);
+
+ $this->assertEquals(
+ [
+ 'onAuthenticationSuccess' => 1,
+ 'onAuthenticationFailure' => 1,
+ 'onInteractiveLogin' => 1,
+ 'onSwitchUser' => 1,
+ ],
+ $container->get('test_subscriber')->calledMethods
+ );
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AliasedEvents/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AliasedEvents/bundles.php
new file mode 100644
index 0000000000..d7b7c498f8
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AliasedEvents/bundles.php
@@ -0,0 +1,20 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
+use Symfony\Bundle\SecurityBundle\SecurityBundle;
+use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\EventBundle\EventBundle;
+
+return [
+ new FrameworkBundle(),
+ new SecurityBundle(),
+ new EventBundle(),
+];
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AliasedEvents/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AliasedEvents/config.yml
new file mode 100644
index 0000000000..bdd94fd0af
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AliasedEvents/config.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: ./../config/framework.yml }
diff --git a/src/Symfony/Component/EventDispatcher/CHANGELOG.md b/src/Symfony/Component/EventDispatcher/CHANGELOG.md
index 7653cad1c0..d607b808a0 100644
--- a/src/Symfony/Component/EventDispatcher/CHANGELOG.md
+++ b/src/Symfony/Component/EventDispatcher/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========
+4.4.0
+-----
+
+* `AddEventAliasesPass` has been added, allowing applications and bundles to extend the event alias mapping used by `RegisterListenersPass`.
+
4.3.0
-----
diff --git a/src/Symfony/Component/EventDispatcher/DependencyInjection/AddEventAliasesPass.php b/src/Symfony/Component/EventDispatcher/DependencyInjection/AddEventAliasesPass.php
new file mode 100644
index 0000000000..c4ea50f786
--- /dev/null
+++ b/src/Symfony/Component/EventDispatcher/DependencyInjection/AddEventAliasesPass.php
@@ -0,0 +1,42 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\EventDispatcher\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * This pass allows bundles to extend the list of event aliases.
+ *
+ * @author Alexander M. Turek
+ */
+class AddEventAliasesPass implements CompilerPassInterface
+{
+ private $eventAliases;
+ private $eventAliasesParameter;
+
+ public function __construct(array $eventAliases, string $eventAliasesParameter = 'event_dispatcher.event_aliases')
+ {
+ $this->eventAliases = $eventAliases;
+ $this->eventAliasesParameter = $eventAliasesParameter;
+ }
+
+ public function process(ContainerBuilder $container): void
+ {
+ $eventAliases = $container->hasParameter($this->eventAliasesParameter) ? $container->getParameter($this->eventAliasesParameter) : [];
+
+ $container->setParameter(
+ $this->eventAliasesParameter,
+ array_merge($eventAliases, $this->eventAliases)
+ );
+ }
+}
diff --git a/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php b/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php
index 433762a4e8..c21d6ca1cf 100644
--- a/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php
+++ b/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php
@@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\EventDispatcher\DependencyInjection\AddEventAliasesPass;
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -67,6 +68,9 @@ class RegisterListenersPassTest extends TestCase
$builder->register('my_event_subscriber', AliasedSubscriber::class)
->addTag('kernel.event_subscriber');
+ $eventAliasPass = new AddEventAliasesPass([CustomEvent::class => 'custom_event']);
+ $eventAliasPass->process($builder);
+
$registerListenersPass = new RegisterListenersPass();
$registerListenersPass->process($builder);
@@ -79,6 +83,14 @@ class RegisterListenersPassTest extends TestCase
0,
],
],
+ [
+ 'addListener',
+ [
+ 'custom_event',
+ [new ServiceClosureArgument(new Reference('my_event_subscriber')), 'onCustomEvent'],
+ 0,
+ ],
+ ],
];
$this->assertEquals($expectedCalls, $builder->getDefinition('event_dispatcher')->getMethodCalls());
}
@@ -202,8 +214,12 @@ class RegisterListenersPassTest extends TestCase
$container = new ContainerBuilder();
$container->setParameter('event_dispatcher.event_aliases', [AliasedEvent::class => 'aliased_event']);
$container->register('foo', InvokableListenerService::class)->addTag('kernel.event_listener', ['event' => AliasedEvent::class, 'method' => 'onEvent']);
+ $container->register('bar', InvokableListenerService::class)->addTag('kernel.event_listener', ['event' => CustomEvent::class, 'method' => 'onEvent']);
$container->register('event_dispatcher');
+ $eventAliasPass = new AddEventAliasesPass([CustomEvent::class => 'custom_event']);
+ $eventAliasPass->process($container);
+
$registerListenersPass = new RegisterListenersPass();
$registerListenersPass->process($container);
@@ -217,6 +233,14 @@ class RegisterListenersPassTest extends TestCase
0,
],
],
+ [
+ 'addListener',
+ [
+ 'custom_event',
+ [new ServiceClosureArgument(new Reference('bar')), 'onEvent'],
+ 0,
+ ],
+ ],
];
$this->assertEquals($expectedCalls, $definition->getMethodCalls());
}
@@ -249,6 +273,7 @@ final class AliasedSubscriber implements EventSubscriberInterface
{
return [
AliasedEvent::class => 'onAliasedEvent',
+ CustomEvent::class => 'onCustomEvent',
];
}
}
@@ -256,3 +281,7 @@ final class AliasedSubscriber implements EventSubscriberInterface
final class AliasedEvent
{
}
+
+final class CustomEvent
+{
+}
diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json
index 01b77c8665..51f0d919a7 100644
--- a/src/Symfony/Component/HttpKernel/composer.json
+++ b/src/Symfony/Component/HttpKernel/composer.json
@@ -19,7 +19,7 @@
"php": "^7.1.3",
"symfony/error-handler": "^4.4|^5.0",
"symfony/error-renderer": "^4.4|^5.0",
- "symfony/event-dispatcher": "^4.3",
+ "symfony/event-dispatcher": "^4.4",
"symfony/http-foundation": "^4.4|^5.0",
"symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-php73": "^1.9",