Skip to content

Commit

Permalink
Add helper class for single-event subscription
Browse files Browse the repository at this point in the history
  • Loading branch information
yceruto committed Sep 7, 2019
1 parent 5765539 commit d347385
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/Symfony/Component/EventDispatcher/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
CHANGELOG
=========

4.4.0
-----

* added `EventListenerTrait` helper class for single-event subscription.

4.3.0
-----

Expand Down
61 changes: 61 additions & 0 deletions src/Symfony/Component/EventDispatcher/EventListenerTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\EventDispatcher;

use Symfony\Contracts\EventDispatcher\Event as ContractsEvent;

/**
* Helper class for single-event subscription.
*
* @author Yonel Ceruto <yonelceruto@gmail.com>
*/
trait EventListenerTrait
{
/**
* {@inheritdoc}
*/
final public static function getSubscribedEvents(): array
{
return [static::getEventName() => [static::getMethodName(), static::getPriority()]];
}

public static function getEventName(): string
{
$method = new \ReflectionMethod(static::class, static::getMethodName());

if (0 === $method->getNumberOfParameters()) {
throw new \LogicException(sprintf('We cannot infer the Event name from "%s::%s()" method without parameters, you must to define one or implement the "%s::getEventName()" method to return it explicitly.', static::class, $method->getName(), static::class));
}

$parameter = $method->getParameters()[0];

if (null === $type = $parameter->getType()) {
throw new \LogicException(sprintf('We cannot infer the Event name from "%s::%s()" method without type-hint the "$%s" parameter, you must to type-hint it or implement the "%s::getEventName()" method to return it explicitly.', ContractsEvent::class, $method->getName(), $parameter->getName(), static::class));
}

if ($type->isBuiltin()) {
throw new \LogicException(sprintf('The "$%s" parameter defined in "%s::%s()" method must be a class of "%s", "%s" given.', $parameter->getName(), static::class, $method->getName(), ContractsEvent::class, $type->getName()));
}

return $type->getName();
}

public static function getMethodName(): string
{
return '__invoke';
}

public static function getPriority(): int
{
return 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use PHPUnit\Framework\TestCase;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventListenerTrait;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Contracts\EventDispatcher\Event as ContractsEvent;

Expand Down Expand Up @@ -437,6 +438,16 @@ public function testLegacySignatureWithNewEventObject()
$this->expectExceptionMessage('Argument 1 passed to "Symfony\Component\EventDispatcher\EventDispatcherInterface::dispatch()" must be an object, string given.');
$this->dispatcher->dispatch('foo', new ContractsEvent());
}

public function testSingleEventSubsriber()
{
$subscriber = new TestSingleEventListener();
$this->dispatcher->addSubscriber($subscriber);
$this->assertTrue($this->dispatcher->hasListeners(MyEvent::class));

$this->dispatcher->dispatch(new MyEvent());
$this->assertTrue($subscriber->invoked);
}
}

class CallableClass
Expand Down Expand Up @@ -480,6 +491,22 @@ public function foo($e, $name, $dispatcher)
}
}

class MyEvent extends ContractsEvent
{
}

class TestSingleEventListener implements EventSubscriberInterface
{
use EventListenerTrait;

public $invoked = false;

public function __invoke(MyEvent $event): void
{
$this->invoked = true;
}
}

class TestEventSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
Expand Down

0 comments on commit d347385

Please sign in to comment.