Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -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
6 changes: 5 additions & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: LINT

on: ['push']
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
coding-standard:
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: TESTS

on: ['push']
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
test:
Expand Down
2 changes: 2 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -64,6 +65,7 @@
]);

$rectorConfig->skip([
DisallowedEmptyRuleFixerRector::class,
CompactToVariablesRector::class,
RemoveEmptyClassMethodRector::class,
RemoveNonExistingVarAnnotationRector::class,
Expand Down
37 changes: 37 additions & 0 deletions src/Documentations/BodyParamDoc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace DenisKorbakov\LaravelDataScribe\Documentations;

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<Data> $laravelDataClass
* @param array<int, array<string, mixed>> $attributeArguments
*/
public function __construct(
public string $laravelDataClass,
public array $attributeArguments,
public DocumentationConfig $config,
) {
}

/** @return ?array<string, array<string, mixed>> */
public function generate(): ?array
{
if (empty($this->laravelDataClass)) {
return null;
}

$attributesDoc = (new AtrToBodyParamTransform($this->attributeArguments))->transform();
$bodyParamsDoc = (new BodyParams($this->laravelDataClass, $this->config))->generate();

return array_merge($bodyParamsDoc, $attributesDoc);
}
}
11 changes: 11 additions & 0 deletions src/Documentations/Doc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace DenisKorbakov\LaravelDataScribe\Documentations;

interface Doc
{
/** @return ?array<string, array<string, mixed>> */
public function generate(): ?array;
}
11 changes: 11 additions & 0 deletions src/Extractors/Attributes/AttributeExtract.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace DenisKorbakov\LaravelDataScribe\Extractors\Attributes;

interface AttributeExtract
{
/** @return array<int, array<string, mixed>> */
public function extract(): array;
}
34 changes: 34 additions & 0 deletions src/Extractors/Attributes/BodyParamAttributeExtract.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace DenisKorbakov\LaravelDataScribe\Extractors\Attributes;

use Knuckles\Scribe\Attributes\BodyParam;
use ReflectionAttribute;

/** Extracts Body Param attribute from method attributes */
final readonly class BodyParamAttributeExtract implements AttributeExtract
{
/** @param ReflectionAttribute<object>[] $attributes Method to analyze */
public function __construct(
public array $attributes,
) {
}

/** @return list<array> Get array arguments or empty array */
public function extract(): array
{
$arguments = [];

foreach ($this->attributes as $attribute) {
if (!is_a($attribute->getName(), BodyParam::class, true)) {
continue;
}

$arguments[] = $attribute->getArguments();
}

return $arguments;
}
}
10 changes: 10 additions & 0 deletions src/Extractors/Classes/ClassExtract.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace DenisKorbakov\LaravelDataScribe\Extractors\Classes;

interface ClassExtract
{
public function extract(): string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

declare(strict_types=1);

namespace DenisKorbakov\LaravelDataScribe\Extractors;
namespace DenisKorbakov\LaravelDataScribe\Extractors\Classes;

use DenisKorbakov\LaravelDataScribe\Resolvers\ParentClassResolver;
use ReflectionNamedType;
use ReflectionParameter;
use Spatie\LaravelData\Data;

/** Extracts Laravel Data class from method parameters */
final readonly class ParametersExtractor
final readonly class LaravelDataClassExtract implements ClassExtract
{
/** @param ReflectionParameter[] $parameters Method to analyze */
public function __construct(
Expand Down
18 changes: 10 additions & 8 deletions src/LaravelDataBodyParam.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -23,14 +25,14 @@ public function __invoke(ExtractedEndpointData $endpointData, array $settings =
{
/** @var ReflectionParameter[] $parameters */
$parameters = $endpointData->method?->getParameters();
/** @var ReflectionAttribute<object>[] $attributes */
$attributes = $endpointData->method?->getAttributes();

/** @var class-string<Data> $laravelDataClass */
$laravelDataClass = (new ParametersExtractor($parameters))->extract();
$laravelDataClass = (new LaravelDataClassExtract($parameters))->extract();
/** @var array<int, array<string, mixed>> $attributeArguments */
$attributeArguments = (new BodyParamAttributeExtract($attributes))->extract();

if (empty($laravelDataClass)) {
return null;
}

return (new BodyParams($laravelDataClass, $this->config))->generate();
return (new BodyParamDoc($laravelDataClass, $attributeArguments, $this->config))->generate();
}
}
39 changes: 39 additions & 0 deletions src/Transforms/BodyParam/AtrToBodyParamTransform.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace DenisKorbakov\LaravelDataScribe\Transforms\BodyParam;

use Knuckles\Scribe\Attributes\BodyParam;
use TypeError;

final readonly class AtrToBodyParamTransform implements BodyParamTransform
{
/** @param array<int, array<string, mixed>> $attributeArguments */
public function __construct(
public array $attributeArguments,
) {
}

/** @return array<string, array<string, mixed>> */
public function transform(): array
{
$argumentsDoc = [];

foreach ($this->attributeArguments as $arguments) {
try {
/** @phpstan-ignore-next-line */
$bodyParam = new BodyParam(...$arguments);

/** @var array<string, mixed> $dataDoc */
$dataDoc = $bodyParam->toArray();

$argumentsDoc[$bodyParam->name] = $dataDoc;
} catch (TypeError) {
continue;
}
}

return $argumentsDoc;
}
}
13 changes: 13 additions & 0 deletions src/Transforms/BodyParam/BodyParamTransform.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace DenisKorbakov\LaravelDataScribe\Transforms\BodyParam;

interface BodyParamTransform
{
/**
* @return array<string, array<string, mixed>>
*/
public function transform(): array;
}
59 changes: 59 additions & 0 deletions tests/Fixtures/BodyParams/ParamsAddBodyParamsFromAttr.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

return [
'name' => [
'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 <code>id</code> 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,
],
];
22 changes: 22 additions & 0 deletions tests/Fixtures/BodyParams/ParamsUpdateAllBodyParamsFromAttr.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

return [
'phone' => [
'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,
],
];
Loading