Skip to content

Commit

Permalink
feat: channel attribute extraction (#22)
Browse files Browse the repository at this point in the history
Part of migration to Schema V3. The channel should be extracted from
message as there may be many channels for one message and in V3 version
the new operation attribute is coming.
  • Loading branch information
Ferror authored Feb 3, 2024
1 parent 9a828a9 commit 34c460d
Show file tree
Hide file tree
Showing 18 changed files with 204 additions and 95 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ ferror_asyncapi_doc_bundle_html:
```php
use Ferror\AsyncapiDocBundle\Attribute\Message;
use Ferror\AsyncapiDocBundle\Attribute\Channel;

#[Message(name: 'ProductCreated', channel: 'product.created')]
#[Message(name: 'ProductCreated')]
#[Channel(name: 'product.created')] // optional
final readonly class ProductCreated
{
public function __construct(
Expand All @@ -81,7 +83,8 @@ use Ferror\AsyncapiDocBundle\Attribute as AA;
use Ferror\AsyncapiDocBundle\Schema\Format;
use Ferror\AsyncapiDocBundle\Schema\PropertyType;

#[AA\Message(name: 'ProductCreated', channel: 'product.created')]
#[AA\Message(name: 'ProductCreated')]
#[AA\Channel(name: 'product.created')] // optional
final readonly class ProductCreated
{
public function __construct(
Expand Down
4 changes: 3 additions & 1 deletion example/src/ProductCreated.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
namespace App;

use DateTime;
use Ferror\AsyncapiDocBundle\Attribute\Channel;
use Ferror\AsyncapiDocBundle\Attribute\Message;
use Ferror\AsyncapiDocBundle\Attribute\Property;
use Ferror\AsyncapiDocBundle\Attribute\PropertyArray;
use Ferror\AsyncapiDocBundle\Schema\Format;
use Ferror\AsyncapiDocBundle\Schema\PropertyType;

#[Message(name: 'ProductCreated', channel: 'product.created')]
#[Message(name: 'ProductCreated')]
#[Channel(name: 'product.created')]
final readonly class ProductCreated
{
/**
Expand Down
4 changes: 3 additions & 1 deletion example/src/UserSignedUp.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

namespace App;

use Ferror\AsyncapiDocBundle\Attribute\Channel;
use Ferror\AsyncapiDocBundle\Attribute\Message;

#[Message(name: 'UserSignedUp', channel: 'user_signed_up')]
#[Message(name: 'UserSignedUp')]
#[Channel(name: 'user_signed_up')]
final readonly class UserSignedUp
{
public function __construct(
Expand Down
3 changes: 3 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<testsuite name="all">
<directory>tests</directory>
</testsuite>
<testsuite name="unit">
<directory>tests/Unit</directory>
</testsuite>
</testsuites>

<php>
Expand Down
26 changes: 26 additions & 0 deletions src/Attribute/Channel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Ferror\AsyncapiDocBundle\Attribute;

use Attribute;
use Ferror\AsyncapiDocBundle\Schema\V2\ChannelType;

#[Attribute(Attribute::TARGET_CLASS)]
readonly class Channel
{
public function __construct(
public string $name,
public ChannelType $type = ChannelType::SUBSCRIBE,
) {
}

public function toArray(): array
{
return [
'name' => $this->name,
'type' => $this->type->value,
];
}
}
13 changes: 8 additions & 5 deletions src/Attribute/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,27 @@
namespace Ferror\AsyncapiDocBundle\Attribute;

use Attribute;
use Ferror\AsyncapiDocBundle\Schema\V2\ChannelType;

#[Attribute(Attribute::TARGET_CLASS)]
class Message
{
/**
* @param array<Property|PropertyArray|PropertyEnum|PropertyObject|PropertyArrayObject> $properties
* @param Channel[] $channels
*/
public function __construct(
public readonly string $name,
public readonly string $channel,
public array $properties = [],
public readonly ChannelType $channelType = ChannelType::SUBSCRIBE,
public array $channels = [],
) {
}

public function toArray(): array
{
return [
'name' => $this->name,
'channel' => $this->channel,
'properties' => array_map(static fn(PropertyInterface $property) => $property->toArray(), $this->properties),
'channelType' => $this->channelType->value,
'channels' => array_map(static fn(Channel $channel) => $channel->toArray(), $this->channels),
];
}

Expand All @@ -36,6 +34,11 @@ public function addProperty(Property|PropertyArray|PropertyEnum|PropertyObject|P
$this->properties[] = $property;
}

public function addChannel(Channel $channel): void
{
$this->channels[] = $channel;
}

public function enrich(self $self): self
{
// UPDATE EXISTING
Expand Down
9 changes: 9 additions & 0 deletions src/DocumentationStrategy/AttributeDocumentationStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Ferror\AsyncapiDocBundle\DocumentationStrategy;

use Ferror\AsyncapiDocBundle\Attribute\Channel;
use Ferror\AsyncapiDocBundle\Attribute\Message;
use ReflectionAttribute;
use ReflectionClass;
Expand Down Expand Up @@ -41,6 +42,14 @@ public function document(string $class): Message
$message->addProperty($property);
}

// Channels are optional as it's possible to document just Messages.
/** @var ReflectionAttribute<Channel>[] $messageAttributes */
$channelAttributes = $reflection->getAttributes(Channel::class);

foreach ($channelAttributes as $channelAttribute) {
$message->addChannel($channelAttribute->newInstance());
}

return $message;
}
}
18 changes: 11 additions & 7 deletions src/Schema/V2/ChannelRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@ class ChannelRenderer
{
public function render(array $document): array
{
$channel[$document['channel']] = [
$document['channelType'] => [
'message' => [
'$ref' => '#/components/messages/' . $document['name'],
$channels = [];

foreach ($document['channels'] as $channel) {
$channels[$channel['name']] = [
$channel['type'] => [
'message' => [
'$ref' => '#/components/messages/' . $document['name'],
],
],
],
];
];
}

return $channel;
return $channels;
}
}
4 changes: 3 additions & 1 deletion tests/Examples/PaymentExecuted.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@

namespace Ferror\AsyncapiDocBundle\Tests\Examples;

use Ferror\AsyncapiDocBundle\Attribute\Channel;
use Ferror\AsyncapiDocBundle\Attribute\Message;

/**
* This class represents an example of documenting by ReflectionStrategy
*/
#[Message(name: 'PaymentExecuted', channel: 'payment_executed')]
#[Message(name: 'PaymentExecuted')]
#[Channel(name: 'payment_executed')]
final readonly class PaymentExecuted
{
public function __construct(
Expand Down
4 changes: 3 additions & 1 deletion tests/Examples/ProductCreated.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Ferror\AsyncapiDocBundle\Tests\Examples;

use DateTime;
use Ferror\AsyncapiDocBundle\Attribute\Channel;
use Ferror\AsyncapiDocBundle\Attribute\Message;
use Ferror\AsyncapiDocBundle\Attribute\Property;
use Ferror\AsyncapiDocBundle\Attribute\PropertyArray;
Expand All @@ -17,7 +18,8 @@
/**
* This class represents an example of documenting by AttributeStrategy. It contains all types.
*/
#[Message(name: 'ProductCreated', channel: 'product.created')]
#[Message(name: 'ProductCreated')]
#[Channel(name: 'product.created')]
final readonly class ProductCreated
{
/**
Expand Down
3 changes: 2 additions & 1 deletion tests/Examples/ProductUpdated.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Ferror\AsyncapiDocBundle\Tests\Examples;

use DateTime;
use Ferror\AsyncapiDocBundle\Attribute\Channel;
use Ferror\AsyncapiDocBundle\Attribute\Message;
use Ferror\AsyncapiDocBundle\Attribute\Property;
use Ferror\AsyncapiDocBundle\Attribute\PropertyArray;
Expand All @@ -19,7 +20,6 @@
*/
#[Message(
name: 'ProductUpdated',
channel: 'product.updated',
properties: [
new Property(name: 'id', type: PropertyType::INTEGER),
new Property(name: 'amount', type: PropertyType::FLOAT),
Expand All @@ -32,6 +32,7 @@
new PropertyArray(name: 'tags', itemsType: PropertyType::STRING),
],
)]
#[Channel(name: 'product.updated')]
final readonly class ProductUpdated
{
/**
Expand Down
4 changes: 3 additions & 1 deletion tests/Examples/UserSignedUp.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Ferror\AsyncapiDocBundle\Tests\Examples;

use Ferror\AsyncapiDocBundle\Attribute\Channel;
use Ferror\AsyncapiDocBundle\Attribute\Message;
use Ferror\AsyncapiDocBundle\Attribute\Property;
use Ferror\AsyncapiDocBundle\Schema\Format;
Expand All @@ -12,7 +13,8 @@
/**
* This class represents a SIMPLE example of documenting by AttributeStrategy.
*/
#[Message(name: 'UserSignedUp', channel: 'user_signed_up')]
#[Message(name: 'UserSignedUp')]
#[Channel(name: 'user_signed_up')]
final readonly class UserSignedUp
{
public function __construct(
Expand Down
8 changes: 4 additions & 4 deletions tests/Unit/Attribute/MessageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ final class MessageTest extends TestCase
{
public function testEnrichAddsProperty(): void
{
$message = new Message('name', 'channel');
$message = new Message('name');

$message->enrich(new Message('name', 'channel', [new Property('name')]));
$message->enrich(new Message('name', [new Property('name')]));

$this->assertCount(1, $message->properties);
}

public function testEnrichUpdatesProperty(): void
{
$message = new Message('name', 'channel', [new Property('name')]);
$message = new Message('name', [new Property('name')]);

$message->enrich(new Message('name', 'channel', [new Property('name', 'Nice Description')]));
$message->enrich(new Message('name', [new Property('name', 'Nice Description')]));

$this->assertEquals('Nice Description', $message->properties[0]->description);
}
Expand Down
3 changes: 1 addition & 2 deletions tests/Unit/DocumentationEditorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ public function testDocument(): void

$expected = [
'name' => 'PaymentExecuted',
'channel' => 'payment_executed',
'channelType' => 'subscribe',
'properties' => [
[
'name' => 'amount',
Expand All @@ -44,6 +42,7 @@ public function testDocument(): void
'example' => null,
],
],
'channels' => [],
];

$this->assertEquals($expected, $actual);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ public function testUserSignedUp(): void

$expected = [
'name' => 'UserSignedUp',
'channel' => 'user_signed_up',
'channelType' => 'subscribe',
'properties' => [
[
'name' => 'name',
Expand Down Expand Up @@ -56,6 +54,12 @@ public function testUserSignedUp(): void
'required' => true,
],
],
'channels' => [
[
'name' => 'user_signed_up',
'type' => 'subscribe',
],
],
];

$this->assertEquals($expected, $actual);
Expand All @@ -69,8 +73,6 @@ public function testProductCreated(): void

$expected = [
'name' => 'ProductCreated',
'channel' => 'product.created',
'channelType' => 'subscribe',
'properties' => [
[
'name' => 'id',
Expand Down Expand Up @@ -146,6 +148,12 @@ public function testProductCreated(): void
'required' => true,
],
],
'channels' => [
[
'name' => 'product.created',
'type' => 'subscribe',
],
],
];

$this->assertEquals($expected, $actual);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ public function test(): void

$expected = [
'name' => 'UserSignedUp',
'channel' => 'user_signed_up',
'channelType' => 'subscribe',
'properties' => [
[
'name' => 'name',
Expand Down Expand Up @@ -53,6 +51,7 @@ public function test(): void
'example' => null,
],
],
'channels' => [],
];

$this->assertEquals($expected, $documentation->document(UserSignedUp::class)->toArray());
Expand All @@ -64,8 +63,6 @@ public function testEnum(): void

$expected = [
'name' => 'ProductCreated',
'channel' => 'product.created',
'channelType' => 'subscribe',
'properties' => [
[
'name' => 'id',
Expand Down Expand Up @@ -100,6 +97,7 @@ public function testEnum(): void
'example' => null
],
],
'channels' => [],
];


Expand Down
Loading

0 comments on commit 34c460d

Please sign in to comment.