From 529b58364c2f0fa214d54aa092379ba85ce350f4 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 20 Aug 2025 22:04:45 +0300 Subject: [PATCH 01/24] #4 delete files --- src/Extractors/ParametersExtractor.php | 46 ----------- .../ParametersExtractor/ExtractTest.php | 79 ------------------- 2 files changed, 125 deletions(-) delete mode 100644 src/Extractors/ParametersExtractor.php delete mode 100644 tests/Unit/Extractors/ParametersExtractor/ExtractTest.php diff --git a/src/Extractors/ParametersExtractor.php b/src/Extractors/ParametersExtractor.php deleted file mode 100644 index 48736b5..0000000 --- a/src/Extractors/ParametersExtractor.php +++ /dev/null @@ -1,46 +0,0 @@ -parameters as $argument) { - $type = $argument->getType(); - - if (!$type instanceof ReflectionNamedType) { - continue; - } - - $nameArgument = $type->getName(); - - if (! class_exists($nameArgument)) { - continue; - } - - $parentResolver = new ParentClassResolver($nameArgument); - - if ($parentResolver->isInstanceOf(Data::class)) { - return $nameArgument; - } - } - - return ''; - } -} diff --git a/tests/Unit/Extractors/ParametersExtractor/ExtractTest.php b/tests/Unit/Extractors/ParametersExtractor/ExtractTest.php deleted file mode 100644 index 688f9ca..0000000 --- a/tests/Unit/Extractors/ParametersExtractor/ExtractTest.php +++ /dev/null @@ -1,79 +0,0 @@ -method->getParameters()); - - $result = $laravelDataExtractor->extract(); - - expect($result)->toBe(ParentClassLaravelData::class); -}); - -test('extract class laravel data from withoutLaravelData', function (): void { - $route = new Route('', '', [LaravelDataController::class, 'withoutLaravelData']); - $extractMethod = ExtractedEndpointData::fromRoute($route); - - $laravelDataExtractor = new ParametersExtractor($extractMethod->method->getParameters()); - - $result = $laravelDataExtractor->extract(); - - expect($result)->toBeEmpty(); -}); - -test('extract class laravel data from emptyMethod', function (): void { - $route = new Route('', '', [LaravelDataController::class, 'emptyMethod']); - $extractMethod = ExtractedEndpointData::fromRoute($route); - - $laravelDataExtractor = new ParametersExtractor($extractMethod->method->getParameters()); - - $result = $laravelDataExtractor->extract(); - - expect($result)->toBeEmpty(); -}); - -test('extract class laravel data from moreParameters', function (): void { - $route = new Route('', '', [LaravelDataController::class, 'moreParameters']); - $extractMethod = ExtractedEndpointData::fromRoute($route); - - $laravelDataExtractor = new ParametersExtractor($extractMethod->method->getParameters()); - - $result = $laravelDataExtractor->extract(); - - expect($result)->toBeEmpty(); -}); - -test('extract class laravel data from requestRules', function (): void { - $route = new Route('', '', [LaravelDataController::class, 'requestRules']); - $extractMethod = ExtractedEndpointData::fromRoute($route); - - $laravelDataExtractor = new ParametersExtractor($extractMethod->method->getParameters()); - - $result = $laravelDataExtractor->extract(); - - expect($result)->toBeEmpty(); -}); - -test('extract class laravel data from requestAndEmptyLaravelData', function (): void { - $route = new Route('', '', [LaravelDataController::class, 'requestAndEmptyLaravelData']); - $extractMethod = ExtractedEndpointData::fromRoute($route); - - $laravelDataExtractor = new ParametersExtractor($extractMethod->method->getParameters()); - - $result = $laravelDataExtractor->extract(); - - expect($result)->toBe(ParentClassLaravelData::class); -}); From a95eb75cbaaea7d4514aa1a37bd4c6e318b4a511 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 20 Aug 2025 22:05:05 +0300 Subject: [PATCH 02/24] #4 add new methods with attr body param --- .../Controllers/LaravelDataController.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/Fixtures/Controllers/LaravelDataController.php b/tests/Fixtures/Controllers/LaravelDataController.php index 5fe1714..0c1bbdd 100644 --- a/tests/Fixtures/Controllers/LaravelDataController.php +++ b/tests/Fixtures/Controllers/LaravelDataController.php @@ -4,6 +4,7 @@ namespace Tests\Fixtures\Controllers; +use Knuckles\Scribe\Attributes\BodyParam; use Tests\Fixtures\LaravelData\AttributeRules; use Tests\Fixtures\LaravelData\CustomAttributeRules; use Tests\Fixtures\LaravelData\ManualRules; @@ -57,4 +58,20 @@ public function requestAndLaravelData(RequestRules $requestRules, AttributeRules public function requestAndEmptyLaravelData(RequestRules $requestRules, ParentClassLaravelData $parentClassLaravelData): void { } + + #[BodyParam('name', 'int', 'updated name', required: false, example: 1)] + public function updateOneBodyParamsFromAttr(AttributeRules $attributeRules): void + { + } + + #[BodyParam('phone', 'bool', 'updated phone', required: true, example: true)] + #[BodyParam('password', 'string', 'updated password', true, 'pass', null, false)] + public function updateAllBodyParamsFromAttr(CustomAttributeRules $customAttributeRules): void + { + } + + #[BodyParam('new', 'string', 'add new params', required: false, example: 'param')] + public function addBodyParamsFromAttr(ManualRules $manualRules): void + { + } } From 97fe1096d5724868743278546efca1d0ed9afdb6 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 20 Aug 2025 22:05:33 +0300 Subject: [PATCH 03/24] #4 update design laravel data extractor --- src/Extractors/Classes/ClassExtract.php | 10 ++++ .../Classes/LaravelDataClassExtract.php | 46 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/Extractors/Classes/ClassExtract.php create mode 100644 src/Extractors/Classes/LaravelDataClassExtract.php diff --git a/src/Extractors/Classes/ClassExtract.php b/src/Extractors/Classes/ClassExtract.php new file mode 100644 index 0000000..7cebfe2 --- /dev/null +++ b/src/Extractors/Classes/ClassExtract.php @@ -0,0 +1,10 @@ +parameters as $argument) { + $type = $argument->getType(); + + if (!$type instanceof ReflectionNamedType) { + continue; + } + + $nameArgument = $type->getName(); + + if (! class_exists($nameArgument)) { + continue; + } + + $parentResolver = new ParentClassResolver($nameArgument); + + if ($parentResolver->isInstanceOf(Data::class)) { + return $nameArgument; + } + } + + return ''; + } +} From 0fbcf1cf281b6ea4ce23d868456527a4ecdcd398 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 20 Aug 2025 22:05:51 +0300 Subject: [PATCH 04/24] #4 add extractor for body param attr --- .../Attributes/AttributeExtract.php | 11 +++++++++ .../Attributes/BodyParamAttributeExtract.php | 23 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/Extractors/Attributes/AttributeExtract.php create mode 100644 src/Extractors/Attributes/BodyParamAttributeExtract.php diff --git a/src/Extractors/Attributes/AttributeExtract.php b/src/Extractors/Attributes/AttributeExtract.php new file mode 100644 index 0000000..159caf6 --- /dev/null +++ b/src/Extractors/Attributes/AttributeExtract.php @@ -0,0 +1,11 @@ + */ + public function extract(): array; +} diff --git a/src/Extractors/Attributes/BodyParamAttributeExtract.php b/src/Extractors/Attributes/BodyParamAttributeExtract.php new file mode 100644 index 0000000..32b138e --- /dev/null +++ b/src/Extractors/Attributes/BodyParamAttributeExtract.php @@ -0,0 +1,23 @@ + Get array arguments or empty array */ + public function extract(): array + { + return ['test' => 'test']; + } +} From 295f9ccf5ba4d3dbb246cda28cc50256f1057927 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 20 Aug 2025 22:07:43 +0300 Subject: [PATCH 05/24] #4 create class for generate doc --- src/Documentations/BodyParamDoc.php | 26 ++++++++++++++++++++++++++ src/Documentations/Doc.php | 10 ++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/Documentations/BodyParamDoc.php create mode 100644 src/Documentations/Doc.php diff --git a/src/Documentations/BodyParamDoc.php b/src/Documentations/BodyParamDoc.php new file mode 100644 index 0000000..d545cb2 --- /dev/null +++ b/src/Documentations/BodyParamDoc.php @@ -0,0 +1,26 @@ +laravelDataClass)) { + return null; + } + + return (new BodyParams($this->laravelDataClass, $this->config))->generate(); + } +} diff --git a/src/Documentations/Doc.php b/src/Documentations/Doc.php new file mode 100644 index 0000000..b5768b4 --- /dev/null +++ b/src/Documentations/Doc.php @@ -0,0 +1,10 @@ + Date: Wed, 20 Aug 2025 22:08:10 +0300 Subject: [PATCH 06/24] #4 updated test --- .../LaravelDataClassExtract/ExtractTest.php | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 tests/Unit/Extractors/LaravelDataClassExtract/ExtractTest.php diff --git a/tests/Unit/Extractors/LaravelDataClassExtract/ExtractTest.php b/tests/Unit/Extractors/LaravelDataClassExtract/ExtractTest.php new file mode 100644 index 0000000..10dc899 --- /dev/null +++ b/tests/Unit/Extractors/LaravelDataClassExtract/ExtractTest.php @@ -0,0 +1,79 @@ +method->getParameters()); + + $result = $laravelDataExtractor->extract(); + + expect($result)->toBe(ParentClassLaravelData::class); +}); + +test('extract class laravel data from withoutLaravelData', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'withoutLaravelData']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $laravelDataExtractor = new LaravelDataClassExtract($extractMethod->method->getParameters()); + + $result = $laravelDataExtractor->extract(); + + expect($result)->toBeEmpty(); +}); + +test('extract class laravel data from emptyMethod', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'emptyMethod']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $laravelDataExtractor = new LaravelDataClassExtract($extractMethod->method->getParameters()); + + $result = $laravelDataExtractor->extract(); + + expect($result)->toBeEmpty(); +}); + +test('extract class laravel data from moreParameters', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'moreParameters']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $laravelDataExtractor = new LaravelDataClassExtract($extractMethod->method->getParameters()); + + $result = $laravelDataExtractor->extract(); + + expect($result)->toBeEmpty(); +}); + +test('extract class laravel data from requestRules', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'requestRules']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $laravelDataExtractor = new LaravelDataClassExtract($extractMethod->method->getParameters()); + + $result = $laravelDataExtractor->extract(); + + expect($result)->toBeEmpty(); +}); + +test('extract class laravel data from requestAndEmptyLaravelData', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'requestAndEmptyLaravelData']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $laravelDataExtractor = new LaravelDataClassExtract($extractMethod->method->getParameters()); + + $result = $laravelDataExtractor->extract(); + + expect($result)->toBe(ParentClassLaravelData::class); +}); From 97fe722804e6ba86d9eb6c26dad070babb5186bc Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 20 Aug 2025 22:08:28 +0300 Subject: [PATCH 07/24] #4 update logic used classes for generate doc --- src/LaravelDataBodyParam.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/LaravelDataBodyParam.php b/src/LaravelDataBodyParam.php index 7794231..898e47d 100755 --- a/src/LaravelDataBodyParam.php +++ b/src/LaravelDataBodyParam.php @@ -4,10 +4,12 @@ namespace DenisKorbakov\LaravelDataScribe; -use DenisKorbakov\LaravelDataScribe\Extractors\ParametersExtractor; -use DenisKorbakov\LaravelDataScribe\Params\BodyParams; +use DenisKorbakov\LaravelDataScribe\Documentations\BodyParamDoc; +use DenisKorbakov\LaravelDataScribe\Extractors\Attributes\BodyParamAttributeExtract; +use DenisKorbakov\LaravelDataScribe\Extractors\Classes\LaravelDataClassExtract; use Knuckles\Camel\Extraction\ExtractedEndpointData; use Knuckles\Scribe\Extracting\Strategies\Strategy; +use ReflectionAttribute; use ReflectionParameter; use Spatie\LaravelData\Data; @@ -23,14 +25,14 @@ public function __invoke(ExtractedEndpointData $endpointData, array $settings = { /** @var ReflectionParameter[] $parameters */ $parameters = $endpointData->method?->getParameters(); + /** @var ReflectionAttribute[] $attributes */ + $attributes = $endpointData->method?->getAttributes(); /** @var class-string $laravelDataClass */ - $laravelDataClass = (new ParametersExtractor($parameters))->extract(); + $laravelDataClass = (new LaravelDataClassExtract($parameters))->extract(); + /** @var array $bodyParamAttribute */ + $bodyParamAttribute = (new BodyParamAttributeExtract($attributes))->extract(); - if (empty($laravelDataClass)) { - return null; - } - - return (new BodyParams($laravelDataClass, $this->config))->generate(); + return (new BodyParamDoc($laravelDataClass, $bodyParamAttribute, $this->config))->generate(); } } From 9caf11fa40162bfe33128d0bad478ce625e0a039 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 20 Aug 2025 22:08:37 +0300 Subject: [PATCH 08/24] #4 add new test case --- tests/Unit/LaravelDataBodyParamTest.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/Unit/LaravelDataBodyParamTest.php b/tests/Unit/LaravelDataBodyParamTest.php index 65a54b2..76b863d 100644 --- a/tests/Unit/LaravelDataBodyParamTest.php +++ b/tests/Unit/LaravelDataBodyParamTest.php @@ -129,3 +129,15 @@ expect($result)->toEqual($this->getParamsAttributeRules()); }); + +test('generate doc body params from method with updateOneBodyParamsFromAttr', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'updateOneBodyParamsFromAttr']); + $laravelDataBodyParam = new LaravelDataBodyParam(new DocumentationConfig()); + + $result = $laravelDataBodyParam(ExtractedEndpointData::fromRoute($route)); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toEqual($this->getParamsAttributeRules()); +}); From 236a1b77af142b9165a7d887f4d877f8c2433501 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 17:05:11 +0300 Subject: [PATCH 09/24] #4 add .gitattributes --- .gitattributes | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9b00bc0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +* text=auto + +/.codecov.yml export-ignore +/.editorconfig export-ignore +/.gitattributes export-ignore +/.github export-ignore +/.gitignore export-ignore +/.phan export-ignore +/.scrutinizer.yml export-ignore +/changelog.md export-ignore +/docs export-ignore +/examples export-ignore +/phpcs.xml.dist export-ignore +/phpdoc.dist.xml export-ignore +/phpunit.xml.dist export-ignore +/test export-ignore +/UPGRADING.md export-ignore From 3d2cf83c404aea1932672de548f29a393998f309 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 17:05:36 +0300 Subject: [PATCH 10/24] #4 add logic in class --- src/Extractors/Attributes/AttributeExtract.php | 2 +- .../Attributes/BodyParamAttributeExtract.php | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Extractors/Attributes/AttributeExtract.php b/src/Extractors/Attributes/AttributeExtract.php index 159caf6..d716665 100644 --- a/src/Extractors/Attributes/AttributeExtract.php +++ b/src/Extractors/Attributes/AttributeExtract.php @@ -6,6 +6,6 @@ interface AttributeExtract { - /** @return array */ + /** @return array> */ public function extract(): array; } diff --git a/src/Extractors/Attributes/BodyParamAttributeExtract.php b/src/Extractors/Attributes/BodyParamAttributeExtract.php index 32b138e..f43a0f2 100644 --- a/src/Extractors/Attributes/BodyParamAttributeExtract.php +++ b/src/Extractors/Attributes/BodyParamAttributeExtract.php @@ -4,6 +4,7 @@ namespace DenisKorbakov\LaravelDataScribe\Extractors\Attributes; +use Knuckles\Scribe\Attributes\BodyParam; use ReflectionAttribute; /** Extracts Body Param attribute from method attributes */ @@ -15,9 +16,19 @@ public function __construct( ) { } - /** @return array Get array arguments or empty array */ + /** @return array> Get array arguments or empty array */ public function extract(): array { - return ['test' => 'test']; + $arguments = []; + + foreach ($this->attributes as $attribute) { + if ($attribute instanceof ReflectionAttribute) { + if(is_a($attribute->getName(), BodyParam::class, true)) { + $arguments[] = $attribute->getArguments(); + } + } + } + + return $arguments; } } From 6d52fb78ed1b8d27cec4050ebe6a404e498904ef Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 17:06:58 +0300 Subject: [PATCH 11/24] #4 create class transform --- .../BodyParam/AtrTBodyParamTransform.php | 29 +++++++++++++++++++ .../BodyParam/BodyParamTransform.php | 13 +++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/Transforms/BodyParam/AtrTBodyParamTransform.php create mode 100644 src/Transforms/BodyParam/BodyParamTransform.php diff --git a/src/Transforms/BodyParam/AtrTBodyParamTransform.php b/src/Transforms/BodyParam/AtrTBodyParamTransform.php new file mode 100644 index 0000000..c9b794c --- /dev/null +++ b/src/Transforms/BodyParam/AtrTBodyParamTransform.php @@ -0,0 +1,29 @@ +> $attributeArguments */ + public function __construct( + public array $attributeArguments, + ) {} + + /** @return array> */ + public function transform(): array + { + $argumentsDoc = []; + + foreach ($this->attributeArguments as $arguments) { + $bodyParam = new BodyParam(...$arguments); + + $argumentsDoc[$bodyParam->name] = $bodyParam->toArray(); + } + + return $argumentsDoc; + } +} diff --git a/src/Transforms/BodyParam/BodyParamTransform.php b/src/Transforms/BodyParam/BodyParamTransform.php new file mode 100644 index 0000000..39fbdc7 --- /dev/null +++ b/src/Transforms/BodyParam/BodyParamTransform.php @@ -0,0 +1,13 @@ +> + */ + public function transform(): array; +} From 2070b70d8ab6c3e9efc8a87689c41c28639948b4 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 17:07:08 +0300 Subject: [PATCH 12/24] #4 update logic generate doc --- src/Documentations/BodyParamDoc.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Documentations/BodyParamDoc.php b/src/Documentations/BodyParamDoc.php index d545cb2..357636b 100644 --- a/src/Documentations/BodyParamDoc.php +++ b/src/Documentations/BodyParamDoc.php @@ -5,13 +5,14 @@ namespace DenisKorbakov\LaravelDataScribe\Documentations; use DenisKorbakov\LaravelDataScribe\Params\BodyParams; +use DenisKorbakov\LaravelDataScribe\Transforms\BodyParam\AtrTBodyParamTransform; use Knuckles\Scribe\Tools\DocumentationConfig; final readonly class BodyParamDoc implements Doc { public function __construct( public string $laravelDataClass, - public array $bodyParamAttribute, + public array $attributeArguments, public DocumentationConfig $config, ) {} @@ -20,7 +21,9 @@ public function generate(): ?array if (empty($this->laravelDataClass)) { return null; } + $attributesDoc = (new AtrTBodyParamTransform($this->attributeArguments))->transform(); + $bodyParamsDoc = (new BodyParams($this->laravelDataClass, $this->config))->generate(); - return (new BodyParams($this->laravelDataClass, $this->config))->generate(); + return array_merge($attributesDoc, $bodyParamsDoc); } } From bb3c5b858a73bfbc0f41671d4fb2915307c659a2 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 17:07:39 +0300 Subject: [PATCH 13/24] #4 rename variable --- src/LaravelDataBodyParam.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LaravelDataBodyParam.php b/src/LaravelDataBodyParam.php index 898e47d..5fe9ffd 100755 --- a/src/LaravelDataBodyParam.php +++ b/src/LaravelDataBodyParam.php @@ -30,9 +30,9 @@ public function __invoke(ExtractedEndpointData $endpointData, array $settings = /** @var class-string $laravelDataClass */ $laravelDataClass = (new LaravelDataClassExtract($parameters))->extract(); - /** @var array $bodyParamAttribute */ - $bodyParamAttribute = (new BodyParamAttributeExtract($attributes))->extract(); + /** @var array> $bodyParamAttribute */ + $attributeArguments = (new BodyParamAttributeExtract($attributes))->extract(); - return (new BodyParamDoc($laravelDataClass, $bodyParamAttribute, $this->config))->generate(); + return (new BodyParamDoc($laravelDataClass, $attributeArguments, $this->config))->generate(); } } From 9f343bfbe7be306320053c4e6988b19fb7a13f22 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 18:28:31 +0300 Subject: [PATCH 14/24] #4 fixed logic at empty args --- ...ParamTransform.php => AtrToBodyParamTransform.php} | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) rename src/Transforms/BodyParam/{AtrTBodyParamTransform.php => AtrToBodyParamTransform.php} (63%) diff --git a/src/Transforms/BodyParam/AtrTBodyParamTransform.php b/src/Transforms/BodyParam/AtrToBodyParamTransform.php similarity index 63% rename from src/Transforms/BodyParam/AtrTBodyParamTransform.php rename to src/Transforms/BodyParam/AtrToBodyParamTransform.php index c9b794c..671482f 100644 --- a/src/Transforms/BodyParam/AtrTBodyParamTransform.php +++ b/src/Transforms/BodyParam/AtrToBodyParamTransform.php @@ -5,8 +5,9 @@ namespace DenisKorbakov\LaravelDataScribe\Transforms\BodyParam; use Knuckles\Scribe\Attributes\BodyParam; +use TypeError; -final readonly class AtrTBodyParamTransform implements BodyParamTransform +final readonly class AtrToBodyParamTransform implements BodyParamTransform { /** @param array> $attributeArguments */ public function __construct( @@ -19,9 +20,13 @@ public function transform(): array $argumentsDoc = []; foreach ($this->attributeArguments as $arguments) { - $bodyParam = new BodyParam(...$arguments); + try { + $bodyParam = new BodyParam(...$arguments); - $argumentsDoc[$bodyParam->name] = $bodyParam->toArray(); + $argumentsDoc[$bodyParam->name] = $bodyParam->toArray(); + } catch (TypeError) { + continue; + } } return $argumentsDoc; From 0aee404bff139dfde298f8f0ad84c8c9f64aa503 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 18:28:53 +0300 Subject: [PATCH 15/24] #4 rename used class --- src/Documentations/BodyParamDoc.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Documentations/BodyParamDoc.php b/src/Documentations/BodyParamDoc.php index 357636b..77659f5 100644 --- a/src/Documentations/BodyParamDoc.php +++ b/src/Documentations/BodyParamDoc.php @@ -5,7 +5,7 @@ namespace DenisKorbakov\LaravelDataScribe\Documentations; use DenisKorbakov\LaravelDataScribe\Params\BodyParams; -use DenisKorbakov\LaravelDataScribe\Transforms\BodyParam\AtrTBodyParamTransform; +use DenisKorbakov\LaravelDataScribe\Transforms\BodyParam\AtrToBodyParamTransform; use Knuckles\Scribe\Tools\DocumentationConfig; final readonly class BodyParamDoc implements Doc @@ -21,9 +21,10 @@ public function generate(): ?array if (empty($this->laravelDataClass)) { return null; } - $attributesDoc = (new AtrTBodyParamTransform($this->attributeArguments))->transform(); + + $attributesDoc = (new AtrToBodyParamTransform($this->attributeArguments))->transform(); $bodyParamsDoc = (new BodyParams($this->laravelDataClass, $this->config))->generate(); - return array_merge($attributesDoc, $bodyParamsDoc); + return array_merge($bodyParamsDoc, $attributesDoc); } } From 7dde1c5a482dc10ddaad81f9bdd4351ee255d558 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 18:29:08 +0300 Subject: [PATCH 16/24] #4 create new tests --- .../BodyParamDoc/GenerateTest.php | 262 ++++++++++++++++++ .../BodyParamAttributeExtract/ExtractTest.php | 58 ++++ .../AtrToBodyParamTransform/TransformTest.php | 90 ++++++ 3 files changed, 410 insertions(+) create mode 100644 tests/Unit/Documentations/BodyParamDoc/GenerateTest.php create mode 100644 tests/Unit/Extractors/BodyParamAttributeExtract/ExtractTest.php create mode 100644 tests/Unit/Transforms/AtrToBodyParamTransform/TransformTest.php diff --git a/tests/Unit/Documentations/BodyParamDoc/GenerateTest.php b/tests/Unit/Documentations/BodyParamDoc/GenerateTest.php new file mode 100644 index 0000000..2524ace --- /dev/null +++ b/tests/Unit/Documentations/BodyParamDoc/GenerateTest.php @@ -0,0 +1,262 @@ +method->getParameters()))->extract(), + (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(), + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toEqual($this->getParamsAttributeRules()); +}); + +test('generate doc body params from method with customAttributeRules', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'customAttributeRules']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $doc = new BodyParamDoc( + (new LaravelDataClassExtract($extractMethod->method->getParameters()))->extract(), + (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(), + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toEqual($this->getParamsCustomAttributeRules()); +}); + +test('generate doc body params from method with manualRules', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'manualRules']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $doc = new BodyParamDoc( + (new LaravelDataClassExtract($extractMethod->method->getParameters()))->extract(), + (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(), + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toEqual($this->getParamsManualRules()); +}); + +test('generate doc body params from method with noRules', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'noRules']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $doc = new BodyParamDoc( + (new LaravelDataClassExtract($extractMethod->method->getParameters()))->extract(), + (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(), + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toEqual($this->getParamsNoRules()); +}); + +test('generate doc body params from method with withoutLaravelData', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'withoutLaravelData']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $doc = new BodyParamDoc( + (new LaravelDataClassExtract($extractMethod->method->getParameters()))->extract(), + (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(), + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toBeEmpty(); +}); + +test('generate doc body params from method with emptyLaravelData', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'emptyLaravelData']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $doc = new BodyParamDoc( + (new LaravelDataClassExtract($extractMethod->method->getParameters()))->extract(), + (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(), + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toBeEmpty(); +}); + +test('generate doc body params from method with empty emptyMethod', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'emptyMethod']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $doc = new BodyParamDoc( + (new LaravelDataClassExtract($extractMethod->method->getParameters()))->extract(), + (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(), + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toBeEmpty(); +}); + +test('generate doc body params from method with more moreParameters', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'moreParameters']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $doc = new BodyParamDoc( + (new LaravelDataClassExtract($extractMethod->method->getParameters()))->extract(), + (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(), + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toBeEmpty(); +}); + +test('generate doc body params from method with requestRules', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'requestRules']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $doc = new BodyParamDoc( + (new LaravelDataClassExtract($extractMethod->method->getParameters()))->extract(), + (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(), + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toBeEmpty(); +}); + +test('generate doc body params from method with requestAndLaravelData', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'requestAndLaravelData']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $doc = new BodyParamDoc( + (new LaravelDataClassExtract($extractMethod->method->getParameters()))->extract(), + (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(), + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toEqual($this->getParamsAttributeRules()); +}); + +test('generate doc body params from method with updateOneBodyParamsFromAttr', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'updateOneBodyParamsFromAttr']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $doc = new BodyParamDoc( + (new LaravelDataClassExtract($extractMethod->method->getParameters()))->extract(), + (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(), + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + expect($result)->toEqual($this->getParamsUpdateOneBodyParamsFromAttr()); +}); + +test('generate doc body params from method with updateAllBodyParamsFromAttr', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'updateAllBodyParamsFromAttr']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $doc = new BodyParamDoc( + (new LaravelDataClassExtract($extractMethod->method->getParameters()))->extract(), + (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(), + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toEqual($this->getParamsUpdateAllBodyParamsFromAttr()); +}); + +test('generate doc body params from method with addBodyParamsFromAttr', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'addBodyParamsFromAttr']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $doc = new BodyParamDoc( + (new LaravelDataClassExtract($extractMethod->method->getParameters()))->extract(), + (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(), + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toEqual($this->getParamsAddBodyParamsFromAttr()); +}); + +test('generate doc body params from empty data', function (): void { + $doc = new BodyParamDoc( + '', + [], + new DocumentationConfig() + ); + + $result = $doc->generate(); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toBeEmpty(); +}); + diff --git a/tests/Unit/Extractors/BodyParamAttributeExtract/ExtractTest.php b/tests/Unit/Extractors/BodyParamAttributeExtract/ExtractTest.php new file mode 100644 index 0000000..72e4485 --- /dev/null +++ b/tests/Unit/Extractors/BodyParamAttributeExtract/ExtractTest.php @@ -0,0 +1,58 @@ +method->getAttributes()); + $result = $attributeArguments->extract(); + + expect($result) + ->toBeArray() + ->toHaveCount(1); +}); + +test('extract body param attribute from updateAllBodyParamsFromAttr', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'updateAllBodyParamsFromAttr']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $attributeArguments = new BodyParamAttributeExtract($extractMethod->method->getAttributes()); + $result = $attributeArguments->extract(); + + expect($result) + ->toBeArray() + ->toHaveCount(2); +}); + +test('extract body param attribute from addBodyParamsFromAttr', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'addBodyParamsFromAttr']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $attributeArguments = new BodyParamAttributeExtract($extractMethod->method->getAttributes()); + $result = $attributeArguments->extract(); + + expect($result) + ->toBeArray() + ->toHaveCount(1); +}); + +test('extract body param attribute from emptyLaravelData', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'emptyLaravelData']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $attributeArguments = new BodyParamAttributeExtract($extractMethod->method->getAttributes()); + $result = $attributeArguments->extract(); + + expect($result) + ->toBeArray() + ->toBeEmpty(); +}); diff --git a/tests/Unit/Transforms/AtrToBodyParamTransform/TransformTest.php b/tests/Unit/Transforms/AtrToBodyParamTransform/TransformTest.php new file mode 100644 index 0000000..f6981c2 --- /dev/null +++ b/tests/Unit/Transforms/AtrToBodyParamTransform/TransformTest.php @@ -0,0 +1,90 @@ +method->getAttributes()))->extract(); + $result = (new AtrToBodyParamTransform($attributeArguments))->transform(); + + expect($result) + ->toBeArray() + ->toHaveCount(1); +}); + +test('transform to body param from updateAllBodyParamsFromAttr', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'updateAllBodyParamsFromAttr']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $attributeArguments = (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(); + $result = (new AtrToBodyParamTransform($attributeArguments))->transform(); + + expect($result) + ->toBeArray() + ->toHaveCount(2); +}); + +test('transform to body param from addBodyParamsFromAttr', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'addBodyParamsFromAttr']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $attributeArguments = (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(); + $result = (new AtrToBodyParamTransform($attributeArguments))->transform(); + + expect($result) + ->toBeArray() + ->toHaveCount(1); +}); + +test('transform to body param from emptyLaravelData', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'emptyLaravelData']); + $extractMethod = ExtractedEndpointData::fromRoute($route); + + $attributeArguments = (new BodyParamAttributeExtract($extractMethod->method->getAttributes()))->extract(); + $result = (new AtrToBodyParamTransform($attributeArguments))->transform(); + + expect($result) + ->toBeArray() + ->toBeEmpty(); +}); + +test('transform to body param from []', function (): void { + $result = (new AtrToBodyParamTransform([]))->transform(); + + expect($result) + ->toBeArray() + ->toBeEmpty(); +}); + +test('transform to body param from other args', function (): void { + $args = [['random', 'args', 123, true]]; + $result = (new AtrToBodyParamTransform($args))->transform(); + + expect($result) + ->toBeArray() + ->toBeEmpty(); +}); + +test('transform to body param from more arg', function (): void { + $args = [ + ['name', 'int', 'updated name', false, 1, ['one', 'two'], true], + ['random', 'args', 123, true], + ['name 2', 'string', 'updated name 2', true, 'test', ExampleEnum::class, false], + ]; + $result = (new AtrToBodyParamTransform($args))->transform(); + + expect($result) + ->toBeArray() + ->toHaveCount(2); +}); From 03bc9a58980364a56aa4169a607d898e38c7c180 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 18:29:19 +0300 Subject: [PATCH 17/24] #4 add new test cases --- tests/Unit/LaravelDataBodyParamTest.php | 26 ++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/tests/Unit/LaravelDataBodyParamTest.php b/tests/Unit/LaravelDataBodyParamTest.php index 76b863d..486d683 100644 --- a/tests/Unit/LaravelDataBodyParamTest.php +++ b/tests/Unit/LaravelDataBodyParamTest.php @@ -139,5 +139,29 @@ $this->deleteExampleKey($result); } - expect($result)->toEqual($this->getParamsAttributeRules()); + expect($result)->toEqual($this->getParamsUpdateOneBodyParamsFromAttr()); +}); + +test('generate doc body params from method with updateAllBodyParamsFromAttr', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'updateAllBodyParamsFromAttr']); + $laravelDataBodyParam = new LaravelDataBodyParam(new DocumentationConfig()); + + $result = $laravelDataBodyParam(ExtractedEndpointData::fromRoute($route)); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toEqual($this->getParamsUpdateAllBodyParamsFromAttr()); +}); + +test('generate doc body params from method with addBodyParamsFromAttr', function (): void { + $route = new Route('', '', [LaravelDataController::class, 'addBodyParamsFromAttr']); + $laravelDataBodyParam = new LaravelDataBodyParam(new DocumentationConfig()); + + $result = $laravelDataBodyParam(ExtractedEndpointData::fromRoute($route)); + if (is_array($result)) { + $this->deleteExampleKey($result); + } + + expect($result)->toEqual($this->getParamsAddBodyParamsFromAttr()); }); From 7d5915c9feb449e543957d19a00b3cd5382a05a6 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 18:29:31 +0300 Subject: [PATCH 18/24] #4 update args in body params --- tests/Fixtures/Controllers/LaravelDataController.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/Fixtures/Controllers/LaravelDataController.php b/tests/Fixtures/Controllers/LaravelDataController.php index 0c1bbdd..f80e0c5 100644 --- a/tests/Fixtures/Controllers/LaravelDataController.php +++ b/tests/Fixtures/Controllers/LaravelDataController.php @@ -5,6 +5,7 @@ namespace Tests\Fixtures\Controllers; use Knuckles\Scribe\Attributes\BodyParam; +use Tests\Fixtures\Enums\ExampleEnum; use Tests\Fixtures\LaravelData\AttributeRules; use Tests\Fixtures\LaravelData\CustomAttributeRules; use Tests\Fixtures\LaravelData\ManualRules; @@ -59,7 +60,7 @@ public function requestAndEmptyLaravelData(RequestRules $requestRules, ParentCla { } - #[BodyParam('name', 'int', 'updated name', required: false, example: 1)] + #[BodyParam('name', 'int', 'updated name', false, 1, ['one', 'two'], true)] public function updateOneBodyParamsFromAttr(AttributeRules $attributeRules): void { } @@ -70,7 +71,7 @@ public function updateAllBodyParamsFromAttr(CustomAttributeRules $customAttribut { } - #[BodyParam('new', 'string', 'add new params', required: false, example: 'param')] + #[BodyParam('new', 'string', 'add new params', required: false, example: 'param', enum: ExampleEnum::class)] public function addBodyParamsFromAttr(ManualRules $manualRules): void { } From 420169d7a9668223b8608b63026015c91e029eba Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 18:29:43 +0300 Subject: [PATCH 19/24] #4 create new fixtures --- .../ParamsAddBodyParamsFromAttr.php | 59 ++++++++++ .../ParamsUpdateAllBodyParamsFromAttr.php | 22 ++++ .../ParamsUpdateOneBodyParamsFromAttr.php | 106 ++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 tests/Fixtures/BodyParams/ParamsAddBodyParamsFromAttr.php create mode 100644 tests/Fixtures/BodyParams/ParamsUpdateAllBodyParamsFromAttr.php create mode 100644 tests/Fixtures/BodyParams/ParamsUpdateOneBodyParamsFromAttr.php diff --git a/tests/Fixtures/BodyParams/ParamsAddBodyParamsFromAttr.php b/tests/Fixtures/BodyParams/ParamsAddBodyParamsFromAttr.php new file mode 100644 index 0000000..5d3413c --- /dev/null +++ b/tests/Fixtures/BodyParams/ParamsAddBodyParamsFromAttr.php @@ -0,0 +1,59 @@ + [ + 'name' => 'name', + 'required' => true, + 'type' => 'string', + 'description' => 'Must not be greater than 100 characters.', + 'nullable' => false, + ], + 'description' => [ + 'name' => 'description', + 'required' => true, + 'type' => 'string', + 'description' => 'Must not be greater than 500 characters.', + 'nullable' => false, + ], + 'price' => [ + 'name' => 'price', + 'required' => true, + 'type' => 'number', + 'description' => 'Must be at least 0. Must not be greater than 9999.99.', + 'nullable' => false, + ], + 'items' => [ + 'name' => 'items', + 'required' => true, + 'type' => 'object[]', + 'description' => 'Must have at least 1 items.', + 'nullable' => false, + ], + 'items[].product_id' => [ + 'name' => 'items[].product_id', + 'required' => true, + 'type' => 'integer', + 'description' => 'The id of an existing record in the products table.', + 'nullable' => false, + ], + 'items[].quantity' => [ + 'name' => 'items[].quantity', + 'required' => true, + 'type' => 'integer', + 'description' => 'Must be at least 1. Must not be greater than 10.', + 'nullable' => false, + ], + 'new' => [ + 'name' => 'new', + 'description' => 'add new params', + 'type' => 'string', + 'required' => false, + 'enumValues' => [ + 'Example One', + 'Example Two', + ], + 'nullable' => false, + ], +]; diff --git a/tests/Fixtures/BodyParams/ParamsUpdateAllBodyParamsFromAttr.php b/tests/Fixtures/BodyParams/ParamsUpdateAllBodyParamsFromAttr.php new file mode 100644 index 0000000..6b00b03 --- /dev/null +++ b/tests/Fixtures/BodyParams/ParamsUpdateAllBodyParamsFromAttr.php @@ -0,0 +1,22 @@ + [ + 'name' => 'phone', + 'description' => 'updated phone', + 'type' => 'bool', + 'required' => true, + 'enumValues' => [], + 'nullable' => false, + ], + 'password' => [ + 'name' => 'password', + 'description' => 'updated password', + 'type' => 'string', + 'required' => true, + 'enumValues' => [], + 'nullable' => false, + ], +]; diff --git a/tests/Fixtures/BodyParams/ParamsUpdateOneBodyParamsFromAttr.php b/tests/Fixtures/BodyParams/ParamsUpdateOneBodyParamsFromAttr.php new file mode 100644 index 0000000..a2b1950 --- /dev/null +++ b/tests/Fixtures/BodyParams/ParamsUpdateOneBodyParamsFromAttr.php @@ -0,0 +1,106 @@ + [ + 'name' => 'name', + 'description' => 'updated name', + 'type' => 'int', + 'required' => false, + 'enumValues' => ['one', 'two'], + 'nullable' => true, + ], + 'email' => [ + 'name' => 'email', + 'required' => true, + 'type' => 'string', + 'description' => 'Must be a valid email address.', + 'nullable' => false, + ], + 'price' => [ + 'name' => 'price', + 'required' => true, + 'type' => 'number', + 'description' => 'Must be between 0 and 100.', + 'nullable' => false, + ], + 'age' => [ + 'name' => 'age', + 'required' => true, + 'type' => 'integer', + 'description' => 'Must be at least 18.', + 'nullable' => false, + ], + 'code' => [ + 'name' => 'code', + 'required' => true, + 'type' => 'string', + 'description' => 'Must be 10 characters.', + 'nullable' => false, + ], + 'active' => [ + 'name' => 'active', + 'required' => false, + 'type' => 'boolean', + 'description' => '', + 'nullable' => false, + ], + 'items' => [ + 'name' => 'items', + 'required' => true, + 'type' => 'object', + 'description' => '', + 'nullable' => false, + ], + 'start_date' => [ + 'name' => 'start_date', + 'required' => true, + 'type' => 'string', + 'description' => 'Must be a valid date. Must be a date after today.', + 'nullable' => false, + ], + 'end_date' => [ + 'name' => 'end_date', + 'required' => true, + 'type' => 'string', + 'description' => 'Must be a valid date. Must be a date before start_date.', + 'nullable' => false, + ], + 'status' => [ + 'name' => 'status', + 'required' => true, + 'type' => 'string', + 'description' => '', + 'nullable' => false, + 'enumValues' => ['active', 'inactive', 'pending'], + ], + 'account_type' => [ + 'name' => 'account_type', + 'required' => true, + 'type' => 'string', + 'description' => 'Must not be one of banned or suspended.', + 'nullable' => false, + ], + 'proper_name' => [ + 'name' => 'proper_name', + 'required' => false, + 'type' => 'string', + 'description' => 'Must match the regex /^[A-Z][a-z]+$/.', + 'nullable' => true, + ], + 'website' => [ + 'name' => 'website', + 'required' => true, + 'type' => 'string', + 'description' => 'Must be a valid URL.', + 'nullable' => false, + ], + 'identifier' => [ + 'name' => 'identifier', + 'required' => true, + 'type' => 'string', + 'description' => 'Must be a valid UUID.', + 'nullable' => false, + ], +]; From a4956a9975c8b65f08d869fd3ff99213d8bc899b Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 18:30:01 +0300 Subject: [PATCH 20/24] #4 add new method for get arr with doc --- tests/TestCase.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/TestCase.php b/tests/TestCase.php index e888a24..dd7e30e 100755 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -20,6 +20,21 @@ protected function deleteExampleKey(array &$array): void data_forget($array, '*.example'); } + protected function getParamsAddBodyParamsFromAttr(): array + { + return include __DIR__ . '/Fixtures/BodyParams/ParamsAddBodyParamsFromAttr.php'; + } + + protected function getParamsUpdateAllBodyParamsFromAttr(): array + { + return include __DIR__ . '/Fixtures/BodyParams/ParamsUpdateAllBodyParamsFromAttr.php'; + } + + protected function getParamsUpdateOneBodyParamsFromAttr(): array + { + return include __DIR__ . '/Fixtures/BodyParams/ParamsUpdateOneBodyParamsFromAttr.php'; + } + protected function getParamsAttributeRules(): array { return include __DIR__ . '/Fixtures/BodyParams/ParamsAttributeRules.php'; From f177714ad0c110274eacfbbd8578b610bb1fb310 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 19:01:46 +0300 Subject: [PATCH 21/24] #4 fix phpstan --- src/Documentations/BodyParamDoc.php | 7 +++++++ src/Documentations/Doc.php | 1 + .../Attributes/BodyParamAttributeExtract.php | 12 ++++++------ src/LaravelDataBodyParam.php | 5 +++-- src/Transforms/BodyParam/AtrToBodyParamTransform.php | 6 +++++- 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/Documentations/BodyParamDoc.php b/src/Documentations/BodyParamDoc.php index 77659f5..5beb5a0 100644 --- a/src/Documentations/BodyParamDoc.php +++ b/src/Documentations/BodyParamDoc.php @@ -7,15 +7,22 @@ use DenisKorbakov\LaravelDataScribe\Params\BodyParams; use DenisKorbakov\LaravelDataScribe\Transforms\BodyParam\AtrToBodyParamTransform; use Knuckles\Scribe\Tools\DocumentationConfig; +use Spatie\LaravelData\Data; final readonly class BodyParamDoc implements Doc { + + /** + * @param class-string $laravelDataClass + * @param array> $attributeArguments + */ public function __construct( public string $laravelDataClass, public array $attributeArguments, public DocumentationConfig $config, ) {} + /** @return ?array> */ public function generate(): ?array { if (empty($this->laravelDataClass)) { diff --git a/src/Documentations/Doc.php b/src/Documentations/Doc.php index b5768b4..5555b59 100644 --- a/src/Documentations/Doc.php +++ b/src/Documentations/Doc.php @@ -6,5 +6,6 @@ interface Doc { + /** @return ?array> */ public function generate(): ?array; } diff --git a/src/Extractors/Attributes/BodyParamAttributeExtract.php b/src/Extractors/Attributes/BodyParamAttributeExtract.php index f43a0f2..790bc21 100644 --- a/src/Extractors/Attributes/BodyParamAttributeExtract.php +++ b/src/Extractors/Attributes/BodyParamAttributeExtract.php @@ -10,23 +10,23 @@ /** Extracts Body Param attribute from method attributes */ final readonly class BodyParamAttributeExtract implements AttributeExtract { - /** @param ReflectionAttribute[] $attributes Method to analyze */ + /** @param ReflectionAttribute[] $attributes Method to analyze */ public function __construct( public array $attributes, ) { } - /** @return array> Get array arguments or empty array */ + /** @return list Get array arguments or empty array */ public function extract(): array { $arguments = []; foreach ($this->attributes as $attribute) { - if ($attribute instanceof ReflectionAttribute) { - if(is_a($attribute->getName(), BodyParam::class, true)) { - $arguments[] = $attribute->getArguments(); - } + if(!is_a($attribute->getName(), BodyParam::class, true)) { + continue; } + + $arguments[] = $attribute->getArguments(); } return $arguments; diff --git a/src/LaravelDataBodyParam.php b/src/LaravelDataBodyParam.php index 5fe9ffd..2af7b95 100755 --- a/src/LaravelDataBodyParam.php +++ b/src/LaravelDataBodyParam.php @@ -8,6 +8,7 @@ use DenisKorbakov\LaravelDataScribe\Extractors\Attributes\BodyParamAttributeExtract; use DenisKorbakov\LaravelDataScribe\Extractors\Classes\LaravelDataClassExtract; use Knuckles\Camel\Extraction\ExtractedEndpointData; +use Knuckles\Scribe\Attributes\BodyParam; use Knuckles\Scribe\Extracting\Strategies\Strategy; use ReflectionAttribute; use ReflectionParameter; @@ -25,12 +26,12 @@ public function __invoke(ExtractedEndpointData $endpointData, array $settings = { /** @var ReflectionParameter[] $parameters */ $parameters = $endpointData->method?->getParameters(); - /** @var ReflectionAttribute[] $attributes */ + /** @var ReflectionAttribute[] $attributes */ $attributes = $endpointData->method?->getAttributes(); /** @var class-string $laravelDataClass */ $laravelDataClass = (new LaravelDataClassExtract($parameters))->extract(); - /** @var array> $bodyParamAttribute */ + /** @var array> $attributeArguments */ $attributeArguments = (new BodyParamAttributeExtract($attributes))->extract(); return (new BodyParamDoc($laravelDataClass, $attributeArguments, $this->config))->generate(); diff --git a/src/Transforms/BodyParam/AtrToBodyParamTransform.php b/src/Transforms/BodyParam/AtrToBodyParamTransform.php index 671482f..6a48ad0 100644 --- a/src/Transforms/BodyParam/AtrToBodyParamTransform.php +++ b/src/Transforms/BodyParam/AtrToBodyParamTransform.php @@ -21,9 +21,13 @@ public function transform(): array foreach ($this->attributeArguments as $arguments) { try { + /** @phpstan-ignore-next-line */ $bodyParam = new BodyParam(...$arguments); - $argumentsDoc[$bodyParam->name] = $bodyParam->toArray(); + /** @var array $dataDoc */ + $dataDoc = $bodyParam->toArray(); + + $argumentsDoc[$bodyParam->name] = $dataDoc; } catch (TypeError) { continue; } From dd210170b3ec031d79ca0e598852a8d8282a8bc9 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 19:03:54 +0300 Subject: [PATCH 22/24] #4 cs fix --- src/Documentations/BodyParamDoc.php | 4 ++-- src/Extractors/Attributes/BodyParamAttributeExtract.php | 2 +- src/LaravelDataBodyParam.php | 1 - src/Transforms/BodyParam/AtrToBodyParamTransform.php | 3 ++- tests/Unit/Documentations/BodyParamDoc/GenerateTest.php | 1 - 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Documentations/BodyParamDoc.php b/src/Documentations/BodyParamDoc.php index 5beb5a0..dadca8d 100644 --- a/src/Documentations/BodyParamDoc.php +++ b/src/Documentations/BodyParamDoc.php @@ -11,7 +11,6 @@ final readonly class BodyParamDoc implements Doc { - /** * @param class-string $laravelDataClass * @param array> $attributeArguments @@ -20,7 +19,8 @@ public function __construct( public string $laravelDataClass, public array $attributeArguments, public DocumentationConfig $config, - ) {} + ) { + } /** @return ?array> */ public function generate(): ?array diff --git a/src/Extractors/Attributes/BodyParamAttributeExtract.php b/src/Extractors/Attributes/BodyParamAttributeExtract.php index 790bc21..d7185b3 100644 --- a/src/Extractors/Attributes/BodyParamAttributeExtract.php +++ b/src/Extractors/Attributes/BodyParamAttributeExtract.php @@ -22,7 +22,7 @@ public function extract(): array $arguments = []; foreach ($this->attributes as $attribute) { - if(!is_a($attribute->getName(), BodyParam::class, true)) { + if (!is_a($attribute->getName(), BodyParam::class, true)) { continue; } diff --git a/src/LaravelDataBodyParam.php b/src/LaravelDataBodyParam.php index 2af7b95..86995c4 100755 --- a/src/LaravelDataBodyParam.php +++ b/src/LaravelDataBodyParam.php @@ -8,7 +8,6 @@ use DenisKorbakov\LaravelDataScribe\Extractors\Attributes\BodyParamAttributeExtract; use DenisKorbakov\LaravelDataScribe\Extractors\Classes\LaravelDataClassExtract; use Knuckles\Camel\Extraction\ExtractedEndpointData; -use Knuckles\Scribe\Attributes\BodyParam; use Knuckles\Scribe\Extracting\Strategies\Strategy; use ReflectionAttribute; use ReflectionParameter; diff --git a/src/Transforms/BodyParam/AtrToBodyParamTransform.php b/src/Transforms/BodyParam/AtrToBodyParamTransform.php index 6a48ad0..34bf2bf 100644 --- a/src/Transforms/BodyParam/AtrToBodyParamTransform.php +++ b/src/Transforms/BodyParam/AtrToBodyParamTransform.php @@ -12,7 +12,8 @@ /** @param array> $attributeArguments */ public function __construct( public array $attributeArguments, - ) {} + ) { + } /** @return array> */ public function transform(): array diff --git a/tests/Unit/Documentations/BodyParamDoc/GenerateTest.php b/tests/Unit/Documentations/BodyParamDoc/GenerateTest.php index 2524ace..7b2e4e3 100644 --- a/tests/Unit/Documentations/BodyParamDoc/GenerateTest.php +++ b/tests/Unit/Documentations/BodyParamDoc/GenerateTest.php @@ -259,4 +259,3 @@ expect($result)->toBeEmpty(); }); - From d3e0cc5ab8605a95e6dcc5d065f377696e98865c Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 19:04:02 +0300 Subject: [PATCH 23/24] #4 update rules rector --- rector.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rector.php b/rector.php index 786aa8e..c76e210 100755 --- a/rector.php +++ b/rector.php @@ -23,6 +23,7 @@ use Rector\Privatization\Rector\ClassMethod\PrivatizeFinalClassMethodRector; use Rector\Privatization\Rector\Property\PrivatizeFinalClassPropertyRector; use Rector\Set\ValueObject\SetList; +use Rector\Strict\Rector\Empty_\DisallowedEmptyRuleFixerRector; use Rector\TypeDeclaration\Rector\ClassMethod\AddVoidReturnTypeWhereNoReturnRector; use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromReturnDirectArrayRector; use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNewArrayRector; @@ -64,6 +65,7 @@ ]); $rectorConfig->skip([ + DisallowedEmptyRuleFixerRector::class, CompactToVariablesRector::class, RemoveEmptyClassMethodRector::class, RemoveNonExistingVarAnnotationRector::class, From 151fea130fbee65409e2300cee7bb6631da290ab Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 21 Aug 2025 19:12:31 +0300 Subject: [PATCH 24/24] #4 update actions --- .github/workflows/lint.yml | 6 +++++- .github/workflows/tests.yml | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index af876c8..8f09c87 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,6 +1,10 @@ name: LINT -on: ['push'] +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] jobs: coding-standard: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 385b9f7..208b8f8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,6 +1,10 @@ name: TESTS -on: ['push'] +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] jobs: test: