Skip to content

Commit

Permalink
feat: channel attribute extraction
Browse files Browse the repository at this point in the history
  • Loading branch information
Ferror committed Feb 3, 2024
1 parent 9a828a9 commit 02268b6
Show file tree
Hide file tree
Showing 16 changed files with 198 additions and 93 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
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
40 changes: 40 additions & 0 deletions tests/Unit/Schema/V2/ChannelRendererTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Ferror\AsyncapiDocBundle\Tests\Unit\Schema\V2;

use Ferror\AsyncapiDocBundle\Schema\V2\ChannelRenderer;
use PHPUnit\Framework\TestCase;

class ChannelRendererTest extends TestCase
{
public function testSingleChannel(): void
{
$document = [
'name' => 'UserSignedUp',
'channels' => [
[
'name' => 'UserSignedUpChannel',
'type' => 'subscribe',
]
]
];

$schema = new ChannelRenderer();

$actual = $schema->render($document);

$expected = [
'UserSignedUpChannel' => [
'subscribe' => [
'message' => [
'$ref' => '#/components/messages/UserSignedUp',
]
]
]
];

$this->assertEquals($expected, $actual);
}
}
Loading

0 comments on commit 02268b6

Please sign in to comment.