Skip to content

Commit 8c65b3d

Browse files
authored
Support union types on event discovery (#38383)
* support union types on event discovery * add test * add test * fix tests * extract method
1 parent a668e6a commit 8c65b3d

File tree

4 files changed

+92
-5
lines changed

4 files changed

+92
-5
lines changed

src/Illuminate/Foundation/Events/DiscoverEvents.php

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,23 @@ class DiscoverEvents
2121
*/
2222
public static function within($listenerPath, $basePath)
2323
{
24-
return collect(static::getListenerEvents(
24+
$listeners = collect(static::getListenerEvents(
2525
(new Finder)->files()->in($listenerPath), $basePath
26-
))->mapToDictionary(function ($event, $listener) {
27-
return [$event => $listener];
28-
})->all();
26+
));
27+
28+
$discoveredEvents = [];
29+
30+
foreach ($listeners as $listener => $events) {
31+
foreach ($events as $event) {
32+
if (! isset($discoveredEvents[$event])) {
33+
$discoveredEvents[$event] = [];
34+
}
35+
36+
$discoveredEvents[$event][] = $listener;
37+
}
38+
}
39+
40+
return $discoveredEvents;
2941
}
3042

3143
/**
@@ -59,7 +71,7 @@ protected static function getListenerEvents($listeners, $basePath)
5971
}
6072

6173
$listenerEvents[$listener->name.'@'.$method->name] =
62-
Reflector::getParameterClassName($method->getParameters()[0]);
74+
Reflector::getParameterClassNames($method->getParameters()[0]);
6375
}
6476
}
6577

src/Illuminate/Support/Reflector.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use ReflectionClass;
66
use ReflectionMethod;
77
use ReflectionNamedType;
8+
use ReflectionUnionType;
89

910
class Reflector
1011
{
@@ -69,6 +70,45 @@ public static function getParameterClassName($parameter)
6970
return;
7071
}
7172

73+
return static::getTypeName($parameter, $type);
74+
}
75+
76+
/**
77+
* Get the class names of the given parameter's type, including union types.
78+
*
79+
* @param \ReflectionParameter $parameter
80+
* @return array
81+
*/
82+
public static function getParameterClassNames($parameter)
83+
{
84+
$type = $parameter->getType();
85+
86+
if (! $type instanceof ReflectionUnionType) {
87+
return [static::getParameterClassName($parameter)];
88+
}
89+
90+
$unionTypes = [];
91+
92+
foreach ($type->getTypes() as $listedType) {
93+
if (! $listedType instanceof ReflectionNamedType || $listedType->isBuiltin()) {
94+
continue;
95+
}
96+
97+
$unionTypes[] = static::getTypeName($parameter, $listedType);
98+
}
99+
100+
return $unionTypes;
101+
}
102+
103+
/**
104+
* Get the given type's class name.
105+
*
106+
* @param \ReflectionParameter $parameter
107+
* @param \ReflectionNamedType $type
108+
* @return string
109+
*/
110+
protected static function getTypeName($parameter, $type)
111+
{
72112
$name = $type->getName();
73113

74114
if (! is_null($class = $parameter->getDeclaringClass())) {

tests/Integration/Foundation/DiscoverEventsTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Illuminate\Tests\Integration\Foundation\Fixtures\EventDiscovery\Listeners\AbstractListener;
99
use Illuminate\Tests\Integration\Foundation\Fixtures\EventDiscovery\Listeners\Listener;
1010
use Illuminate\Tests\Integration\Foundation\Fixtures\EventDiscovery\Listeners\ListenerInterface;
11+
use Illuminate\Tests\Integration\Foundation\Fixtures\EventDiscovery\UnionListeners\UnionListener;
1112
use Orchestra\Testbench\TestCase;
1213

1314
class DiscoverEventsTest extends TestCase
@@ -30,4 +31,24 @@ class_alias(ListenerInterface::class, 'Tests\Integration\Foundation\Fixtures\Eve
3031
],
3132
], $events);
3233
}
34+
35+
public function testUnionEventsCanBeDiscovered()
36+
{
37+
if (version_compare(phpversion(), '8.0.0', '<')) {
38+
$this->markTestSkipped('Test uses union types.');
39+
}
40+
41+
class_alias(UnionListener::class, 'Tests\Integration\Foundation\Fixtures\EventDiscovery\UnionListeners\UnionListener');
42+
43+
$events = DiscoverEvents::within(__DIR__.'/Fixtures/EventDiscovery/UnionListeners', getcwd());
44+
45+
$this->assertEquals([
46+
EventOne::class => [
47+
UnionListener::class.'@handle',
48+
],
49+
EventTwo::class => [
50+
UnionListener::class.'@handle',
51+
],
52+
], $events);
53+
}
3354
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Integration\Foundation\Fixtures\EventDiscovery\UnionListeners;
4+
5+
use Illuminate\Tests\Integration\Foundation\Fixtures\EventDiscovery\Events\EventOne;
6+
use Illuminate\Tests\Integration\Foundation\Fixtures\EventDiscovery\Events\EventTwo;
7+
8+
class UnionListener
9+
{
10+
public function handle(EventOne|EventTwo $event)
11+
{
12+
//
13+
}
14+
}

0 commit comments

Comments
 (0)