Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Doctrine] Respect parent class contract in ContainerAwareEventManager #31335

Merged
merged 1 commit into from May 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
89 changes: 46 additions & 43 deletions src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php
Expand Up @@ -37,72 +37,61 @@ public function __construct(ContainerInterface $container)
}

/**
* Dispatches an event to all registered listeners.
*
* @param string $eventName The name of the event to dispatch. The name of the event is
* 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
Koc marked this conversation as resolved.
Show resolved Hide resolved
* {@inheritdoc}
*/
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);
}
}

/**
* Gets the listeners of a specific event or all listeners.
*
* @param string $event The name of the event
*
* @return array The event listeners for the specified event, or all event listeners
* {@inheritdoc}
*/
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 ($this->listeners as $event => $listeners) {
if (!isset($this->initialized[$event])) {
$this->initializeListeners($event);
}
}

return $this->listeners;
}

/**
* Checks whether an event has any registered listeners.
*
* @param string $event
*
* @return bool TRUE if the specified event has any listeners, FALSE otherwise
* {@inheritdoc}
*/
public function hasListeners($event)
{
return isset($this->listeners[$event]) && $this->listeners[$event];
}

/**
* Adds an event listener that listens on the specified events.
*
* @param string|array $events The event(s) to listen on
* @param object|string $listener The listener object
*
* @throws \RuntimeException
* {@inheritdoc}
*/
public function addEventListener($events, $listener)
{
if (\is_string($listener)) {
if ($this->initialized) {
throw new \RuntimeException('Adding lazy-loading listeners after construction is not supported.');
Koc marked this conversation as resolved.
Show resolved Hide resolved
}

$hash = '_service_'.$listener;
} else {
// Picks the hash code related to that listener
Expand All @@ -113,14 +102,15 @@ 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]);
}
}
}

/**
* Removes an event listener from the specified events.
*
* @param string|array $events
* @param object|string $listener
* {@inheritdoc}
*/
public function removeEventListener($events, $listener)
{
Expand All @@ -138,4 +128,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);
Koc marked this conversation as resolved.
Show resolved Hide resolved
$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