Skip to content
This repository was archived by the owner on Feb 14, 2021. It is now read-only.
This repository was archived by the owner on Feb 14, 2021. It is now read-only.

[Suggestion] provide a way to check valid EventSubscriberInterface implementations #7

Open
@stof

Description

@stof

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 index 1 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 ?)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions