diff --git a/src/Attribute/Message.php b/src/Attribute/Message.php index 5ff21de..a1046d5 100644 --- a/src/Attribute/Message.php +++ b/src/Attribute/Message.php @@ -11,7 +11,7 @@ class Message { /** - * @param PropertyInterface[] $properties + * @param array $properties */ public function __construct( public readonly string $name, @@ -31,7 +31,7 @@ public function toArray(): array ]; } - public function addProperty(PropertyInterface $property): void + public function addProperty(Property|PropertyArray|PropertyEnum|PropertyObject|PropertyArrayObject $property): void { $this->properties[] = $property; } diff --git a/src/DocumentationEditor.php b/src/DocumentationEditor.php index a844eb5..de22c4f 100644 --- a/src/DocumentationEditor.php +++ b/src/DocumentationEditor.php @@ -26,7 +26,7 @@ public function document(string $class): Message $strategies[$documentationStrategy::getDefaultPriority()] = $documentationStrategy; } - $firstStrategy = array_pop($strategies); + $firstStrategy = array_shift($strategies); $documentedMessage = $firstStrategy->document($class); diff --git a/src/DocumentationStrategy/PropertyExtractor.php b/src/DocumentationStrategy/PropertyExtractor.php index 446af0d..4467a98 100644 --- a/src/DocumentationStrategy/PropertyExtractor.php +++ b/src/DocumentationStrategy/PropertyExtractor.php @@ -17,7 +17,7 @@ class PropertyExtractor { /** - * @return iterable + * @return iterable * * @throws ReflectionException */ diff --git a/src/DocumentationStrategy/ReflectionDocumentationStrategy.php b/src/DocumentationStrategy/ReflectionDocumentationStrategy.php index e405093..b30d286 100644 --- a/src/DocumentationStrategy/ReflectionDocumentationStrategy.php +++ b/src/DocumentationStrategy/ReflectionDocumentationStrategy.php @@ -43,13 +43,25 @@ public function document(string $class): Message $type = $property->getType(); $name = $property->getName(); - $message->addProperty( - new Property( - name: $name, - type: PropertyType::fromNative($type?->getName()), - required: $type && !$type->allowsNull(), - ) - ); + if (null === $type) { + break; + } + + // ATM we don't support array types in ReflectionStrategy + if (in_array($type->getName(), ['array', 'object', 'resource'])) { + break; + } + + // ATM we support only builtin types like integer, string, boolean, float + if ($type->isBuiltin()) { + $message->addProperty( + new Property( + name: $name, + type: PropertyType::fromNative($type->getName()), + required: !$type->allowsNull(), + ) + ); + } } return $message; diff --git a/tests/Examples/PaymentExecuted.php b/tests/Examples/PaymentExecuted.php index f7e5032..984c5c2 100644 --- a/tests/Examples/PaymentExecuted.php +++ b/tests/Examples/PaymentExecuted.php @@ -5,16 +5,15 @@ namespace Ferror\AsyncapiDocBundle\Tests\Examples; use Ferror\AsyncapiDocBundle\Attribute\Message; -use Ferror\AsyncapiDocBundle\Attribute\Property; -use Ferror\AsyncapiDocBundle\Schema\Format; -use Ferror\AsyncapiDocBundle\Schema\PropertyType; +/** + * This class represents an example of documenting by ReflectionStrategy + */ #[Message(name: 'PaymentExecuted', channel: 'payment_executed')] final readonly class PaymentExecuted { public function __construct( public float $amount, - #[Property(name: 'createdAt', type: PropertyType::STRING, description: 'Creation date', format: Format::DATETIME, example: '2023-11-23 13:41:21')] public string $createdAt, ) { } diff --git a/tests/Examples/ProductCreated.php b/tests/Examples/ProductCreated.php index abedbd4..74e5e84 100644 --- a/tests/Examples/ProductCreated.php +++ b/tests/Examples/ProductCreated.php @@ -14,6 +14,9 @@ use Ferror\AsyncapiDocBundle\Schema\Format; use Ferror\AsyncapiDocBundle\Schema\PropertyType; +/** + * This class represents an example of documenting by AttributeStrategy. It contains all types. + */ #[Message(name: 'ProductCreated', channel: 'product.created')] final readonly class ProductCreated { diff --git a/tests/Examples/ProductUpdated.php b/tests/Examples/ProductUpdated.php index cc5e6d7..7553f34 100644 --- a/tests/Examples/ProductUpdated.php +++ b/tests/Examples/ProductUpdated.php @@ -14,6 +14,9 @@ use Ferror\AsyncapiDocBundle\Schema\Format; use Ferror\AsyncapiDocBundle\Schema\PropertyType; +/** + * This class represents an example of documenting by AttributeStrategy. The properties are provided via objects. + */ #[Message( name: 'ProductUpdated', channel: 'product.updated', diff --git a/tests/Examples/UserSignedUp.php b/tests/Examples/UserSignedUp.php index 0fb4c10..0854989 100644 --- a/tests/Examples/UserSignedUp.php +++ b/tests/Examples/UserSignedUp.php @@ -9,6 +9,9 @@ use Ferror\AsyncapiDocBundle\Schema\Format; use Ferror\AsyncapiDocBundle\Schema\PropertyType; +/** + * This class represents a SIMPLE example of documenting by AttributeStrategy. + */ #[Message(name: 'UserSignedUp', channel: 'user_signed_up')] final readonly class UserSignedUp { diff --git a/tests/Integration/DumpSpecificationConsoleTest.php b/tests/Integration/DumpSpecificationConsoleTest.php index 3b487d3..2450c8f 100644 --- a/tests/Integration/DumpSpecificationConsoleTest.php +++ b/tests/Integration/DumpSpecificationConsoleTest.php @@ -140,14 +140,8 @@ public function testExecuteYaml(): void properties: amount: type: number - description: 'Payment amount' - format: float - example: '1000' createdAt: type: string - description: 'Creation date' - format: date-time - example: '2023-11-23 13:41:21' required: - amount - createdAt @@ -284,12 +278,12 @@ public function testExecuteJson(): void "example": "true" } }, - "required": [ - "name", - "email", - "age", - "isCitizen" - ] + "required": [ + "name", + "email", + "age", + "isCitizen" + ] } }, "PaymentExecuted": { @@ -297,22 +291,16 @@ public function testExecuteJson(): void "type": "object", "properties": { "amount": { - "type": "number", - "description": "Payment amount", - "format": "float", - "example": "1000" + "type": "number" }, "createdAt": { - "type": "string", - "description": "Creation date", - "format": "date-time", - "example": "2023-11-23 13:41:21" + "type": "string" } }, - "required": [ - "amount", - "createdAt" - ] + "required": [ + "amount", + "createdAt" + ] } }, "ProductCreated": { @@ -348,17 +336,17 @@ public function testExecuteJson(): void "type": "string" } }, - "required": [ - "id", - "amount", - "currency", - "isPaid", - "createdAt", - "week", - "payment", - "products", - "tags" - ] + "required": [ + "id", + "amount", + "currency", + "isPaid", + "createdAt", + "week", + "payment", + "products", + "tags" + ] } } } diff --git a/tests/Unit/DocumentationEditorTest.php b/tests/Unit/DocumentationEditorTest.php index 9f20c38..cb46f87 100644 --- a/tests/Unit/DocumentationEditorTest.php +++ b/tests/Unit/DocumentationEditorTest.php @@ -23,22 +23,25 @@ public function testDocument(): void $actual = $documentationEditor->document(PaymentExecuted::class)->toArray(); $expected = [ - 'name' => "PaymentExecuted", - 'channel' => "payment_executed", - "channelType" => "subscribe", + 'name' => 'PaymentExecuted', + 'channel' => 'payment_executed', + 'channelType' => 'subscribe', 'properties' => [ [ - "name" => "amount", - "required" => true, - "type" => "float", + 'name' => 'amount', + 'required' => true, + 'type' => 'number', + 'description' => '', + 'format' => null, + 'example' => null, ], [ - "name" => "createdAt", - "description" => "Creation date", - "required" => true, - "type" => "string", - "format" => "date-time", - "example" => "2023-11-23 13:41:21", + 'name' => 'createdAt', + 'description' => '', + 'required' => true, + 'type' => 'string', + 'format' => null, + 'example' => null, ], ], ]; diff --git a/tests/Unit/DocumentationStrategy/ReflectionDocumentationStrategyTest.php b/tests/Unit/DocumentationStrategy/ReflectionDocumentationStrategyTest.php index 613bf78..29abcc5 100644 --- a/tests/Unit/DocumentationStrategy/ReflectionDocumentationStrategyTest.php +++ b/tests/Unit/DocumentationStrategy/ReflectionDocumentationStrategyTest.php @@ -5,6 +5,7 @@ namespace Ferror\AsyncapiDocBundle\Tests\Unit\DocumentationStrategy; use Ferror\AsyncapiDocBundle\DocumentationStrategy\ReflectionDocumentationStrategy; +use Ferror\AsyncapiDocBundle\Tests\Examples\ProductCreated; use Ferror\AsyncapiDocBundle\Tests\Examples\UserSignedUp; use PHPUnit\Framework\TestCase; @@ -56,4 +57,54 @@ public function test(): void $this->assertEquals($expected, $documentation->document(UserSignedUp::class)->toArray()); } + + public function testEnum(): void + { + $documentation = new ReflectionDocumentationStrategy(); + + $expected = [ + 'name' => 'ProductCreated', + 'channel' => 'product.created', + 'channelType' => 'subscribe', + 'properties' => [ + [ + 'name' => 'id', + 'description' => '', + 'required' => true, + 'type' => 'integer', + 'format' => null, + 'example' => null + ], + [ + 'name' => 'amount', + 'description' => '', + 'required' => true, + 'type' => 'number', + 'format' => null, + 'example' => null + ], + [ + 'name' => 'currency', + 'description' => '', + 'required' => true, + 'type' => 'string', + 'format' => null, + 'example' => null + ], + [ + 'name' => 'isPaid', + 'description' => '', + 'required' => true, + 'type' => 'boolean', + 'format' => null, + 'example' => null + ], + ], + ]; + + + $actual = $documentation->document(ProductCreated::class)->toArray(); + + $this->assertEquals($expected, $actual); + } } diff --git a/tests/Unit/Symfony/Controller/JsonSpecificationControllerTest.php b/tests/Unit/Symfony/Controller/JsonSpecificationControllerTest.php index 7417362..d8807e4 100644 --- a/tests/Unit/Symfony/Controller/JsonSpecificationControllerTest.php +++ b/tests/Unit/Symfony/Controller/JsonSpecificationControllerTest.php @@ -8,6 +8,7 @@ use Ferror\AsyncapiDocBundle\DocumentationEditor; use Ferror\AsyncapiDocBundle\DocumentationStrategy\AttributeDocumentationStrategy; use Ferror\AsyncapiDocBundle\DocumentationStrategy\PropertyExtractor; +use Ferror\AsyncapiDocBundle\DocumentationStrategy\ReflectionDocumentationStrategy; use Ferror\AsyncapiDocBundle\Generator\JsonGenerator; use Ferror\AsyncapiDocBundle\Schema\V2\ChannelRenderer; use Ferror\AsyncapiDocBundle\Schema\V2\InfoRenderer; @@ -32,7 +33,8 @@ public function test(): void ProductCreated::class, ]), new DocumentationEditor([ - new AttributeDocumentationStrategy(new PropertyExtractor()) + new AttributeDocumentationStrategy(new PropertyExtractor()), + new ReflectionDocumentationStrategy(), ]), new ChannelRenderer(), new MessageRenderer(), @@ -106,12 +108,12 @@ public function test(): void "example": "true" } }, - "required": [ - "name", - "email", - "age", - "isCitizen" - ] + "required": [ + "name", + "email", + "age", + "isCitizen" + ] } }, "PaymentExecuted": { @@ -119,22 +121,16 @@ public function test(): void "type": "object", "properties": { "amount": { - "type": "number", - "description": "Payment amount", - "format": "float", - "example": "1000" + "type": "number" }, "createdAt": { - "type": "string", - "description": "Creation date", - "format": "date-time", - "example": "2023-11-23 13:41:21" + "type": "string" } }, - "required": [ - "amount", - "createdAt" - ] + "required": [ + "amount", + "createdAt" + ] } }, "ProductCreated": { @@ -170,17 +166,17 @@ public function test(): void "type": "string" } }, - "required": [ - "id", - "amount", - "currency", - "isPaid", - "createdAt", - "week", - "payment", - "products", - "tags" - ] + "required": [ + "id", + "amount", + "currency", + "isPaid", + "createdAt", + "week", + "payment", + "products", + "tags" + ] } } } diff --git a/tests/Unit/Symfony/Controller/YamlSpecificationControllerTest.php b/tests/Unit/Symfony/Controller/YamlSpecificationControllerTest.php index d168877..d8912f3 100644 --- a/tests/Unit/Symfony/Controller/YamlSpecificationControllerTest.php +++ b/tests/Unit/Symfony/Controller/YamlSpecificationControllerTest.php @@ -8,6 +8,7 @@ use Ferror\AsyncapiDocBundle\DocumentationEditor; use Ferror\AsyncapiDocBundle\DocumentationStrategy\AttributeDocumentationStrategy; use Ferror\AsyncapiDocBundle\DocumentationStrategy\PropertyExtractor; +use Ferror\AsyncapiDocBundle\DocumentationStrategy\ReflectionDocumentationStrategy; use Ferror\AsyncapiDocBundle\Generator\YamlGenerator; use Ferror\AsyncapiDocBundle\Schema\V2\ChannelRenderer; use Ferror\AsyncapiDocBundle\Schema\V2\InfoRenderer; @@ -32,7 +33,8 @@ public function test(): void ProductCreated::class, ]), new DocumentationEditor([ - new AttributeDocumentationStrategy(new PropertyExtractor()) + new AttributeDocumentationStrategy(new PropertyExtractor()), + new ReflectionDocumentationStrategy(), ]), new ChannelRenderer(), new MessageRenderer(), @@ -100,14 +102,8 @@ public function test(): void properties: amount: type: number - description: 'Payment amount' - format: float - example: '1000' createdAt: type: string - description: 'Creation date' - format: date-time - example: '2023-11-23 13:41:21' required: - amount - createdAt