Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add interfaces and custom data #37

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!make

.PHONY: tests

COMPOSE_IMAGE = composer:2
PHP_IMAGE=php:8

composer:
docker pull $(DOCKER_COMPOSE)
docker run --rm --interactive --tty --user $(id -u):$(id -g) -w /app --volume `pwd`:/app $(COMPOSE_IMAGE) composer $(P)

composer_install:
make composer P="install"

phpunit:
docker pull $(PHP_IMAGE)
docker run --rm -it --user $(id -u):$(id -g) -w /app --volume `pwd`:/app $(PHP_IMAGE) ./vendor/bin/phpunit $(P)

# run all php unit tests
tests:
make phpunit P=tests
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "vyuldashev/laravel-openapi",
"name": "ogsoft/laravel-openapi",
"description": "Generate OpenAPI Specification for Laravel Applications",
"keywords": [
"laravel",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function build(): array

Parameter::query()
->name('limit')
->description('How many items to return at one time (max 100)')
->description('How many items to return at one time (max 100) '.$this->data)
->required(false)
->schema(
Schema::integer()->format(Schema::FORMAT_INT32)
Expand Down
23 changes: 23 additions & 0 deletions examples/petstore/OpenApi/RequestBodies/CreatePetRequestBody.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Examples\Petstore\OpenApi\RequestBodies;

use Examples\Petstore\OpenApi\Schemas\PetSchema;
use GoldSpecDigital\ObjectOrientedOAS\Objects\MediaType;
use GoldSpecDigital\ObjectOrientedOAS\Objects\RequestBody;
use Vyuldashev\LaravelOpenApi\Concerns\Referencable;
use Vyuldashev\LaravelOpenApi\Contracts\RequestBodyFactoryInterface;

class CreatePetRequestBody implements RequestBodyFactoryInterface
{
use Referencable;

public function build(): RequestBody
{
return RequestBody::create('UserCreate')
->description($this->data['custom'])
->content(
MediaType::json()->schema(PetSchema::ref())
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ErrorValidationResponse extends ResponseFactory implements Reusable
public function build(): Response
{
$response = Schema::object()->properties(
Schema::string('message')->example('The given data was invalid.'),
Schema::string('message')->example('The given data was invalid. '.$this->data),
Schema::object('errors')
->additionalProperties(
Schema::array()->items(Schema::string())
Expand Down
14 changes: 12 additions & 2 deletions examples/petstore/PetController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Examples\Petstore;

use Examples\Petstore\OpenApi\Parameters\ListPetsParameters;
use Examples\Petstore\OpenApi\RequestBodies\CreatePetRequestBody;
use Examples\Petstore\OpenApi\Responses\ErrorValidationResponse;
use Vyuldashev\LaravelOpenApi\Attributes as OpenApi;

Expand All @@ -13,9 +14,18 @@ class PetController
* List all pets.
*/
#[OpenApi\Operation('listPets')]
#[OpenApi\Parameters(ListPetsParameters::class)]
#[OpenApi\Response(ErrorValidationResponse::class, 422)]
#[OpenApi\Parameters(ListPetsParameters::class, 'Parameters custom data')]
#[OpenApi\Response(ErrorValidationResponse::class, 422, '', 'Response custom data')]
public function index()
{
}

/**
* Create pet.
*/
#[OpenApi\Operation('createPet')]
#[OpenApi\RequestBody(CreatePetRequestBody::class, ['custom' => 'My custom data'])]
public function create()
{
}
}
6 changes: 3 additions & 3 deletions src/Attributes/Callback.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Attribute;
use InvalidArgumentException;
use Vyuldashev\LaravelOpenApi\Factories\CallbackFactory;
use Vyuldashev\LaravelOpenApi\Contracts\CallbackFactoryInterface;

#[Attribute]
class Callback
Expand All @@ -15,8 +15,8 @@ public function __construct(string $factory)
{
$this->factory = class_exists($factory) ? $factory : app()->getNamespace().'OpenApi\\Callbacks\\'.$factory;

if (! is_a($this->factory, CallbackFactory::class, true)) {
throw new InvalidArgumentException('Factory class must be instance of CallbackFactory');
if (! is_a($this->factory, CallbackFactoryInterface::class, true)) {
throw new InvalidArgumentException('Factory class must be instance of CallbackFactoryInterface');
}
}
}
6 changes: 3 additions & 3 deletions src/Attributes/Extension.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Attribute;
use InvalidArgumentException;
use Vyuldashev\LaravelOpenApi\Factories\ExtensionFactory;
use Vyuldashev\LaravelOpenApi\Contracts\ExtensionFactoryInterface;

#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
class Extension
Expand All @@ -18,8 +18,8 @@ public function __construct(string $factory = null, string $key = null, string $
if ($factory) {
$this->factory = class_exists($factory) ? $factory : app()->getNamespace().'OpenApi\\Extensions\\'.$factory;

if (! is_a($this->factory, ExtensionFactory::class, true)) {
throw new InvalidArgumentException('Factory class must be instance of ExtensionFactory');
if (! is_a($this->factory, ExtensionFactoryInterface::class, true)) {
throw new InvalidArgumentException('Factory class must be instance of ExtensionFactoryInterface');
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Attributes/Operation.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ public function __construct(string $id = null, array $tags = [], string $securit
}
}
}
}
}
10 changes: 6 additions & 4 deletions src/Attributes/Parameters.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@

use Attribute;
use InvalidArgumentException;
use Vyuldashev\LaravelOpenApi\Factories\ParametersFactory;
use Vyuldashev\LaravelOpenApi\Contracts\ParametersFactoryInterface;

#[Attribute(Attribute::TARGET_METHOD)]
class Parameters
{
public string $factory;
public $data;

public function __construct(string $factory)
public function __construct(string $factory, $data = null)
{
$this->factory = class_exists($factory) ? $factory : app()->getNamespace().'OpenApi\\Parameters\\'.$factory;
$this->data = $data;

if (! is_a($this->factory, ParametersFactory::class, true)) {
throw new InvalidArgumentException('Factory class must be instance of ParametersFactory');
if (! is_a($this->factory, ParametersFactoryInterface::class, true)) {
throw new InvalidArgumentException('Factory class must be instance of ParametersFactoryInterface');
}
}
}
10 changes: 6 additions & 4 deletions src/Attributes/RequestBody.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@

use Attribute;
use InvalidArgumentException;
use Vyuldashev\LaravelOpenApi\Factories\RequestBodyFactory;
use Vyuldashev\LaravelOpenApi\Contracts\RequestBodyFactoryInterface;

#[Attribute(Attribute::TARGET_METHOD)]
class RequestBody
{
public string $factory;
public $data;

public function __construct(string $factory)
public function __construct(string $factory, $data = null)
{
$this->factory = class_exists($factory) ? $factory : app()->getNamespace().'OpenApi\\RequestBodies\\'.$factory;
$this->data = $data;

if (! is_a($this->factory, RequestBodyFactory::class, true)) {
throw new InvalidArgumentException('Factory class must be instance of RequestBodyFactory');
if (! is_a($this->factory, RequestBodyFactoryInterface::class, true)) {
throw new InvalidArgumentException('Factory class must be instance of RequestBodyFactoryInterface');
}
}
}
11 changes: 7 additions & 4 deletions src/Attributes/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Attribute;
use InvalidArgumentException;
use Vyuldashev\LaravelOpenApi\Factories\ResponseFactory;
use Vyuldashev\LaravelOpenApi\Contracts\ResponseFactoryInterface;

#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
class Response
Expand All @@ -15,12 +15,15 @@ class Response

public ?string $description;

public function __construct(string $factory, int $statusCode = null, string $description = null)
public $data;

public function __construct(string $factory, int $statusCode = null, string $description = null, $data = null)
{
$this->factory = class_exists($factory) ? $factory : app()->getNamespace().'OpenApi\\Responses\\'.$factory;
$this->data = $data;

if (! is_a($this->factory, ResponseFactory::class, true)) {
throw new InvalidArgumentException('Factory class must be instance of ResponseFactory');
if (! is_a($this->factory, ResponseFactoryInterface::class, true)) {
throw new InvalidArgumentException('Factory class must be instance of ResponseFactoryInterface');
}

$this->statusCode = $statusCode;
Expand Down
6 changes: 3 additions & 3 deletions src/Builders/Components/CallbacksBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace Vyuldashev\LaravelOpenApi\Builders\Components;

use Vyuldashev\LaravelOpenApi\Contracts\CallbackFactoryInterface;
use Vyuldashev\LaravelOpenApi\Contracts\Reusable;
use Vyuldashev\LaravelOpenApi\Factories\CallbackFactory;
use Vyuldashev\LaravelOpenApi\Generator;

class CallbacksBuilder extends Builder
Expand All @@ -13,11 +13,11 @@ public function build(string $collection = Generator::COLLECTION_DEFAULT): array
return $this->getAllClasses($collection)
->filter(static function ($class) {
return
is_a($class, CallbackFactory::class, true) &&
is_a($class, CallbackFactoryInterface::class, true) &&
is_a($class, Reusable::class, true);
})
->map(static function ($class) {
/** @var CallbackFactory $instance */
/** @var CallbackFactoryInterface $instance */
$instance = app($class);

return $instance->build();
Expand Down
6 changes: 3 additions & 3 deletions src/Builders/Components/RequestBodiesBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace Vyuldashev\LaravelOpenApi\Builders\Components;

use Vyuldashev\LaravelOpenApi\Contracts\RequestBodyFactoryInterface;
use Vyuldashev\LaravelOpenApi\Contracts\Reusable;
use Vyuldashev\LaravelOpenApi\Factories\RequestBodyFactory;
use Vyuldashev\LaravelOpenApi\Generator;

class RequestBodiesBuilder extends Builder
Expand All @@ -13,11 +13,11 @@ public function build(string $collection = Generator::COLLECTION_DEFAULT): array
return $this->getAllClasses($collection)
->filter(static function ($class) {
return
is_a($class, RequestBodyFactory::class, true) &&
is_a($class, RequestBodyFactoryInterface::class, true) &&
is_a($class, Reusable::class, true);
})
->map(static function ($class) {
/** @var RequestBodyFactory $instance */
/** @var RequestBodyFactoryInterface $instance */
$instance = app($class);

return $instance->build();
Expand Down
6 changes: 3 additions & 3 deletions src/Builders/Components/ResponsesBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace Vyuldashev\LaravelOpenApi\Builders\Components;

use Vyuldashev\LaravelOpenApi\Contracts\ResponseFactoryInterface;
use Vyuldashev\LaravelOpenApi\Contracts\Reusable;
use Vyuldashev\LaravelOpenApi\Factories\ResponseFactory;
use Vyuldashev\LaravelOpenApi\Generator;

class ResponsesBuilder extends Builder
Expand All @@ -13,11 +13,11 @@ public function build(string $collection = Generator::COLLECTION_DEFAULT): array
return $this->getAllClasses($collection)
->filter(static function ($class) {
return
is_a($class, ResponseFactory::class, true) &&
is_a($class, ResponseFactoryInterface::class, true) &&
is_a($class, Reusable::class, true);
})
->map(static function ($class) {
/** @var ResponseFactory $instance */
/** @var ResponseFactoryInterface $instance */
$instance = app($class);

return $instance->build();
Expand Down
6 changes: 3 additions & 3 deletions src/Builders/Components/SchemasBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Vyuldashev\LaravelOpenApi\Builders\Components;

use Vyuldashev\LaravelOpenApi\Contracts\Reusable;
use Vyuldashev\LaravelOpenApi\Factories\SchemaFactory;
use Vyuldashev\LaravelOpenApi\Contracts\SchemaFactoryInterface;
use Vyuldashev\LaravelOpenApi\Generator;

class SchemasBuilder extends Builder
Expand All @@ -13,11 +13,11 @@ public function build(string $collection = Generator::COLLECTION_DEFAULT): array
return $this->getAllClasses($collection)
->filter(static function ($class) {
return
is_a($class, SchemaFactory::class, true) &&
is_a($class, SchemaFactoryInterface::class, true) &&
is_a($class, Reusable::class, true);
})
->map(static function ($class) {
/** @var SchemaFactory $instance */
/** @var SchemaFactoryInterface $instance */
$instance = app($class);

return $instance->build();
Expand Down
6 changes: 3 additions & 3 deletions src/Builders/Components/SecuritySchemesBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Vyuldashev\LaravelOpenApi\Builders\Components;

use Vyuldashev\LaravelOpenApi\Factories\SecuritySchemeFactory;
use Vyuldashev\LaravelOpenApi\Contracts\SecuritySchemeFactoryInterface;
use Vyuldashev\LaravelOpenApi\Generator;

class SecuritySchemesBuilder extends Builder
Expand All @@ -11,10 +11,10 @@ public function build(string $collection = Generator::COLLECTION_DEFAULT): array
{
return $this->getAllClasses($collection)
->filter(static function ($class) {
return is_a($class, SecuritySchemeFactory::class, true);
return is_a($class, SecuritySchemeFactoryInterface::class, true);
})
->map(static function ($class) {
/** @var SecuritySchemeFactory $instance */
/** @var SecuritySchemeFactoryInterface $instance */
$instance = app($class);

return $instance->build();
Expand Down
4 changes: 2 additions & 2 deletions src/Builders/ExtensionsBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use GoldSpecDigital\ObjectOrientedOAS\Objects\BaseObject;
use Illuminate\Support\Collection;
use Vyuldashev\LaravelOpenApi\Attributes\Extension as ExtensionAttribute;
use Vyuldashev\LaravelOpenApi\Factories\ExtensionFactory;
use Vyuldashev\LaravelOpenApi\Contracts\ExtensionFactoryInterface;

class ExtensionsBuilder
{
Expand All @@ -15,7 +15,7 @@ public function build(BaseObject $object, Collection $attributes): void
->filter(static fn (object $attribute) => $attribute instanceof ExtensionAttribute)
->each(static function (ExtensionAttribute $attribute) use ($object): void {
if ($attribute->factory) {
/** @var ExtensionFactory $factory */
/** @var ExtensionFactoryInterface $factory */
$factory = app($attribute->factory);
$key = $factory->key();
$value = $factory->value();
Expand Down
7 changes: 4 additions & 3 deletions src/Builders/Paths/Operation/ParametersBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use phpDocumentor\Reflection\DocBlock\Tags\Param;
use ReflectionParameter;
use Vyuldashev\LaravelOpenApi\Attributes\Parameters;
use Vyuldashev\LaravelOpenApi\Factories\ParametersFactory;
use Vyuldashev\LaravelOpenApi\Contracts\ParametersFactoryInterface;
use Vyuldashev\LaravelOpenApi\RouteInformation;
use Vyuldashev\LaravelOpenApi\SchemaHelpers;

Expand Down Expand Up @@ -60,9 +60,10 @@ protected function buildAttribute(RouteInformation $route): Collection
$parameters = $route->actionAttributes->first(static fn ($attribute) => $attribute instanceof Parameters, []);

if ($parameters) {
/** @var ParametersFactory $parametersFactory */
/** @var ParametersFactoryInterface $parametersFactory */
$parametersFactory = app($parameters->factory);

// little bit magic, add custom data into factory
$parametersFactory->data = $parameters->data;
$parameters = $parametersFactory->build();
}

Expand Down
Loading