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 067a900

Browse filesBrowse files
committed
[EventDispatcher] Updated RegisterListenersPass to throw a meaningful error when the listener callback method could not be found
1 parent 4559a65 commit 067a900
Copy full SHA for 067a900

File tree

3 files changed

+59
-18
lines changed
Filter options

3 files changed

+59
-18
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class WrappedListener
3838
private $priority;
3939
private static $hasClassStub;
4040

41-
public function __construct(callable $listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null)
41+
public function __construct($listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null)
4242
{
4343
$this->listener = $listener;
4444
$this->optimizedListener = $listener instanceof \Closure ? $listener : \Closure::fromCallable($listener);

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php
+43-8Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,36 @@ public function process(ContainerBuilder $container)
7272
$event['event'] = $aliases[$event['event']] ?? $event['event'];
7373

7474
if (!isset($event['method'])) {
75-
$event['method'] = 'on'.preg_replace_callback([
76-
'/(?<=\b)[a-z]/i',
77-
'/[^a-z0-9]/i',
78-
], function ($matches) { return strtoupper($matches[0]); }, $event['event']);
79-
$event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']);
80-
81-
if (null !== ($class = $container->getDefinition($id)->getClass()) && ($r = $container->getReflectionClass($class, false)) && !$r->hasMethod($event['method']) && $r->hasMethod('__invoke')) {
82-
$event['method'] = '__invoke';
75+
$methodName = $this->guessMethodName($event['event']);
76+
$event['method'] = $methodName;
77+
78+
if (null !== ($class = $container->getDefinition($id)->getClass()) &&
79+
($r = $container->getReflectionClass($class, false)) &&
80+
!$r->hasMethod($event['method'])
81+
) {
82+
if ($r->hasMethod('__invoke')) {
83+
$event['method'] = '__invoke';
84+
} else {
85+
throw new InvalidArgumentException(sprintf(
86+
'Could not found a valid callback method in the listener "%s". '.
87+
'Please add "%s()" or "__invoke()" method or define the "method" attribute '.
88+
'(in the listener configuration) containing a name of existing method',
89+
$id,
90+
$methodName
91+
));
92+
}
93+
}
94+
} else {
95+
if (null !== ($class = $container->getDefinition($id)->getClass()) &&
96+
($r = $container->getReflectionClass($class, false)) &&
97+
!$r->hasMethod($event['method'])
98+
) {
99+
throw new InvalidArgumentException(sprintf(
100+
'Could not found the "%s()" method in the listener "%s". '.
101+
'Please add it or update the "method" attribute in the listener configuration',
102+
$event['method'],
103+
$id
104+
));
83105
}
84106
}
85107

@@ -122,6 +144,19 @@ public function process(ContainerBuilder $container)
122144
ExtractingEventDispatcher::$aliases = [];
123145
}
124146
}
147+
148+
private function guessMethodName(string $event)
149+
{
150+
$name = 'on'.
151+
preg_replace_callback([
152+
'/(?<=\b)[a-z]/i',
153+
'/[^a-z0-9]/i',
154+
], function ($matches) {
155+
return strtoupper($matches[0]);
156+
}, $event);
157+
158+
return preg_replace('/[^a-z0-9]/i', '', $name);
159+
}
125160
}
126161

127162
/**

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php
+15-9Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ public function testEventSubscriberUnresolvableClassName()
145145
public function testInvokableEventListener()
146146
{
147147
$container = new ContainerBuilder();
148-
$container->register('foo', \stdClass::class)->addTag('kernel.event_listener', ['event' => 'foo.bar']);
149148
$container->register('bar', InvokableListenerService::class)->addTag('kernel.event_listener', ['event' => 'foo.bar']);
150149
$container->register('baz', InvokableListenerService::class)->addTag('kernel.event_listener', ['event' => 'event']);
151150
$container->register('event_dispatcher', \stdClass::class);
@@ -155,14 +154,6 @@ public function testInvokableEventListener()
155154

156155
$definition = $container->getDefinition('event_dispatcher');
157156
$expectedCalls = [
158-
[
159-
'addListener',
160-
[
161-
'foo.bar',
162-
[new ServiceClosureArgument(new Reference('foo')), 'onFooBar'],
163-
0,
164-
],
165-
],
166157
[
167158
'addListener',
168159
[
@@ -182,6 +173,21 @@ public function testInvokableEventListener()
182173
];
183174
$this->assertEquals($expectedCalls, $definition->getMethodCalls());
184175
}
176+
177+
/**
178+
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
179+
* @expectedExceptionMessage Could not found a valid callback method in the listener "foo". Please add "onFooBar()"
180+
* or "__invoke()" method or define the "method" attribute (in the listener configuration) containing a name of
181+
* existing method
182+
*/
183+
public function testEventListenerUnresolvableMethodName()
184+
{
185+
$container = new ContainerBuilder();
186+
$container->register('foo', \stdClass::class)->addTag('kernel.event_listener', ['event' => 'foo.bar']);
187+
$container->register('event_dispatcher', \stdClass::class);
188+
189+
(new RegisterListenersPass())->process($container);
190+
}
185191
}
186192

187193
class SubscriberService implements \Symfony\Component\EventDispatcher\EventSubscriberInterface

0 commit comments

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