Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ded0bb4

Browse filesBrowse files
[EventDispatcher] Handle lazyness internally instead of relying on ClosureProxyArgument
1 parent 7a9875c commit ded0bb4
Copy full SHA for ded0bb4

File tree

3 files changed

+89
-9
lines changed
Filter options

3 files changed

+89
-9
lines changed

‎src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php
+4-3Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111

1212
namespace Symfony\Component\EventDispatcher\DependencyInjection;
1313

14-
use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
14+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1515
use Symfony\Component\DependencyInjection\ContainerBuilder;
1616
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1717
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
18+
use Symfony\Component\DependencyInjection\Reference;
1819
use Symfony\Component\EventDispatcher\EventDispatcher;
1920
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
2021

@@ -78,7 +79,7 @@ public function process(ContainerBuilder $container)
7879
$event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']);
7980
}
8081

81-
$definition->addMethodCall('addListener', array($event['event'], new ClosureProxyArgument($id, $event['method']), $priority));
82+
$definition->addMethodCall('addListener', array($event['event'], array(new ServiceClosureArgument(new Reference($id)), $event['method']), $priority));
8283
}
8384
}
8485

@@ -103,7 +104,7 @@ public function process(ContainerBuilder $container)
103104
ExtractingEventDispatcher::$subscriber = $class;
104105
$extractingDispatcher->addSubscriber($extractingDispatcher);
105106
foreach ($extractingDispatcher->listeners as $args) {
106-
$args[1] = new ClosureProxyArgument($id, $args[1]);
107+
$args[1] = array(new ServiceClosureArgument(new Reference($id)), $args[1]);
107108
$definition->addMethodCall('addListener', $args);
108109
}
109110
$extractingDispatcher->listeners = array();

‎src/Symfony/Component/EventDispatcher/EventDispatcher.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/EventDispatcher/EventDispatcher.php
+80-2Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* @author Fabien Potencier <fabien@symfony.com>
2525
* @author Jordi Boggiano <j.boggiano@seld.be>
2626
* @author Jordan Alliot <jordan.alliot@gmail.com>
27+
* @author Nicolas Grekas <p@tchwork.com>
2728
*/
2829
class EventDispatcher implements EventDispatcherInterface
2930
{
@@ -86,14 +87,47 @@ public function getListenerPriority($eventName, $listener)
8687
return $priority;
8788
}
8889
}
90+
91+
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
92+
$listener[0] = $listener[0]();
93+
foreach ($this->listeners[$eventName] as $priority => $listeners) {
94+
if (false !== in_array($listener, $listeners, true)) {
95+
return $priority;
96+
}
97+
}
98+
} elseif (!isset($this->sorted[$eventName])) {
99+
foreach ($this->listeners[$eventName] as $priority => $listeners) {
100+
foreach ($listeners as $k => $v) {
101+
if (!is_array($v) || !isset($v[0]) || !$v[0] instanceof \Closure) {
102+
continue;
103+
}
104+
$v[0] = $v[0]();
105+
$this->listeners[$eventName][$priority][$k] = $v;
106+
107+
if ($v === $listener) {
108+
return $priority;
109+
}
110+
}
111+
}
112+
}
89113
}
90114

91115
/**
92116
* {@inheritdoc}
93117
*/
94118
public function hasListeners($eventName = null)
95119
{
96-
return (bool) $this->getListeners($eventName);
120+
if (null !== $eventName) {
121+
return isset($this->listeners[$eventName]) && !empty(array_filter($this->listeners[$eventName]));
122+
}
123+
124+
foreach ($this->listeners as $eventListeners) {
125+
if (!empty(array_filter($eventListeners))) {
126+
return true;
127+
}
128+
}
129+
130+
return false;
97131
}
98132

99133
/**
@@ -113,10 +147,44 @@ public function removeListener($eventName, $listener)
113147
if (!isset($this->listeners[$eventName])) {
114148
return;
115149
}
150+
$found = false;
116151

117152
foreach ($this->listeners[$eventName] as $priority => $listeners) {
118153
if (false !== ($key = array_search($listener, $listeners, true))) {
119154
unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]);
155+
$found = true;
156+
}
157+
}
158+
159+
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
160+
$listener[0] = $listener[0]();
161+
foreach ($this->listeners[$eventName] as $priority => $listeners) {
162+
if (false !== ($key = array_search($listener, $listeners, true))) {
163+
unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]);
164+
$found = true;
165+
}
166+
}
167+
}
168+
169+
if ($found || isset($this->sorted[$eventName])) {
170+
// There might be more matches encapsed in closures,
171+
// but we don't want to instanciate the world
172+
// to remove a listener that already matched.
173+
return;
174+
}
175+
176+
foreach ($this->listeners[$eventName] as $priority => $listeners) {
177+
foreach ($listeners as $k => $v) {
178+
if (!is_array($v) || !isset($v[0]) || !$v[0] instanceof \Closure) {
179+
continue;
180+
}
181+
$v[0] = $v[0]();
182+
183+
if ($v === $listener) {
184+
unset($this->listeners[$eventName][$priority][$k], $this->sorted[$eventName]);
185+
} else {
186+
$this->listeners[$eventName][$priority][$k] = $v;
187+
}
120188
}
121189
}
122190
}
@@ -183,6 +251,16 @@ protected function doDispatch($listeners, $eventName, Event $event)
183251
private function sortListeners($eventName)
184252
{
185253
krsort($this->listeners[$eventName]);
186-
$this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]);
254+
$this->sorted[$eventName] = array();
255+
256+
foreach ($this->listeners[$eventName] as $priority => $listeners) {
257+
foreach ($listeners as $k => $listener) {
258+
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
259+
$listener[0] = $listener[0]();
260+
$this->listeners[$eventName][$priority][$k] = $listener;
261+
}
262+
$this->sorted[$eventName][] = $listener;
263+
}
264+
}
187265
}
188266
}

‎src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php
+5-4Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
namespace Symfony\Component\EventDispatcher\Tests\DependencyInjection;
1313

1414
use PHPUnit\Framework\TestCase;
15-
use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
15+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1616
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Reference;
1718
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
1819

1920
class RegisterListenersPassTest extends TestCase
@@ -127,17 +128,17 @@ public function testEventSubscriberResolvableClassName()
127128
$registerListenersPass->process($container);
128129

129130
$definition = $container->getDefinition('event_dispatcher');
130-
$expected_calls = array(
131+
$expectedCalls = array(
131132
array(
132133
'addListener',
133134
array(
134135
'event',
135-
new ClosureProxyArgument('foo', 'onEvent'),
136+
array(new ServiceClosureArgument(new Reference('foo')), 'onEvent'),
136137
0,
137138
),
138139
),
139140
);
140-
$this->assertEquals($expected_calls, $definition->getMethodCalls());
141+
$this->assertEquals($expectedCalls, $definition->getMethodCalls());
141142
}
142143

143144
/**

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.