[Suggestion] provide a way to check valid EventSubscriberInterface implementations #7
Description
The EventSubscriberInterface
asks you to return an array of events for which the class wants to listen. Validating the proper implementation of this interface is a bit complex. Here is an example doing part of it:
<?php
namespace spec\Acme\DemoBundle\Activity;
use PhpSpec\Exception\Example\FailureException;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MyListenerSpec extends ObjectBehavior
{
function it_is_an_event_subscriber()
{
$this->shouldHaveType('Symfony\Component\EventDispatcher\EventSubscriberInterface');
$this->getSubscribedEvents()->shouldBeArray();
foreach ($this->getSubscribedEvents()->getWrappedObject() as $event => $listeners) {
if (is_string($listeners)) {
$this->shouldHaveListenerMethod($listeners);
continue;
}
if (!is_array($listeners)) {
throw new FailureException(sprintf('The listener registered for %s must be a string or an array of listeners', $event));
}
if (is_string($listeners[0])) {
$this->shouldHaveListenerMethod($listeners[0]);
continue;
}
foreach ($listeners as $i => $listener) {
if (!is_array($listener)) {
throw new FailureException(sprintf('The listener %s registered for %s must be an array (method, priority)', $i, $event));
}
$this->shouldHaveListenerMethod($listener[0]);
}
}
}
public function getMatchers()
{
return array(
'haveListenerMethod' => function ($subject, $method) {
if (!method_exists($subject, $method)) {
return false;
}
$refl = new \ReflectionMethod($subject, $method);
return $refl->isPublic() && !$refl->isAbstract();
}
);
}
}
This implementation is incomplete:
- it does not verify that the priority is returned properly in cases where it is expected (both cases where I access the index
0
for the method should check the index1
for an integer) - it misses some checks for missing indexes in arrays
- it is not implemented as a matcher on its own
This implementation most checks that the registered method actually exist (which avoids mistakes like doing a typo in the method name)
Having to repeat this complex validation in each subscriber spec would be a huge pain, which is why I would prefer to register it as a matcher and write something like $this->shouldBeAnEventSubscriber()
or something like that.
Do you think such matcher could fit in the Symfony2Extension ? Or is the extension aimed at integrating with the fullstack and component-specific matchers should better go in a separate extension easier to use separately ? I haven't tried to use the Symfony2Extension yet in my project, so I don't know how intrusive it is (i.e. is it possible to register it in a project not using the fullstack to benefit from such a matcher ?)