Skip to content

Commit

Permalink
Merge pull request #13 from rebuy-de/attribute-support
Browse files Browse the repository at this point in the history
  • Loading branch information
Spea authored Jul 28, 2023
2 parents f1c3427 + db333c7 commit 9ddc54d
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 54 deletions.
13 changes: 9 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
}
],
"require": {
"php": "^7.2|^8.0",
"php-amqplib/php-amqplib": "^2.12.3|^3.0.0",
"doctrine/annotations": "^1.10",
"php": "^8.1",
"php-amqplib/php-amqplib": "^3.0.0",
"doctrine/annotations": "^1.13.3|^2.0.1",
"symfony/event-dispatcher": "^4.4|^5.0|^6.0",
"doctrine/collections": "^1.6"
"doctrine/collections": "^1.6|^2.1.2"
},
"require-dev": {
"jms/serializer": "^3.15.0",
Expand All @@ -36,6 +36,11 @@
"Rebuy\\Amqp\\Consumer\\": "src/Rebuy/Amqp/Consumer"
}
},
"autoload-dev": {
"psr-4": {
"Rebuy\\Tests\\": "tests/Rebuy/Tests"
}
},
"suggest": {
"psr/log": "required if you'd like to use the LogHandler or LogSubscriber",
"league/statsd": "required if you'd like to use the TimingSubscriber",
Expand Down
2 changes: 1 addition & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
bootstrap="./tests/bootstrap.php"
bootstrap="vendor/autoload.php"
>
<testsuites>
<testsuite name="Rebuy AMQP Test Suite">
Expand Down
21 changes: 10 additions & 11 deletions src/Rebuy/Amqp/Consumer/Annotation/Consumer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
) {
}
}
18 changes: 8 additions & 10 deletions src/Rebuy/Amqp/Consumer/Annotation/ConsumerContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ public function getBindings()
return [];
}

$class = $this->method->getParameters()[0]->getClass();
$class = $this->method->getParameters()[0]->getType()?->getName();
if (null === $class) {
return [];
}

if (!$class->implementsInterface(MessageInterface::class)) {
if (!is_a($class, MessageInterface::class, true)) {
return [];
}

Expand All @@ -76,22 +76,20 @@ public function getConsumerIdentification()
*/
public function getRoutingKey()
{
$class = $this->method->getParameters()[0]->getClass();
$class = $this->method->getParameters()[0]->getType()?->getName();
if (!is_a($class, MessageInterface::class, true)) {
return null;
}

return $class->getMethod('getRoutingKey')->invoke(null);
return $class::getRoutingKey();
}

/**
* @return string
*/
public function getMessageClass()
{
$class = $this->method->getParameters()[0]->getClass();
if (null === $class) {
return null;
}

return $class->getName();
return $this->method->getParameters()[0]->getType()?->getName();
}

/**
Expand Down
19 changes: 16 additions & 3 deletions src/Rebuy/Amqp/Consumer/Annotation/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -65,8 +64,22 @@ private function validateMethod(ReflectionMethod $method)
}

$parameter = $method->getParameters()[0];
if (null === $parameter->getClass() || !$parameter->getClass()->implementsInterface(MessageInterface::class)) {
$class = $parameter->getType()?->getName();
if (!is_a($class, MessageInterface::class, true)) {
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);

}
}
3 changes: 0 additions & 3 deletions src/Rebuy/Amqp/Consumer/ClientInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
namespace Rebuy\Amqp\Consumer;

use InvalidArgumentException;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\Serializer;
use PhpAmqpLib\Channel\AMQPChannel;
use PhpAmqpLib\Message\AMQPMessage;
use Rebuy\Amqp\Consumer\Message\MessageInterface;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function invoke_should_invoke_reflection()
self::TEST_PREFIX,
$consumer,
$reflectionMethod->reveal(),
new ConsumerAnnotation()
new ConsumerAnnotation('name')
);
$container->invoke($payload);
}
Expand All @@ -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();
Expand All @@ -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
*/
Expand All @@ -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();
Expand All @@ -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();
Expand All @@ -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();
Expand All @@ -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();
Expand All @@ -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();
Expand Down
18 changes: 17 additions & 1 deletion tests/Rebuy/Tests/Amqp/Consumer/Annotation/ParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -49,7 +50,7 @@ public function parser_should_use_default_prefetch_count()
}

/**
* @tests
* @test
*/
public function parser_should_use_prefetch_count_from_annotation()
{
Expand All @@ -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
*/
Expand Down
11 changes: 11 additions & 0 deletions tests/Rebuy/Tests/Amqp/Consumer/Stubs/ConsumerWithAttributes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Rebuy\Tests\Amqp\Consumer\Stubs;

class ConsumerWithAttributes
{
#[\Rebuy\Amqp\Consumer\Annotation\Consumer(name: 'consume-with-attributes', prefetchCount: 100)]
public function consume(Message $message)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public function preConsume_with_postConsume_should_add_timing_entry()
$consumerName = 'consumer';
$eventName = $consumerName . '-' . $deliveryTag;
$message = new AMQPMessage('body');
$message->delivery_info['delivery_tag'] = $deliveryTag;
$message->setDeliveryTag($deliveryTag);

$container = $this->prophesize(ConsumerContainer::class);
$container->getConsumerName()->willReturn($consumerName);
Expand Down
12 changes: 0 additions & 12 deletions tests/bootstrap.php

This file was deleted.

0 comments on commit 9ddc54d

Please sign in to comment.