Skip to content

Commit

Permalink
Respect parent class contract in ContainerAwareDoctrineEventManager
Browse files Browse the repository at this point in the history
  • Loading branch information
Koc committed May 7, 2019
1 parent e197c9a commit 28df79d
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 29 deletions.
62 changes: 43 additions & 19 deletions src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php
Expand Up @@ -28,7 +28,9 @@ class ContainerAwareEventManager extends EventManager
* <event> => <listeners>
*/
private $listeners = [];

private $initialized = [];

private $container;

public function __construct(ContainerInterface $container)
Expand All @@ -43,24 +45,21 @@ public function __construct(ContainerInterface $container)
* the name of the method that is invoked on listeners.
* @param EventArgs $eventArgs The event arguments to pass to the event handlers/listeners.
* If not supplied, the single empty EventArgs instance is used.
*
* @return bool
*/
public function dispatchEvent($eventName, EventArgs $eventArgs = null)
{
if (isset($this->listeners[$eventName])) {
$eventArgs = null === $eventArgs ? EventArgs::getEmptyInstance() : $eventArgs;
if (!isset($this->listeners[$eventName])) {
return;
}

$initialized = isset($this->initialized[$eventName]);
$eventArgs = null === $eventArgs ? EventArgs::getEmptyInstance() : $eventArgs;

foreach ($this->listeners[$eventName] as $hash => $listener) {
if (!$initialized && \is_string($listener)) {
$this->listeners[$eventName][$hash] = $listener = $this->container->get($listener);
}
if (!isset($this->initialized[$eventName])) {
$this->initializeListeners($eventName);
}

$listener->$eventName($eventArgs);
}
$this->initialized[$eventName] = true;
foreach ($this->listeners[$eventName] as $hash => $listener) {
$listener->$eventName($eventArgs);
}
}

Expand All @@ -73,7 +72,21 @@ public function dispatchEvent($eventName, EventArgs $eventArgs = null)
*/
public function getListeners($event = null)
{
return $event ? $this->listeners[$event] : $this->listeners;
if (null !== $event) {
if (!isset($this->initialized[$event])) {
$this->initializeListeners($event);
}

return $this->listeners[$event];
}

foreach (array_keys($this->listeners) as $event) {
if (!isset($this->initialized[$event])) {
$this->initializeListeners($event);
}
}

return $this->listeners;
}

/**
Expand All @@ -93,16 +106,10 @@ public function hasListeners($event)
*
* @param string|array $events The event(s) to listen on
* @param object|string $listener The listener object
*
* @throws \RuntimeException
*/
public function addEventListener($events, $listener)
{
if (\is_string($listener)) {
if ($this->initialized) {
throw new \RuntimeException('Adding lazy-loading listeners after construction is not supported.');
}

$hash = '_service_'.$listener;
} else {
// Picks the hash code related to that listener
Expand All @@ -113,6 +120,10 @@ public function addEventListener($events, $listener)
// Overrides listener if a previous one was associated already
// Prevents duplicate listeners on same event (same instance only)
$this->listeners[$event][$hash] = $listener;

if (\is_string($listener)) {
unset($this->initialized[$event]);
}
}
}

Expand All @@ -138,4 +149,17 @@ public function removeEventListener($events, $listener)
}
}
}

/**
* @param string $eventName
*/
private function initializeListeners($eventName)
{
foreach ($this->listeners[$eventName] as $hash => $listener) {
if (\is_string($listener)) {
$this->listeners[$eventName][$hash] = $this->container->get($listener);
}
}
$this->initialized[$eventName] = true;
}
}
Expand Up @@ -28,8 +28,8 @@ protected function setUp()

public function testDispatchEvent()
{
$this->container->set('foobar', $listener1 = new MyListener());
$this->evm->addEventListener('foo', 'foobar');
$this->container->set('lazy', $listener1 = new MyListener());
$this->evm->addEventListener('foo', 'lazy');
$this->evm->addEventListener('foo', $listener2 = new MyListener());

$this->evm->dispatchEvent('foo');
Expand All @@ -38,19 +38,69 @@ public function testDispatchEvent()
$this->assertTrue($listener2->called);
}

public function testAddEventListenerAfterDispatchEvent()
{
$this->container->set('lazy1', $listener1 = new MyListener());
$this->evm->addEventListener('foo', 'lazy1');
$this->evm->addEventListener('foo', $listener2 = new MyListener());

$this->evm->dispatchEvent('foo');

$this->container->set('lazy2', $listener3 = new MyListener());
$this->evm->addEventListener('foo', 'lazy2');
$this->evm->addEventListener('foo', $listener4 = new MyListener());

$this->evm->dispatchEvent('foo');

$this->assertTrue($listener1->called);
$this->assertTrue($listener2->called);
$this->assertTrue($listener3->called);
$this->assertTrue($listener4->called);
}

public function testGetListenersForEvent()
{
$this->container->set('lazy', $listener1 = new MyListener());
$this->evm->addEventListener('foo', 'lazy');
$this->evm->addEventListener('foo', $listener2 = new MyListener());

$this->assertSame([$listener1, $listener2], array_values($this->evm->getListeners('foo')));
}

public function testGetListeners()
{
$this->container->set('lazy', $listener1 = new MyListener());
$this->evm->addEventListener('foo', 'lazy');
$this->evm->addEventListener('foo', $listener2 = new MyListener());

$this->assertSame([$listener1, $listener2], array_values($this->evm->getListeners()['foo']));
}

public function testRemoveEventListener()
{
$this->evm->addEventListener('foo', 'bar');
$this->evm->addEventListener('foo', $listener = new MyListener());
$this->container->set('lazy', $listener1 = new MyListener());
$this->evm->addEventListener('foo', 'lazy');
$this->evm->addEventListener('foo', $listener2 = new MyListener());

$this->evm->removeEventListener('foo', $listener2);
$this->assertSame([$listener1], array_values($this->evm->getListeners('foo')));

$listeners = ['foo' => ['_service_bar' => 'bar', spl_object_hash($listener) => $listener]];
$this->assertSame($listeners, $this->evm->getListeners());
$this->assertSame($listeners['foo'], $this->evm->getListeners('foo'));
$this->evm->removeEventListener('foo', 'lazy');
$this->assertSame([], $this->evm->getListeners('foo'));
}

public function testRemoveEventListenerAfterDispatchEvent()
{
$this->container->set('lazy', $listener1 = new MyListener());
$this->evm->addEventListener('foo', 'lazy');
$this->evm->addEventListener('foo', $listener2 = new MyListener());

$this->evm->dispatchEvent('foo');

$this->evm->removeEventListener('foo', $listener);
$this->assertSame(['_service_bar' => 'bar'], $this->evm->getListeners('foo'));
$this->evm->removeEventListener('foo', $listener2);
$this->assertSame([$listener1], array_values($this->evm->getListeners('foo')));

$this->evm->removeEventListener('foo', 'bar');
$this->evm->removeEventListener('foo', 'lazy');
$this->assertSame([], $this->evm->getListeners('foo'));
}
}
Expand Down

0 comments on commit 28df79d

Please sign in to comment.