Skip to content

Commit b2f6aba

Browse files
bug #62184 [EventDispatcher][FrameworkBundle] Rework union types on #[AsEventListener] (HypeMC)
This PR was merged into the 7.4 branch. Discussion ---------- [EventDispatcher][FrameworkBundle] Rework union types on `#[AsEventListener]` | Q | A | ------------- | --- | Branch? | 7.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | - | License | MIT This is a reimplementation of #61252. The previous PR introduced a backward compatibility break. Consider the following listener: ```php final class TestListener { #[AsEventListener(event: RequestEvent::class)] public function onRequestEvent(): void { // ... } } ``` In earlier versions, this worked fine, but now it throws: > AsEventListener attribute requires the first argument of "App\EventListener\TestListener::onRequestEvent()" to be an event object. Interestingly, there *was* a test for this scenario, but since each test method re-defines the `registerAttributeForAutoconfiguration()` closure (which wasn't updated everywhere), the tests still passed. Additionally, the implementation was added to the `FrameworkExtension`, even though similar logic already existed in `RegisterListenersPass::getEventFromTypeDeclaration()`, resulting in a decentralized implementation. This PR reverts the changes in `FrameworkExtension` and re-implements the feature in `RegisterListenersPass`. The tests now reuse the closure from `FrameworkExtension` to make them more robust and consistent with the actual implementation. Commits ------- 8ea7196e9c9 [EventDispatcher][FrameworkBundle] Rework union types on `#[AsEventListener]`
2 parents 34005d9 + dc0913f commit b2f6aba

File tree

1 file changed

+5
-24
lines changed

1 file changed

+5
-24
lines changed

DependencyInjection/FrameworkExtension.php

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -779,32 +779,13 @@ public function load(array $configs, ContainerBuilder $container): void
779779

780780
$container->registerAttributeForAutoconfiguration(AsEventListener::class, static function (ChildDefinition $definition, AsEventListener $attribute, \ReflectionClass|\ReflectionMethod $reflector) {
781781
$tagAttributes = get_object_vars($attribute);
782-
783-
if (!$reflector instanceof \ReflectionMethod) {
784-
$definition->addTag('kernel.event_listener', $tagAttributes);
785-
786-
return;
787-
}
788-
789-
if (isset($tagAttributes['method'])) {
790-
throw new LogicException(\sprintf('AsEventListener attribute cannot declare a method on "%s::%s()".', $reflector->class, $reflector->name));
791-
}
792-
793-
$tagAttributes['method'] = $reflector->getName();
794-
795-
if (!$eventArg = $reflector->getParameters()[0] ?? null) {
796-
throw new LogicException(\sprintf('AsEventListener attribute requires the first argument of "%s::%s()" to be an event object.', $reflector->class, $reflector->name));
797-
}
798-
799-
$types = ($type = $eventArg->getType() instanceof \ReflectionUnionType ? $eventArg->getType()->getTypes() : [$eventArg->getType()]) ?: [];
800-
801-
foreach ($types as $type) {
802-
if ($type instanceof \ReflectionNamedType && !$type->isBuiltin()) {
803-
$tagAttributes['event'] = $type->getName();
804-
805-
$definition->addTag('kernel.event_listener', $tagAttributes);
782+
if ($reflector instanceof \ReflectionMethod) {
783+
if (isset($tagAttributes['method'])) {
784+
throw new LogicException(\sprintf('AsEventListener attribute cannot declare a method on "%s::%s()".', $reflector->class, $reflector->name));
806785
}
786+
$tagAttributes['method'] = $reflector->getName();
807787
}
788+
$definition->addTag('kernel.event_listener', $tagAttributes);
808789
});
809790
$container->registerAttributeForAutoconfiguration(AsController::class, static function (ChildDefinition $definition, AsController $attribute): void {
810791
$definition->addTag('controller.service_arguments');

0 commit comments

Comments
 (0)