From de891e9289743b1b693466344a78f5ee0081fb30 Mon Sep 17 00:00:00 2001 From: Thibault Taillandier Date: Tue, 7 Jan 2025 16:03:20 +0100 Subject: [PATCH] feat(event): refacto of eventInterceptor and EventFactory --- phpstan.neon | 1 + .../Symfony/Config/services.php | 5 ++ .../SymfonyEventDispatcherEventHandler.php | 2 +- .../Config/EventInterceptorConfig.php | 18 +++++ .../Contract/Event/EventFactory.php | 24 ++++++ .../Impl/Event/ServiceProxyEventFactory.php | 36 +++++++++ src/Interceptor/Impl/EventInterceptor.php | 28 ++++--- src/Model/Event.php | 76 +++++++------------ tests/Interceptor/EventInterceptorTest.php | 4 + tests/ProxyFactoryTest.php | 7 +- 10 files changed, 140 insertions(+), 61 deletions(-) create mode 100644 src/Interceptor/Config/EventInterceptorConfig.php create mode 100644 src/Interceptor/Contract/Event/EventFactory.php create mode 100644 src/Interceptor/Impl/Event/ServiceProxyEventFactory.php diff --git a/phpstan.neon b/phpstan.neon index d0642ca..bdf7148 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -19,6 +19,7 @@ parameters: - '/Call to static method Webmozart\\Assert\\Assert::allIsInstanceOf\(\) with/' - '/Function compact\(\) should not be used/' - '/In method .+, caught "Throwable" must be rethrown. Either catch a more specific exception or add a "throw" clause in the "catch" block to propagate the exception./' + - '/Class OpenClassrooms\\ServiceProxy\\Model\\Event is neither abstract nor final./' exceptions: check: missingCheckedExceptionInThrows: true diff --git a/src/FrameworkBridge/Symfony/Config/services.php b/src/FrameworkBridge/Symfony/Config/services.php index 338854d..df986c4 100644 --- a/src/FrameworkBridge/Symfony/Config/services.php +++ b/src/FrameworkBridge/Symfony/Config/services.php @@ -5,6 +5,7 @@ use OpenClassrooms\ServiceProxy\FrameworkBridge\Symfony\Messenger\Transport\Serialization\MessageSerializer; use OpenClassrooms\ServiceProxy\FrameworkBridge\Symfony\Subscriber\ServiceProxySubscriber; use OpenClassrooms\ServiceProxy\Handler\Impl\Cache\SymfonyCacheHandler; +use OpenClassrooms\ServiceProxy\Interceptor\Impl\Event\ServiceProxyEventFactory; use OpenClassrooms\ServiceProxy\Invoker\Impl\AggregateMethodInvoker; use OpenClassrooms\ServiceProxy\ProxyFactory; use OpenClassrooms\ServiceProxy\ProxyFactoryConfiguration; @@ -74,4 +75,8 @@ service('annotation_reader')->nullOnInvalid(), ]) ->tag('kernel.event_subscriber'); + + $services->set(ServiceProxyEventFactory::class) + ->autowire() + ->autoconfigure(); }; diff --git a/src/Handler/Impl/Event/SymfonyEventDispatcherEventHandler.php b/src/Handler/Impl/Event/SymfonyEventDispatcherEventHandler.php index 62d8e69..707cc1f 100644 --- a/src/Handler/Impl/Event/SymfonyEventDispatcherEventHandler.php +++ b/src/Handler/Impl/Event/SymfonyEventDispatcherEventHandler.php @@ -26,7 +26,7 @@ public function dispatch(Event $event, ?string $queue = null): void { $this->eventDispatcher->dispatch( $event, - $event->name . '.' . Transport::SYNC->value, + $event->name, ); } diff --git a/src/Interceptor/Config/EventInterceptorConfig.php b/src/Interceptor/Config/EventInterceptorConfig.php new file mode 100644 index 0000000..3a80e43 --- /dev/null +++ b/src/Interceptor/Config/EventInterceptorConfig.php @@ -0,0 +1,18 @@ + $eventInstanceClassName + */ + public function __construct( + public readonly string $eventInstanceClassName = Event::class, + ) { + } +} diff --git a/src/Interceptor/Contract/Event/EventFactory.php b/src/Interceptor/Contract/Event/EventFactory.php new file mode 100644 index 0000000..e61da77 --- /dev/null +++ b/src/Interceptor/Contract/Event/EventFactory.php @@ -0,0 +1,24 @@ + $eventClassName + * @return T + */ + public function createFromSenderInstance( + Instance $instance, + Moment $moment = Moment::SUFFIX, + ?string $name = null, + string $eventClassName = Event::class + ): Event; +} diff --git a/src/Interceptor/Impl/Event/ServiceProxyEventFactory.php b/src/Interceptor/Impl/Event/ServiceProxyEventFactory.php new file mode 100644 index 0000000..01671a2 --- /dev/null +++ b/src/Interceptor/Impl/Event/ServiceProxyEventFactory.php @@ -0,0 +1,36 @@ + $eventClassName + * @return T + */ + public function createFromSenderInstance( + Instance $instance, + Moment $moment = Moment::SUFFIX, + ?string $name = null, + string $eventClassName = Event::class + ): Event { + return new $eventClassName( + $instance->getReflection()->getName(), + $instance->getReflection()->getShortName(), + $instance->getMethod()->getName(), + $instance->getMethod()->getParameters(), + $name, + $instance->getMethod()->getReturnedValue(), + $instance->getMethod()->getException(), + $moment, + ); + } +} diff --git a/src/Interceptor/Impl/EventInterceptor.php b/src/Interceptor/Impl/EventInterceptor.php index 9b48403..846daa4 100644 --- a/src/Interceptor/Impl/EventInterceptor.php +++ b/src/Interceptor/Impl/EventInterceptor.php @@ -6,7 +6,9 @@ use OpenClassrooms\ServiceProxy\Attribute\Event; use OpenClassrooms\ServiceProxy\Handler\Contract\EventHandler; +use OpenClassrooms\ServiceProxy\Interceptor\Config\EventInterceptorConfig; use OpenClassrooms\ServiceProxy\Interceptor\Contract\AbstractInterceptor; +use OpenClassrooms\ServiceProxy\Interceptor\Contract\Event\EventFactory; use OpenClassrooms\ServiceProxy\Interceptor\Contract\PrefixInterceptor; use OpenClassrooms\ServiceProxy\Interceptor\Contract\SuffixInterceptor; use OpenClassrooms\ServiceProxy\Model\Request\Instance; @@ -15,6 +17,14 @@ final class EventInterceptor extends AbstractInterceptor implements SuffixInterceptor, PrefixInterceptor { + public function __construct( + private readonly EventFactory $eventFactory, + private readonly EventInterceptorConfig $config, + iterable $handlers = [], + ) { + parent::__construct($handlers); + } + public function getPrefixPriority(): int { return 20; @@ -28,15 +38,15 @@ public function getSuffixPriority(): int public function prefix(Instance $instance): Response { $attributes = $instance->getMethod() - ->getAttributesInstances(Event::class) - ; + ->getAttributesInstances(Event::class); foreach ($attributes as $attribute) { $handlers = $this->getHandlers(EventHandler::class, $attribute); - $event = \OpenClassrooms\ServiceProxy\Model\Event::createFromSenderInstance( + $event = $this->eventFactory->createFromSenderInstance( $instance, Moment::PREFIX, $attribute->name, + $this->config->eventInstanceClassName, ); foreach ($handlers as $handler) { if ($attribute->isPre()) { @@ -51,27 +61,28 @@ public function prefix(Instance $instance): Response public function suffix(Instance $instance): Response { $attributes = $instance->getMethod() - ->getAttributes(Event::class) - ; + ->getAttributes(Event::class); foreach ($attributes as $attribute) { $attribute = $attribute->newInstance(); $handlers = $this->getHandlers(EventHandler::class, $attribute); foreach ($handlers as $handler) { if ($attribute->isPost() && !$instance->getMethod()->threwException()) { - $event = \OpenClassrooms\ServiceProxy\Model\Event::createFromSenderInstance( + $event = $this->eventFactory->createFromSenderInstance( $instance, Moment::SUFFIX, $attribute->name, + $this->config->eventInstanceClassName, ); $handler->dispatch($event, $attribute->queue); } if ($attribute->isOnException() && $instance->getMethod()->threwException()) { - $event = \OpenClassrooms\ServiceProxy\Model\Event::createFromSenderInstance( + $event = $this->eventFactory->createFromSenderInstance( $instance, Moment::EXCEPTION, $attribute->name, + $this->config->eventInstanceClassName, ); $handler->dispatch($event, $attribute->queue); } @@ -89,7 +100,6 @@ public function supportsSuffix(Instance $instance): bool public function supportsPrefix(Instance $instance): bool { return $instance->getMethod() - ->hasAttribute(Event::class) - ; + ->hasAttribute(Event::class); } } diff --git a/src/Model/Event.php b/src/Model/Event.php index 69bde22..768f99e 100644 --- a/src/Model/Event.php +++ b/src/Model/Event.php @@ -5,56 +5,48 @@ namespace OpenClassrooms\ServiceProxy\Model; use OpenClassrooms\ServiceProxy\Attribute\Event\Transport; -use OpenClassrooms\ServiceProxy\Model\Request\Instance; use OpenClassrooms\ServiceProxy\Model\Request\Moment; -final class Event +class Event { + public string $name; + /** - * @param mixed[] $parameters + * @param class-string $class + * @param array $parameters */ public function __construct( - public readonly string $name, public readonly string $class, public readonly string $classShortName, public readonly string $method, public readonly array $parameters, + ?string $name = null, public readonly mixed $response = null, public readonly mixed $exception = null, public readonly Moment $type = Moment::SUFFIX ) { + $this->name = self::getName( + className: $class, + moment: $type, + transport: Transport::SYNC, + method: $method, + name: $name + ); } - public static function createFromSenderInstance( - Instance $instance, - Moment $moment = Moment::SUFFIX, - ?string $name = null - ): self { - /** @var class-string $className */ - $className = $instance->getReflection()->getName(); + public function getUseCaseRequest(): mixed + { + return $this->parameters['useCaseRequest'] ?? ($this->parameters['request'] ?? null); + } - return new self( - self::getName( - className: $className, - moment: $moment, - method: $instance->getMethod() - ->getName(), - name: $name, - ), - $instance->getReflection() - ->getName(), - $instance->getReflection() - ->getShortName(), - $instance->getMethod() - ->getName(), - $instance->getMethod() - ->getParameters(), - $instance->getMethod() - ->getReturnedValue(), - $instance->getMethod() - ->getException(), - $moment, - ); + public function getUseCaseResponse(): mixed + { + return $this->response; + } + + public function getUseCaseException(): mixed + { + return $this->exception; } /** @@ -70,7 +62,6 @@ public static function getName( if ($name !== null) { return $name; } - $parts = explode('\\', $className); $classShortName = array_pop($parts); @@ -80,25 +71,10 @@ public static function getName( $name = mb_strtolower((string) preg_replace('/(?<=\\w)(?=[A-Z])/', '_$1', $name)); - if ($transport !== null) { + if ($transport !== null && $transport !== Transport::SYNC) { return "{$moment->value}.{$name}.{$transport->value}"; } return "{$moment->value}.{$name}"; } - - public function getUseCaseRequest(): mixed - { - return $this->parameters['useCaseRequest'] ?? ($this->parameters['request'] ?? null); - } - - public function getUseCaseResponse(): mixed - { - return $this->response; - } - - public function getUseCaseException(): mixed - { - return $this->exception; - } } diff --git a/tests/Interceptor/EventInterceptorTest.php b/tests/Interceptor/EventInterceptorTest.php index 600139e..3d40a64 100644 --- a/tests/Interceptor/EventInterceptorTest.php +++ b/tests/Interceptor/EventInterceptorTest.php @@ -4,6 +4,8 @@ namespace OpenClassrooms\ServiceProxy\Tests\Interceptor; +use OpenClassrooms\ServiceProxy\Interceptor\Config\EventInterceptorConfig; +use OpenClassrooms\ServiceProxy\Interceptor\Impl\Event\ServiceProxyEventFactory; use OpenClassrooms\ServiceProxy\Interceptor\Impl\EventInterceptor; use OpenClassrooms\ServiceProxy\ProxyFactory; use OpenClassrooms\ServiceProxy\Tests\Double\Mock\Event\EventHandlerMock; @@ -28,6 +30,8 @@ protected function setUp(): void $this->proxyFactory = $this->getProxyFactory( [ new EventInterceptor( + new ServiceProxyEventFactory(), + new EventInterceptorConfig(), [$this->handler], ), ] diff --git a/tests/ProxyFactoryTest.php b/tests/ProxyFactoryTest.php index 1c01938..9b002c7 100644 --- a/tests/ProxyFactoryTest.php +++ b/tests/ProxyFactoryTest.php @@ -4,9 +4,11 @@ namespace OpenClassrooms\ServiceProxy\Tests; +use OpenClassrooms\ServiceProxy\Interceptor\Config\EventInterceptorConfig; use OpenClassrooms\ServiceProxy\Interceptor\Contract\PrefixInterceptor; use OpenClassrooms\ServiceProxy\Interceptor\Contract\SuffixInterceptor; use OpenClassrooms\ServiceProxy\Interceptor\Impl\CacheInterceptor; +use OpenClassrooms\ServiceProxy\Interceptor\Impl\Event\ServiceProxyEventFactory; use OpenClassrooms\ServiceProxy\Interceptor\Impl\EventInterceptor; use OpenClassrooms\ServiceProxy\Interceptor\Impl\InvalidateCacheInterceptor; use OpenClassrooms\ServiceProxy\Interceptor\Impl\LegacyCacheInterceptor; @@ -37,7 +39,10 @@ protected function setUp(): void $classes = get_declared_classes(); foreach ($classes as $class) { - if (is_subclass_of($class, PrefixInterceptor::class) || is_subclass_of($class, SuffixInterceptor::class)) { + if ($class === EventInterceptor::class) { + $interceptors[] = new $class(new ServiceProxyEventFactory(), new EventInterceptorConfig()); + } elseif (is_subclass_of($class, PrefixInterceptor::class) + || is_subclass_of($class, SuffixInterceptor::class)) { $interceptors[] = new $class(); } }