From db333c7fe3c49e2b47c4336902bb51ef694cae62 Mon Sep 17 00:00:00 2001 From: Martin Parsiegla Date: Sat, 22 Jul 2023 17:03:05 +0200 Subject: [PATCH] Support attribute With this addition, it is now possible to use `#[Rebuy\Amqp\Consumer\Annotation\Consumer]` instead of a doctrine annotation. --- composer.json | 2 +- .../Amqp/Consumer/Annotation/Consumer.php | 21 +++++++------ src/Rebuy/Amqp/Consumer/Annotation/Parser.php | 16 ++++++++-- .../Annotation/ConsumerContainerTest.php | 30 ++++++++++++++----- .../Amqp/Consumer/Annotation/ParserTest.php | 18 ++++++++++- .../Consumer/Stubs/ConsumerWithAttributes.php | 11 +++++++ 6 files changed, 75 insertions(+), 23 deletions(-) create mode 100644 tests/Rebuy/Tests/Amqp/Consumer/Stubs/ConsumerWithAttributes.php diff --git a/composer.json b/composer.json index d39f8df..0beeec9 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ "require": { "php": "^8.1", "php-amqplib/php-amqplib": "^3.0.0", - "doctrine/annotations": "^1.10|^2.0.1", + "doctrine/annotations": "^1.13.3|^2.0.1", "symfony/event-dispatcher": "^4.4|^5.0|^6.0", "doctrine/collections": "^1.6|^2.1.2" }, diff --git a/src/Rebuy/Amqp/Consumer/Annotation/Consumer.php b/src/Rebuy/Amqp/Consumer/Annotation/Consumer.php index c5d1e45..2dfe064 100644 --- a/src/Rebuy/Amqp/Consumer/Annotation/Consumer.php +++ b/src/Rebuy/Amqp/Consumer/Annotation/Consumer.php @@ -2,22 +2,21 @@ namespace Rebuy\Amqp\Consumer\Annotation; +use Attribute; + /** * @Annotation * @Target({"METHOD"}) + * @NamedArgumentConstructor */ +#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)] class Consumer { - const DEFAULT_PREFETCH_COUNT = 1; - - /** - * @Required - * @var string - */ - public $name; + private const DEFAULT_PREFETCH_COUNT = 1; - /** - * @var int - */ - public $prefetchCount = self::DEFAULT_PREFETCH_COUNT; + public function __construct( + public string $name, + public int $prefetchCount = self::DEFAULT_PREFETCH_COUNT + ) { + } } diff --git a/src/Rebuy/Amqp/Consumer/Annotation/Parser.php b/src/Rebuy/Amqp/Consumer/Annotation/Parser.php index dd63e1f..0cfe9d7 100644 --- a/src/Rebuy/Amqp/Consumer/Annotation/Parser.php +++ b/src/Rebuy/Amqp/Consumer/Annotation/Parser.php @@ -39,8 +39,7 @@ public function getConsumerMethods($obj) $class = new ReflectionClass($obj); $consumerMethods = []; foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { - /** @var Consumer $annotation */ - $annotation = $this->reader->getMethodAnnotation($method, Consumer::class); + $annotation = $this->getConsumerAnnotationOrAttribute($method); if (null === $annotation) { continue; } @@ -70,4 +69,17 @@ private function validateMethod(ReflectionMethod $method) throw new InvalidArgumentException('A @Consumer\'s parameter must implement ' . MessageInterface::class); } } + + private function getConsumerAnnotationOrAttribute(ReflectionMethod $method): ?Consumer + { + $reflectionAttributes = $method->getAttributes(); + foreach ($reflectionAttributes as $attribute) { + if ($attribute->getName() === Consumer::class) { + return $attribute->newInstance(); + } + } + + return $this->reader->getMethodAnnotation($method, Consumer::class); + + } } diff --git a/tests/Rebuy/Tests/Amqp/Consumer/Annotation/ConsumerContainerTest.php b/tests/Rebuy/Tests/Amqp/Consumer/Annotation/ConsumerContainerTest.php index b4f70f8..45ce6ac 100644 --- a/tests/Rebuy/Tests/Amqp/Consumer/Annotation/ConsumerContainerTest.php +++ b/tests/Rebuy/Tests/Amqp/Consumer/Annotation/ConsumerContainerTest.php @@ -33,7 +33,7 @@ public function invoke_should_invoke_reflection() self::TEST_PREFIX, $consumer, $reflectionMethod->reveal(), - new ConsumerAnnotation() + new ConsumerAnnotation('name') ); $container->invoke($payload); } @@ -46,7 +46,7 @@ public function get_bindings_should_return_empty_array_if_interface_is_not_imple $consumer = new ConsumerWithInvalidParameter(); $method = new ReflectionMethod($consumer, 'classWithoutImplementingInterface'); - $container = new ConsumerContainer(self::TEST_PREFIX, $consumer, $method, new ConsumerAnnotation()); + $container = new ConsumerContainer(self::TEST_PREFIX, $consumer, $method, new ConsumerAnnotation('name')); $result = $container->getBindings(); verify($result)->empty(); @@ -60,12 +60,26 @@ public function get_bindings_should_return_empty_array_if_parameter_count_is_not $consumer = new ConsumerWithTwoParameters(); $method = new ReflectionMethod($consumer, 'consume'); - $container = new ConsumerContainer(self::TEST_PREFIX, $consumer, $method, new ConsumerAnnotation()); + $container = new ConsumerContainer(self::TEST_PREFIX, $consumer, $method, new ConsumerAnnotation('name')); $result = $container->getBindings(); verify($result)->empty(); } + /** + * @test + */ + public function getRoutingKey_should_return_null_if_the_class_does_not_implement_the_MessageInterface() + { + $consumer = new ConsumerWithInvalidParameter(); + $method = new ReflectionMethod($consumer, 'classWithoutImplementingInterface'); + + $container = new ConsumerContainer(self::TEST_PREFIX, $consumer, $method, new ConsumerAnnotation('name')); + $result = $container->getRoutingKey(); + + verify($result)->empty(); + } + /** * @test */ @@ -74,7 +88,7 @@ public function get_bindings_should_return_empty_array_parameter_is_not_a_class( $consumer = new ConsumerWithInvalidParameter(); $method = new ReflectionMethod($consumer, 'consume'); - $container = new ConsumerContainer(self::TEST_PREFIX, $consumer, $method, new ConsumerAnnotation()); + $container = new ConsumerContainer(self::TEST_PREFIX, $consumer, $method, new ConsumerAnnotation('name')); $result = $container->getBindings(); verify($result)->empty(); @@ -88,7 +102,7 @@ public function get_bindings_should_return_array_with_two_bindings() $consumer = new Consumer(); $method = new ReflectionMethod($consumer, 'consume'); - $container = new ConsumerContainer(self::TEST_PREFIX, $consumer, $method, new ConsumerAnnotation()); + $container = new ConsumerContainer(self::TEST_PREFIX, $consumer, $method, new ConsumerAnnotation('name')); $result = $container->getBindings(); verify($result)->notEmpty(); @@ -103,7 +117,7 @@ public function get_bindings_should_return_correct_bindings() $consumer = new Consumer(); $method = new ReflectionMethod($consumer, 'consume'); - $consumerAnnotation = new ConsumerAnnotation(); + $consumerAnnotation = new ConsumerAnnotation('name'); $consumerAnnotation->name = "consume-method"; $container = new ConsumerContainer(self::TEST_PREFIX, $consumer, $method, $consumerAnnotation); $result = $container->getBindings(); @@ -120,7 +134,7 @@ public function get_consumer_name_should_return_correct_name() $consumer = new Consumer(); $method = new ReflectionMethod($consumer, 'consume'); - $consumerAnnotation = new ConsumerAnnotation(); + $consumerAnnotation = new ConsumerAnnotation('name'); $consumerAnnotation->name = "consume-method"; $container = new ConsumerContainer(self::TEST_PREFIX, $consumer, $method, $consumerAnnotation); $result = $container->getConsumerName(); @@ -136,7 +150,7 @@ public function get_method_name_should_return_class_with_method_name() $consumer = new Consumer(); $method = new ReflectionMethod($consumer, 'consume'); - $consumerAnnotation = new ConsumerAnnotation(); + $consumerAnnotation = new ConsumerAnnotation('name'); $container = new ConsumerContainer(self::TEST_PREFIX, $consumer, $method, $consumerAnnotation); $result = $container->getMethodName(); diff --git a/tests/Rebuy/Tests/Amqp/Consumer/Annotation/ParserTest.php b/tests/Rebuy/Tests/Amqp/Consumer/Annotation/ParserTest.php index fc55913..7564dbe 100644 --- a/tests/Rebuy/Tests/Amqp/Consumer/Annotation/ParserTest.php +++ b/tests/Rebuy/Tests/Amqp/Consumer/Annotation/ParserTest.php @@ -9,6 +9,7 @@ use Rebuy\Amqp\Consumer\Annotation\Consumer as ConsumerAnnotation; use Rebuy\Amqp\Consumer\Annotation\Parser; use Rebuy\Tests\Amqp\Consumer\Stubs\Consumer; +use Rebuy\Tests\Amqp\Consumer\Stubs\ConsumerWithAttributes; use Rebuy\Tests\Amqp\Consumer\Stubs\ConsumerWithInvalidAnnotation; use Rebuy\Tests\Amqp\Consumer\Stubs\ConsumerWithInvalidParameter; use Rebuy\Tests\Amqp\Consumer\Stubs\ConsumerWithPrefetchCount; @@ -49,7 +50,7 @@ public function parser_should_use_default_prefetch_count() } /** - * @tests + * @test */ public function parser_should_use_prefetch_count_from_annotation() { @@ -62,6 +63,21 @@ public function parser_should_use_prefetch_count_from_annotation() verify($consumerMethod->getPrefetchCount())->equals(100); } + /** + * @test + */ + public function parser_should_support_attributes() + { + $parser = new Parser(new AnnotationReader(), 'prefix'); + $consumer = new ConsumerWithAttributes(); + + $consumerMethods = $parser->getConsumerMethods($consumer); + $consumerMethod = $consumerMethods[0]; + + verify($consumerMethod->getConsumerName())->equals('prefix-consume-with-attributes'); + verify($consumerMethod->getPrefetchCount())->equals(100); + } + /** * @test */ diff --git a/tests/Rebuy/Tests/Amqp/Consumer/Stubs/ConsumerWithAttributes.php b/tests/Rebuy/Tests/Amqp/Consumer/Stubs/ConsumerWithAttributes.php new file mode 100644 index 0000000..3c72a87 --- /dev/null +++ b/tests/Rebuy/Tests/Amqp/Consumer/Stubs/ConsumerWithAttributes.php @@ -0,0 +1,11 @@ +