diff --git a/src/Illuminate/Foundation/Events/DiscoverEvents.php b/src/Illuminate/Foundation/Events/DiscoverEvents.php index 0fa87135c9ff..6d07df058b3f 100644 --- a/src/Illuminate/Foundation/Events/DiscoverEvents.php +++ b/src/Illuminate/Foundation/Events/DiscoverEvents.php @@ -21,11 +21,23 @@ class DiscoverEvents */ public static function within($listenerPath, $basePath) { - return collect(static::getListenerEvents( + $listeners = collect(static::getListenerEvents( (new Finder)->files()->in($listenerPath), $basePath - ))->mapToDictionary(function ($event, $listener) { - return [$event => $listener]; - })->all(); + )); + + $discoveredEvents = []; + + foreach ($listeners as $listener => $events) { + foreach ($events as $event) { + if (! isset($discoveredEvents[$event])) { + $discoveredEvents[$event] = []; + } + + $discoveredEvents[$event][] = $listener; + } + } + + return $discoveredEvents; } /** @@ -59,7 +71,7 @@ protected static function getListenerEvents($listeners, $basePath) } $listenerEvents[$listener->name.'@'.$method->name] = - Reflector::getParameterClassName($method->getParameters()[0]); + Reflector::getParameterClassNames($method->getParameters()[0]); } } diff --git a/src/Illuminate/Support/Reflector.php b/src/Illuminate/Support/Reflector.php index 66392ca2f39a..0ec014fa5de7 100644 --- a/src/Illuminate/Support/Reflector.php +++ b/src/Illuminate/Support/Reflector.php @@ -5,6 +5,7 @@ use ReflectionClass; use ReflectionMethod; use ReflectionNamedType; +use ReflectionUnionType; class Reflector { @@ -69,6 +70,45 @@ public static function getParameterClassName($parameter) return; } + return static::getTypeName($parameter, $type); + } + + /** + * Get the class names of the given parameter's type, including union types. + * + * @param \ReflectionParameter $parameter + * @return array + */ + public static function getParameterClassNames($parameter) + { + $type = $parameter->getType(); + + if (! $type instanceof ReflectionUnionType) { + return [static::getParameterClassName($parameter)]; + } + + $unionTypes = []; + + foreach ($type->getTypes() as $listedType) { + if (! $listedType instanceof ReflectionNamedType || $listedType->isBuiltin()) { + continue; + } + + $unionTypes[] = static::getTypeName($parameter, $listedType); + } + + return $unionTypes; + } + + /** + * Get the given type's class name. + * + * @param \ReflectionParameter $parameter + * @param \ReflectionNamedType $type + * @return string + */ + protected static function getTypeName($parameter, $type) + { $name = $type->getName(); if (! is_null($class = $parameter->getDeclaringClass())) { diff --git a/tests/Integration/Foundation/DiscoverEventsTest.php b/tests/Integration/Foundation/DiscoverEventsTest.php index 7194d19640ba..9ef03c89f05c 100644 --- a/tests/Integration/Foundation/DiscoverEventsTest.php +++ b/tests/Integration/Foundation/DiscoverEventsTest.php @@ -8,6 +8,7 @@ use Illuminate\Tests\Integration\Foundation\Fixtures\EventDiscovery\Listeners\AbstractListener; use Illuminate\Tests\Integration\Foundation\Fixtures\EventDiscovery\Listeners\Listener; use Illuminate\Tests\Integration\Foundation\Fixtures\EventDiscovery\Listeners\ListenerInterface; +use Illuminate\Tests\Integration\Foundation\Fixtures\EventDiscovery\UnionListeners\UnionListener; use Orchestra\Testbench\TestCase; class DiscoverEventsTest extends TestCase @@ -30,4 +31,24 @@ class_alias(ListenerInterface::class, 'Tests\Integration\Foundation\Fixtures\Eve ], ], $events); } + + public function testUnionEventsCanBeDiscovered() + { + if (version_compare(phpversion(), '8.0.0', '<')) { + $this->markTestSkipped('Test uses union types.'); + } + + class_alias(UnionListener::class, 'Tests\Integration\Foundation\Fixtures\EventDiscovery\UnionListeners\UnionListener'); + + $events = DiscoverEvents::within(__DIR__.'/Fixtures/EventDiscovery/UnionListeners', getcwd()); + + $this->assertEquals([ + EventOne::class => [ + UnionListener::class.'@handle', + ], + EventTwo::class => [ + UnionListener::class.'@handle', + ], + ], $events); + } } diff --git a/tests/Integration/Foundation/Fixtures/EventDiscovery/UnionListeners/UnionListener.php b/tests/Integration/Foundation/Fixtures/EventDiscovery/UnionListeners/UnionListener.php new file mode 100644 index 000000000000..6911e9e1f71b --- /dev/null +++ b/tests/Integration/Foundation/Fixtures/EventDiscovery/UnionListeners/UnionListener.php @@ -0,0 +1,14 @@ +