Skip to content

Commit f17cfd9

Browse files
committed
Add listener config to EventManager
1 parent f35ad88 commit f17cfd9

File tree

4 files changed

+57
-9
lines changed

4 files changed

+57
-9
lines changed

phpcs.xml.dist

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
<file>src</file>
1616
<file>tests</file>
1717

18-
<rule ref="Doctrine" />
18+
<rule ref="Doctrine">
19+
<exclude name="Squiz.Commenting.FunctionComment.ExtraParamComment" />
20+
</rule>
1921

2022
<rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint">
2123
<!-- This interface is commonly implemented by userland code.

phpstan.neon.dist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ parameters:
33
paths:
44
- src/
55
- tests/
6+
ignoreErrors:
7+
- identifier: parameter.notFound

src/EventManager.php

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace Doctrine\Common;
66

7+
use function func_get_arg;
8+
use function func_num_args;
79
use function spl_object_hash;
810

911
/**
@@ -21,6 +23,14 @@ class EventManager
2123
*/
2224
private array $listeners = [];
2325

26+
/**
27+
* Map of registered listener configurations.
28+
* <hash><event> => <configuration>
29+
*
30+
* @var array<string, array<string, array{method?: string}>>
31+
*/
32+
private array $listenerConfigs = [];
33+
2434
/**
2535
* Dispatches an event to all registered listeners.
2636
*
@@ -37,8 +47,10 @@ public function dispatchEvent(string $eventName, EventArgs|null $eventArgs = nul
3747

3848
$eventArgs ??= EventArgs::getEmptyInstance();
3949

40-
foreach ($this->listeners[$eventName] as $listener) {
41-
$listener->$eventName($eventArgs);
50+
foreach ($this->listeners[$eventName] as $hash => $listener) {
51+
$method = $this->listenerConfigs[$hash][$eventName]['method'] ?? $eventName;
52+
53+
$listener->$method($eventArgs);
4254
}
4355
}
4456

@@ -75,18 +87,23 @@ public function hasListeners(string $event): bool
7587
/**
7688
* Adds an event listener that listens on the specified events.
7789
*
78-
* @param string|string[] $events The event(s) to listen on.
79-
* @param object $listener The listener object.
90+
* @param string|string[] $events The event(s) to listen on.
91+
* @param object $listener The listener object.
92+
* @param array<string, array{method?: string}> $listenerConfig The listener configuration, indexed by event.
8093
*/
81-
public function addEventListener(string|array $events, object $listener): void
94+
public function addEventListener(string|array $events, object $listener, /* array $listenerConfig = [] */): void
8295
{
96+
/** @var array<string, array{method?: string}> $listenerConfig */
97+
$listenerConfig = 3 <= func_num_args() ? func_get_arg(2) : [];
98+
8399
// Picks the hash code related to that listener
84100
$hash = spl_object_hash($listener);
85101

86102
foreach ((array) $events as $event) {
87103
// Overrides listener if a previous one was associated already
88104
// Prevents duplicate listeners on same event (same instance only)
89-
$this->listeners[$event][$hash] = $listener;
105+
$this->listeners[$event][$hash] = $listener;
106+
$this->listenerConfigs[$hash][$event] = $listenerConfig[$event] ?? [];
90107
}
91108
}
92109

@@ -100,6 +117,7 @@ public function removeEventListener(string|array $events, object $listener): voi
100117
// Picks the hash code related to that listener
101118
$hash = spl_object_hash($listener);
102119

120+
unset($this->listenerConfigs[$hash]);
103121
foreach ((array) $events as $event) {
104122
unset($this->listeners[$event][$hash]);
105123
}

tests/EventManagerTest.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ class EventManagerTest extends TestCase
1919
private const POST_FOO = 'postFoo';
2020
private const PRE_BAR = 'preBar';
2121

22-
private bool $preFooInvoked = false;
23-
private bool $postFooInvoked = false;
22+
private bool $preFooInvoked = false;
23+
private bool $postFooInvoked = false;
24+
private bool $customMethodInvoked = false;
2425
private EventManager $eventManager;
2526

2627
protected function setUp(): void
@@ -48,6 +49,17 @@ public function testAddEventListener(): void
4849
self::assertSame(['preFoo', 'postFoo'], array_keys($this->eventManager->getAllListeners()));
4950
}
5051

52+
public function testAddEventListenerWithConfig(): void
53+
{
54+
$this->eventManager->addEventListener(['preFoo', 'postFoo'], $this, ['preFoo' => ['method' => 'customMethod']]);
55+
self::assertTrue($this->eventManager->hasListeners(self::PRE_FOO));
56+
self::assertTrue($this->eventManager->hasListeners(self::POST_FOO));
57+
self::assertCount(1, $this->eventManager->getListeners(self::PRE_FOO));
58+
self::assertCount(1, $this->eventManager->getListeners(self::POST_FOO));
59+
self::assertCount(2, $this->eventManager->getAllListeners());
60+
self::assertSame(['preFoo', 'postFoo'], array_keys($this->eventManager->getAllListeners()));
61+
}
62+
5163
public function testDispatchEvent(): void
5264
{
5365
$this->eventManager->addEventListener(['preFoo', 'postFoo'], $this);
@@ -56,6 +68,15 @@ public function testDispatchEvent(): void
5668
self::assertFalse($this->postFooInvoked);
5769
}
5870

71+
public function testDispatchEventWithConfig(): void
72+
{
73+
$this->eventManager->addEventListener(['preFoo', 'postFoo'], $this, ['preFoo' => ['method' => 'customMethod']]);
74+
$this->eventManager->dispatchEvent(self::PRE_FOO);
75+
self::assertTrue($this->customMethodInvoked);
76+
self::assertFalse($this->preFooInvoked);
77+
self::assertFalse($this->postFooInvoked);
78+
}
79+
5980
public function testRemoveEventListener(): void
6081
{
6182
$this->eventManager->addEventListener(['preBar'], $this);
@@ -107,6 +128,11 @@ public function postFoo(EventArgs $e): void
107128
{
108129
$this->postFooInvoked = true;
109130
}
131+
132+
public function customMethod(EventArgs $e): void
133+
{
134+
$this->customMethodInvoked = true;
135+
}
110136
}
111137

112138
class TestEventSubscriber implements EventSubscriber

0 commit comments

Comments
 (0)