From e40e117e1175e45ab4d5d285728cb7bf50a6dad6 Mon Sep 17 00:00:00 2001 From: DerManoMann Date: Tue, 5 Nov 2024 10:30:47 +1300 Subject: [PATCH 1/6] Switch to using `openapi-extras` and remove all custom annotations --- .github/workflows/build.yml | 10 +- .github/workflows/code-style.yml | 6 +- .github/workflows/security-checks.yml | 6 +- README.md | 8 +- composer.json | 16 ++-- docs/AnnotationExtensions.md | 2 +- src/Annotations/Controller.php | 38 -------- src/Annotations/Delete.php | 15 --- src/Annotations/Get.php | 15 --- src/Annotations/Head.php | 15 --- src/Annotations/Middleware.php | 39 -------- src/Annotations/MiddlewareProperty.php | 15 --- src/Annotations/Operation.php | 21 ----- src/Annotations/Options.php | 15 --- src/Annotations/Patch.php | 15 --- src/Annotations/Post.php | 15 --- src/Annotations/Put.php | 15 --- src/Annotations/Trace.php | 15 --- src/Attributes/Controller.php | 45 --------- src/Attributes/Middleware.php | 37 -------- src/OpenApiRouter.php | 59 ++---------- src/Processors/ControllerCleanup.php | 37 -------- src/Processors/MergeController.php | 94 ------------------- src/Processors/VendorPropertyValidation.php | 9 +- .../Controllers/AttributeController.php | 10 +- .../Fixtures/Controllers/InvokeController.php | 4 + .../Controllers/MiddlewareController.php | 3 + .../Controllers/NamedRouteController.php | 4 + .../Controllers/ParametersController.php | 19 ++++ .../Controllers/PrefixedController.php | 5 + tests/Laravel/LaravelTest.php | 4 +- tests/Lumen/LumenTest.php | 1 + tests/Slim4/SlimTest.php | 1 + 33 files changed, 79 insertions(+), 534 deletions(-) delete mode 100644 src/Annotations/Controller.php delete mode 100644 src/Annotations/Delete.php delete mode 100644 src/Annotations/Get.php delete mode 100644 src/Annotations/Head.php delete mode 100644 src/Annotations/Middleware.php delete mode 100644 src/Annotations/MiddlewareProperty.php delete mode 100644 src/Annotations/Operation.php delete mode 100644 src/Annotations/Options.php delete mode 100644 src/Annotations/Patch.php delete mode 100644 src/Annotations/Post.php delete mode 100644 src/Annotations/Put.php delete mode 100644 src/Annotations/Trace.php delete mode 100644 src/Attributes/Controller.php delete mode 100644 src/Attributes/Middleware.php delete mode 100644 src/Processors/ControllerCleanup.php delete mode 100644 src/Processors/MergeController.php diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7087b53..c2f636e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,15 +3,15 @@ name: build on: push: branches: - - master + - main pull_request: branches: - - master + - main jobs: call-laravel: - uses: DerManoMann/openapi-router/.github/workflows/laravel.yml@master + uses: ./.github/workflows/laravel.yml@main call-lumen: - uses: DerManoMann/openapi-router/.github/workflows/lumen.yml@master + uses: ./.github/workflows/lumen.yml@main call-slim: - uses: DerManoMann/openapi-router/.github/workflows/slim.yml@master + uses: ./.github/workflows/slim.yml@main diff --git a/.github/workflows/code-style.yml b/.github/workflows/code-style.yml index 84b8512..d47797b 100644 --- a/.github/workflows/code-style.yml +++ b/.github/workflows/code-style.yml @@ -3,10 +3,10 @@ name: code-style on: push: branches: - - master + - main pull_request: branches: - - master + - main jobs: php-cs: @@ -18,7 +18,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.1' + php-version: '8.3' - uses: ramsey/composer-install@v1 with: diff --git a/.github/workflows/security-checks.yml b/.github/workflows/security-checks.yml index 173d87b..b7811a4 100644 --- a/.github/workflows/security-checks.yml +++ b/.github/workflows/security-checks.yml @@ -3,10 +3,10 @@ name: security-checks on: push: branches: - - master + - main pull_request: branches: - - master + - main jobs: security-checker: @@ -18,7 +18,7 @@ jobs: fail-fast: true matrix: operating-system: [ ubuntu-latest ] - php: [ '8.0', '8.1' ] + php: [ '7.4', '8.0', '8.1', '8.2', '8.3', '8.4' ] dependencies: [ 'highest' ] name: PHP ${{ matrix.php }} on ${{ matrix.operating-system }} with ${{ matrix.dependencies }} dependencies diff --git a/README.md b/README.md index 79f08c3..0c596d5 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ## Introduction -Allows to (re-)use [Swagger-PHP](https://github.com/zircote/swagger-php) annotations to configure routes in the +Allows to (re-)use [Swagger-PHP](https://github.com/zircote/swagger-php) attributes to configure routes in the following frameworks: * [Laravel](https://github.com/laravel/laravel) * [Lumen](https://github.com/laravel/lumen) @@ -13,7 +13,7 @@ following frameworks: ## Requirements -* [PHP 7.2 or higher](http://www.php.net/) - depending on framework version. +* [PHP 7.4 or higher](http://www.php.net/) - depending on framework version. ## Installation @@ -34,7 +34,7 @@ After that all required classes should be availabe in your project to add routin ## Basic usage -Example using the `Slim` framework adapter and standard [OpenApi annotations](https://github.com/zircote/swagger-php/tree/master/src/Annotations) only. +Example using the `Slim` framework adapter and standard [OpenApi annotations](https://github.com/zircote/swagger-php/tree/main/src/Annotations) only. **index.php** ```php @@ -59,6 +59,8 @@ $app->run(); namespace MyApp\Controllers; +use OpenApi\Annotations as OA; + class GetController { diff --git a/composer.json b/composer.json index b447386..c3fc574 100644 --- a/composer.json +++ b/composer.json @@ -35,20 +35,22 @@ }, "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-main": "3.x-dev" } }, "require": { - "php": ">=7.2", - "doctrine/annotations": "^1.13", - "psr/simple-cache": "^1.0 || ^2.0", - "zircote/swagger-php": "^4.2.3" + "php": ">=7.4", + "laravel/laravel": "^9", + "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", + "radebatz/openapi-extras": "^2.1", + "zircote/swagger-php": "^4.11.1" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.17 || ^3.0", + "doctrine/annotations": "^2.0", + "friendsofphp/php-cs-fixer": "^3.0", "nyholm/psr7": "^1.4", "nyholm/psr7-server": "^1.0", - "phpunit/phpunit": ">=8.0", + "phpunit/phpunit": "^9.0", "symfony/cache": "^5.0 || ^6.0", "symfony/psr-http-message-bridge": "^2.1" }, diff --git a/docs/AnnotationExtensions.md b/docs/AnnotationExtensions.md index 652847a..366ecd1 100644 --- a/docs/AnnotationExtensions.md +++ b/docs/AnnotationExtensions.md @@ -1,7 +1,7 @@ # Annotation Extensions ## Default Annotations -By default the router expects only standard [OpenApi annotations](https://github.com/zircote/swagger-php/tree/master/src/Annotations). +By default the router expects only standard [OpenApi annotations](https://github.com/zircote/swagger-php/tree/main/src/Annotations). Theses annotations have only limited build in support for advanced routing features. If you feel like sticking to those the only way to add more options is to use the diff --git a/src/Annotations/Controller.php b/src/Annotations/Controller.php deleted file mode 100644 index 6b6b222..0000000 --- a/src/Annotations/Controller.php +++ /dev/null @@ -1,38 +0,0 @@ - ['responses', 'response'], - Attachable::class => ['attachables'], - ]; -} diff --git a/src/Annotations/Delete.php b/src/Annotations/Delete.php deleted file mode 100644 index 0f6247c..0000000 --- a/src/Annotations/Delete.php +++ /dev/null @@ -1,15 +0,0 @@ -names = $names; - } -} diff --git a/src/Annotations/MiddlewareProperty.php b/src/Annotations/MiddlewareProperty.php deleted file mode 100644 index 162db9c..0000000 --- a/src/Annotations/MiddlewareProperty.php +++ /dev/null @@ -1,15 +0,0 @@ - ['responses', 'response'], - Attachable::class => ['attachables'], - ]; - - /** - * @param array|null $responses - * @param array|null $attachables - */ - public function __construct( - ?string $prefix = null, - ?array $responses = null, - // annotation - ?array $x = null, - ?array $attachables = null - ) { - parent::__construct([ - 'prefix' => $prefix ?? Generator::UNDEFINED, - 'x' => $x ?? Generator::UNDEFINED, - 'value' => $this->combine($responses, $attachables), - ]); - } -} diff --git a/src/Attributes/Middleware.php b/src/Attributes/Middleware.php deleted file mode 100644 index e8508cc..0000000 --- a/src/Attributes/Middleware.php +++ /dev/null @@ -1,37 +0,0 @@ -names = $names; - } -} diff --git a/src/OpenApiRouter.php b/src/OpenApiRouter.php index efd7f5f..85b8b68 100644 --- a/src/OpenApiRouter.php +++ b/src/OpenApiRouter.php @@ -10,16 +10,12 @@ use OpenApi\Annotations\OpenApi; use OpenApi\Annotations\Operation; use OpenApi\Annotations\Parameter; -use OpenApi\Annotations\PathItem; use OpenApi\Context; use OpenApi\Generator; use OpenApi\Processors\BuildPaths; use Psr\SimpleCache\CacheInterface; -use Radebatz\OpenApi\Routing\Annotations as OAX; -use Radebatz\OpenApi\Routing\Annotations\Middleware; -use Radebatz\OpenApi\Routing\Annotations\MiddlewareProperty; -use Radebatz\OpenApi\Routing\Processors\ControllerCleanup; -use Radebatz\OpenApi\Routing\Processors\MergeController; +use Radebatz\OpenApi\Extras\Processors\MergeControllerDefaults; +use Radebatz\OpenApi\Extras\Annotations\Middleware; use Symfony\Component\Finder\Finder; /** @@ -118,12 +114,6 @@ protected function registerOpenApi(OpenApi $openapi) } $middleware = []; - $uses = array_flip(class_uses($operation)); - if (array_key_exists(MiddlewareProperty::class, $uses)) { - if (!Generator::isDefault($operation->middleware) && is_array($operation->middleware)) { - $middleware = array_merge($middleware, $operation->middleware); - } - } if (!Generator::isDefault($operation->attachables)) { foreach ($operation->attachables as $attachable) { if ($attachable instanceof Middleware) { @@ -187,7 +177,7 @@ protected function parameterMetadata($parameters): array $metadata[$name]['type'] = $schema->type; if (!Generator::isDefault($pattern = $schema->pattern)) { $metadata[$name]['type'] = 'regex'; - $metadata[$name]['pattern'] = $schema->pattern; + $metadata[$name]['pattern'] = $pattern; } break; case 'integer': @@ -217,47 +207,12 @@ public function scan(): OpenApi ->generate($this->sources, $analysis); } - /** - * Set up Generator. - * - * Registers our custom annotations under the `oax` namespace alias. - */ public function generator(): Generator { - $operations = [ - OAX\Get::class => 'get', - OAX\Post::class => 'post', - OAX\Put::class => 'put', - OAX\Patch::class => 'patch', - OAX\Delete::class => 'delete', - OAX\Options::class => 'options', - OAX\Head::class => 'head', - OAX\Trace::class => 'trace', - ]; - foreach ($operations as $class => $operation) { - PathItem::$_nested[$class] = $operation; - $class::$_blacklist[] = 'middleware'; - } - - $routingNamespace = 'Radebatz\\OpenApi\\Routing\\Annotations'; - $generator = (new Generator()) - ->addNamespace($routingNamespace . '\\') - ->addAlias('oax', $routingNamespace) - ->addProcessor(new ControllerCleanup()); - - $processors = $generator->getProcessors(); - $insertMergeController = function (array $processors) { - $tmp = []; - foreach ($processors as $processor) { - if (get_class($processor) == BuildPaths::class) { - $tmp[] = new MergeController(); - } - $tmp[] = $processor; - } - - return $tmp; - }; - $generator->setProcessors($insertMergeController($processors)); + $generator = new Generator(); + $generator + ->getProcessorPipeline() + ->insert(new MergeControllerDefaults(), BuildPaths::class); return $generator; } diff --git a/src/Processors/ControllerCleanup.php b/src/Processors/ControllerCleanup.php deleted file mode 100644 index 8e3658c..0000000 --- a/src/Processors/ControllerCleanup.php +++ /dev/null @@ -1,37 +0,0 @@ -getAnnotationsOfType(Controller::class); - foreach ($controllers as $controller) { - $this->clearMerged($analysis, $controller); - $this->clearMerged($analysis, $controller->responses); - } - } - - protected function clearMerged(Analysis $analysis, $annotations) - { - if (Generator::isDefault($annotations)) { - return; - } - - $annotations = is_array($annotations) ? $annotations : [$annotations]; - - foreach ($annotations as $annotation) { - if (false !== ($offset = array_search($annotation, $analysis->openapi->_unmerged))) { - unset($analysis->openapi->_unmerged[$offset]); - } - } - } -} diff --git a/src/Processors/MergeController.php b/src/Processors/MergeController.php deleted file mode 100644 index 27842a9..0000000 --- a/src/Processors/MergeController.php +++ /dev/null @@ -1,94 +0,0 @@ -getAnnotationsOfType(Controller::class); - /** @var Operation[] $operations */ - $operations = $analysis->getAnnotationsOfType(Operation::class); - - foreach ($controllers as $controller) { - if ($this->needsProcessing($controller)) { - foreach ($operations as $operation) { - if ($this->contextMatch($operation, $controller->_context)) { - // update path - if (!Generator::isDefault($controller->prefix)) { - $path = $controller->prefix . '/' . $operation->path; - $operation->path = str_replace('//', '/', $path); - } - - if (!Generator::isDefault($controller->middleware) || !Generator::isDefault($controller->attachables)) { - $middleware = !Generator::isDefault($controller->middleware) ? $controller->middleware : []; - if (!Generator::isDefault($controller->attachables)) { - foreach ($controller->attachables as $attachable) { - if ($attachable instanceof AnnotationMiddleware || $attachable instanceof AttributeMiddleware) { - $middleware = array_merge($middleware, $attachable->names); - } - } - } - if (!Generator::isDefault($operation->attachables)) { - foreach ($operation->attachables as $attachable) { - if ($attachable instanceof AnnotationMiddleware || $attachable instanceof AttributeMiddleware) { - $middleware = array_merge($middleware, $attachable->names); - } - } - } - $middleware = array_unique($middleware); - - $uses = array_flip(class_uses($operation)); - if (array_key_exists(MiddlewareProperty::class, $uses)) { - $operation->middleware = !Generator::isDefault($operation->middleware) ? $operation->middleware : []; - $operation->middleware = array_merge($operation->middleware, $middleware); - } else { - // add as X property - $operation->x = !Generator::isDefault($operation->x) ? $operation->x : []; - $operation->x[RoutingAdapterInterface::X_MIDDLEWARE] = - array_key_exists(RoutingAdapterInterface::X_MIDDLEWARE, $operation->x) - ? $operation->x[RoutingAdapterInterface::X_MIDDLEWARE] - : []; - $operation->x[RoutingAdapterInterface::X_MIDDLEWARE] = - array_merge($operation->x[RoutingAdapterInterface::X_MIDDLEWARE], $middleware); - } - } - - if (!Generator::isDefault($controller->responses)) { - $operation->merge($controller->responses, true); - } - } - } - } - } - } - - protected function needsProcessing(Controller $controller) - { - return !Generator::isDefault($controller->prefix) - || !Generator::isDefault($controller->middleware) - || !Generator::isDefault($controller->responses) - || !Generator::isDefault($controller->attachables); - } - - protected function contextMatch(AbstractAnnotation $annotation, Context $context) - { - return $annotation->_context->namespace === $context->namespace - && $annotation->_context->class == $context->class; - } -} diff --git a/src/Processors/VendorPropertyValidation.php b/src/Processors/VendorPropertyValidation.php index 0086d72..feb6659 100644 --- a/src/Processors/VendorPropertyValidation.php +++ b/src/Processors/VendorPropertyValidation.php @@ -5,8 +5,7 @@ use OpenApi\Analysis; use OpenApi\Annotations\Operation; use OpenApi\Generator; -use Radebatz\OpenApi\Routing\Annotations\Middleware; -use Radebatz\OpenApi\Routing\Annotations\MiddlewareProperty; +use Radebatz\OpenApi\Extras\Annotations\Middleware; use Radebatz\OpenApi\Routing\RoutingAdapterInterface; /** @@ -42,12 +41,6 @@ public function __invoke(Analysis $analysis) $this->validateUniqueName($operation->operationId); } - $uses = array_flip(class_uses_recursive($operation)); - if (array_key_exists(MiddlewareProperty::class, $uses)) { - if (!Generator::isDefault($operation->middleware)) { - $this->validateVendorProperty(RoutingAdapterInterface::X_MIDDLEWARE, $operation->middleware); - } - } if (!Generator::isDefault($operation->attachables)) { foreach ($operation->attachables as $attachable) { if ($attachable instanceof Middleware) { diff --git a/tests/Fixtures/Controllers/AttributeController.php b/tests/Fixtures/Controllers/AttributeController.php index 4caaa61..36c8125 100644 --- a/tests/Fixtures/Controllers/AttributeController.php +++ b/tests/Fixtures/Controllers/AttributeController.php @@ -2,19 +2,19 @@ namespace Radebatz\OpenApi\Routing\Tests\Fixtures\Controllers; -use OpenApi\Attributes as OA; -use Radebatz\OpenApi\Routing\Attributes as OAX; +use OpenApi\Attributes as OAT; +use Radebatz\OpenApi\Extras\Attributes as OAX; use Radebatz\OpenApi\Routing\Tests\Fixtures\Middleware\BarMiddleware; use Radebatz\OpenApi\Routing\Tests\Fixtures\Middleware\FooMiddleware; if (\PHP_VERSION_ID >= 80100) { #[OAX\Controller(prefix: '/attributes')] - #[OA\Response(response: 403, description: 'Not allowed')] + #[OAT\Response(response: 403, description: 'Not allowed')] #[OAX\Middleware([FooMiddleware::class])] class AttributeController { - #[OA\Get(path: '/prefixed', x: ['name' => 'attributes'])] - #[OA\Response(response: 200, description: 'All good')] + #[OAT\Get(path: '/prefixed', x: ['name' => 'attributes'])] + #[OAT\Response(response: 200, description: 'All good')] #[OAX\Middleware([BarMiddleware::class])] public function prefixed() { diff --git a/tests/Fixtures/Controllers/InvokeController.php b/tests/Fixtures/Controllers/InvokeController.php index 842b4e9..470a07e 100644 --- a/tests/Fixtures/Controllers/InvokeController.php +++ b/tests/Fixtures/Controllers/InvokeController.php @@ -2,9 +2,12 @@ namespace Radebatz\OpenApi\Routing\Tests\Fixtures\Controllers; +use Radebatz\OpenApi\Extras\Annotations as OAX; + /** * @OAX\Controller( * prefix="/foo", + * * @OA\Response(response="401", description="Unauthorized") * ) */ @@ -16,6 +19,7 @@ class InvokeController * x={ * "name": "invoke" * }, + * * @OA\Response(response="200", description="All good") * ) */ diff --git a/tests/Fixtures/Controllers/MiddlewareController.php b/tests/Fixtures/Controllers/MiddlewareController.php index e99eb6e..2061960 100644 --- a/tests/Fixtures/Controllers/MiddlewareController.php +++ b/tests/Fixtures/Controllers/MiddlewareController.php @@ -2,6 +2,8 @@ namespace Radebatz\OpenApi\Routing\Tests\Fixtures\Controllers; +use OpenApi\Annotations as OA; + class MiddlewareController { /** @@ -11,6 +13,7 @@ class MiddlewareController * "name": "mw", * "middleware"={"Radebatz\OpenApi\Routing\Tests\Fixtures\Middleware\FooMiddleware", "Radebatz\OpenApi\Routing\Tests\Fixtures\Middleware\BarMiddleware"} * }, + * * @OA\Response(response="200", description="All good") * ) */ diff --git a/tests/Fixtures/Controllers/NamedRouteController.php b/tests/Fixtures/Controllers/NamedRouteController.php index 5f7c3b5..ce251f9 100644 --- a/tests/Fixtures/Controllers/NamedRouteController.php +++ b/tests/Fixtures/Controllers/NamedRouteController.php @@ -2,6 +2,8 @@ namespace Radebatz\OpenApi\Routing\Tests\Fixtures\Controllers; +use OpenApi\Annotations as OA; + class NamedRouteController { /** @@ -10,6 +12,7 @@ class NamedRouteController * x={ * "name": "getya" * }, + * * @OA\Response(response="200", description="All good") * ) */ @@ -24,6 +27,7 @@ public function getya() * x={ * "name": "static_getya" * }, + * * @OA\Response(response="200", description="All good") * ) */ diff --git a/tests/Fixtures/Controllers/ParametersController.php b/tests/Fixtures/Controllers/ParametersController.php index a43e25e..44c708e 100644 --- a/tests/Fixtures/Controllers/ParametersController.php +++ b/tests/Fixtures/Controllers/ParametersController.php @@ -2,6 +2,8 @@ namespace Radebatz\OpenApi\Routing\Tests\Fixtures\Controllers; +use OpenApi\Annotations as OA; + class ParametersController { /** @@ -10,15 +12,18 @@ class ParametersController * x={ * "name": "hey" * }, + * * @OA\Parameter( * name="name", * in="path", * required=true, * description="The name", + * * @OA\Schema( * type="string" * ) * ), + * * @OA\Response(response="200", description="All good") * ) */ @@ -33,15 +38,18 @@ public function hey($name) * x={ * "name": "oi" * }, + * * @OA\Parameter( * name="name", * in="path", * required=false, * description="The name", + * * @OA\Schema( * type="string" * ) * ), + * * @OA\Response(response="200", description="All good") * ) */ @@ -56,16 +64,19 @@ public function oi($name = 'you') * x={ * "name": "id" * }, + * * @OA\Parameter( * name="id", * in="path", * required=true, * description="The id", + * * @OA\Schema( * type="integer", * format="int32" * ) * ), + * * @OA\Response(response="200", description="All good") * ) */ @@ -80,16 +91,19 @@ public function id($id) * x={ * "name": "hid" * }, + * * @OA\Parameter( * name="hid", * in="path", * required=true, * description="The hid", + * * @OA\Schema( * type="string", * pattern="[0-9a-f]+" * ) * ), + * * @OA\Response(response="200", description="All good") * ) */ @@ -104,24 +118,29 @@ public function hid($hid) * x={ * "name": "multi" * }, + * * @OA\Parameter( * name="foo", * in="path", * required=false, * description="The foo", + * * @OA\Schema( * type="string" * ) * ), + * * @OA\Parameter( * name="bar", * in="path", * required=false, * description="The bar", + * * @OA\Schema( * type="string" * ) * ), + * * @OA\Response(response="200", description="All good") * ) */ diff --git a/tests/Fixtures/Controllers/PrefixedController.php b/tests/Fixtures/Controllers/PrefixedController.php index abdaf91..ebff64a 100644 --- a/tests/Fixtures/Controllers/PrefixedController.php +++ b/tests/Fixtures/Controllers/PrefixedController.php @@ -2,9 +2,13 @@ namespace Radebatz\OpenApi\Routing\Tests\Fixtures\Controllers; +use OpenApi\Annotations as OA; +use Radebatz\OpenApi\Extras\Annotations as OAX; + /** * @OAX\Controller( * prefix="/foo", + * * @OA\Response(response="403", description="Not allowed") * ) */ @@ -16,6 +20,7 @@ class PrefixedController * x={ * "name": "prefixed" * }, + * * @OA\Response(response="200", description="All good") * ) */ diff --git a/tests/Laravel/LaravelTest.php b/tests/Laravel/LaravelTest.php index c3ba376..0913184 100644 --- a/tests/Laravel/LaravelTest.php +++ b/tests/Laravel/LaravelTest.php @@ -36,6 +36,7 @@ public function prefixed() /** * @test + * * @requires PHP 8.1 */ public function attributesPrefixed() @@ -47,6 +48,7 @@ public function attributesPrefixed() /** * @test + * * @requires PHP 8.1 */ public function attributesMiddleware() @@ -54,6 +56,6 @@ public function attributesMiddleware() $route = $this->getRouter()->getRoutes()->getByName('attributes'); $this->assertNotNull($route); - $this->assertEquals([FooMiddleware::class, BarMiddleware::class], $route->gatherMiddleware()); + $this->assertEquals([BarMiddleware::class, FooMiddleware::class], $route->gatherMiddleware()); } } diff --git a/tests/Lumen/LumenTest.php b/tests/Lumen/LumenTest.php index 9a15c7e..18e2bc8 100644 --- a/tests/Lumen/LumenTest.php +++ b/tests/Lumen/LumenTest.php @@ -38,6 +38,7 @@ public function middleware() /** * @test + * * @requires PHP 8.1 */ public function attributesPrefixed() diff --git a/tests/Slim4/SlimTest.php b/tests/Slim4/SlimTest.php index 12c0ce1..3e6054b 100644 --- a/tests/Slim4/SlimTest.php +++ b/tests/Slim4/SlimTest.php @@ -43,6 +43,7 @@ public function middleware() /** * @test + * * @requires PHP 8.1 */ public function attributesPrefixed() From d88f998c36facd481874a7ce8724df1b1f8a1901 Mon Sep 17 00:00:00 2001 From: DerManoMann Date: Wed, 6 Nov 2024 09:52:05 +1300 Subject: [PATCH 2/6] Reconfigure dependabot --- .github/dependabot.yml | 6 ++---- .github/workflows/build.yml | 12 +++++++++--- .github/workflows/laravel.yml | 21 ++++++++------------- .github/workflows/lumen.yml | 23 +++++++---------------- .github/workflows/security-checks.yml | 9 +++------ .github/workflows/slim.yml | 11 ++++++----- README.md | 2 +- composer.json | 10 +++++----- 8 files changed, 41 insertions(+), 53 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1d2aaba..8c139c7 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,6 @@ version: 2 updates: -- package-ecosystem: composer +- package-ecosystem: "github-actions" directory: "/" schedule: - interval: daily - time: "17:00" - open-pull-requests-limit: 10 + interval: "weekly" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c2f636e..a5ba8d2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,8 +10,14 @@ on: jobs: call-laravel: - uses: ./.github/workflows/laravel.yml@main + uses: ./.github/workflows/laravel.yml + with: + php-versions: '8.1,8.2,8.3,8.4' call-lumen: - uses: ./.github/workflows/lumen.yml@main + uses: ./.github/workflows/lumen.yml + with: + php-versions: '8.1,8.2,8.3,8.4' call-slim: - uses: ./.github/workflows/slim.yml@main + uses: ./.github/workflows/slim.yml + with: + php-versions: '8.1,8.2,8.3,8.4' diff --git a/.github/workflows/laravel.yml b/.github/workflows/laravel.yml index d068dcd..1d493df 100644 --- a/.github/workflows/laravel.yml +++ b/.github/workflows/laravel.yml @@ -2,6 +2,10 @@ name: laravel on: workflow_call: + inputs: + php-versions: + required: true + type: string jobs: test: @@ -10,24 +14,15 @@ jobs: COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}' COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} strategy: - fail-fast: true + fail-fast: false matrix: operating-system: [ ubuntu-latest ] - php: [ '7.2', '7.3', '7.4', '8.0', '8.1' ] - laravel: [ '7.0', '8.0', '9.0' ] + php: ${{ fromJson(format('[{0}]', inputs.php-versions)) }} + laravel: [ '10.0', '11.0' ] dependencies: [ 'lowest', ' highest' ] exclude: - - php: '7.2' - laravel: '9.0' - - php: '7.2' - laravel: '8.0' - - php: '7.3' - laravel: '9.0' - - php: '7.4' - laravel: '9.0' - php: '8.1' - laravel: '7.0' - - dependencies: 'lowest' + laravel: '11.0' name: PHP ${{ matrix.php }} / Laravel ${{ matrix.laravel }} on ${{ matrix.operating-system }} with ${{ matrix.dependencies }} dependencies diff --git a/.github/workflows/lumen.yml b/.github/workflows/lumen.yml index 3907592..01503be 100644 --- a/.github/workflows/lumen.yml +++ b/.github/workflows/lumen.yml @@ -2,6 +2,10 @@ name: lumen on: workflow_call: + inputs: + php-versions: + required: true + type: string jobs: test: @@ -10,25 +14,12 @@ jobs: COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}' COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} strategy: - fail-fast: true + fail-fast: false matrix: operating-system: [ ubuntu-latest ] - php: [ '7.2', '7.3', '7.4', '8.0', '8.1' ] - lumen: [ '8.0', '9.0' ] + php: ${{ fromJson(format('[{0}]', inputs.php-versions)) }} + lumen: [ '10.0' ] dependencies: [ 'highest' ] - exclude: - - php: '7.2' - lumen: '9.0' - - php: '7.2' - lumen: '8.0' - - php: '7.3' - lumen: '9.0' - - php: '7.4' - lumen: '9.0' - - php: '8.1' - lumen: '8.0' - - php: '8.1' - dependencies: 'lowest' name: PHP ${{ matrix.php }} / Lumen ${{ matrix.lumen }} on ${{ matrix.operating-system }} with ${{ matrix.dependencies }} dependencies diff --git a/.github/workflows/security-checks.yml b/.github/workflows/security-checks.yml index b7811a4..0e58b3a 100644 --- a/.github/workflows/security-checks.yml +++ b/.github/workflows/security-checks.yml @@ -11,14 +11,11 @@ on: jobs: security-checker: runs-on: ${{ matrix.operating-system }} - env: - COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}' - COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} strategy: fail-fast: true matrix: operating-system: [ ubuntu-latest ] - php: [ '7.4', '8.0', '8.1', '8.2', '8.3', '8.4' ] + php: [ '8.1', '8.2', '8.3', '8.4' ] dependencies: [ 'highest' ] name: PHP ${{ matrix.php }} on ${{ matrix.operating-system }} with ${{ matrix.dependencies }} dependencies @@ -33,7 +30,7 @@ jobs: php-version: ${{ matrix.php }} - name: Composer install - uses: ramsey/composer-install@v1 + uses: ramsey/composer-install@v2 with: dependency-versions: ${{ matrix.dependencies }} composer-options: ${{ matrix.composer-options }} --no-dev @@ -44,4 +41,4 @@ jobs: path: ~/.symfony/cache key: security-checker-db - - uses: symfonycorp/security-checker-action@v2 + - uses: symfonycorp/security-checker-action@v3 diff --git a/.github/workflows/slim.yml b/.github/workflows/slim.yml index 02484a6..b8d2277 100644 --- a/.github/workflows/slim.yml +++ b/.github/workflows/slim.yml @@ -2,6 +2,10 @@ name: slim on: workflow_call: + inputs: + php-versions: + required: true + type: string jobs: test: @@ -10,15 +14,12 @@ jobs: COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}' COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} strategy: - fail-fast: true + fail-fast: false matrix: operating-system: [ ubuntu-latest ] - php: [ '8.0', '8.1' ] + php: ${{ fromJson(format('[{0}]', inputs.php-versions)) }} slim: [ '4.0' ] dependencies: [ 'lowest', 'highest' ] - exclude: - - php: '8.1' - dependencies: 'lowest' name: PHP ${{ matrix.php }} / Slim ${{ matrix.slim }} on ${{ matrix.operating-system }} with ${{ matrix.dependencies }} dependencies diff --git a/README.md b/README.md index 0c596d5..555ab32 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ following frameworks: ## Requirements -* [PHP 7.4 or higher](http://www.php.net/) - depending on framework version. +* [PHP 8.1 or higher](http://www.php.net/) - depending on framework version. ## Installation diff --git a/composer.json b/composer.json index c3fc574..120ca21 100644 --- a/composer.json +++ b/composer.json @@ -39,8 +39,8 @@ } }, "require": { - "php": ">=7.4", - "laravel/laravel": "^9", + "php": ">=8.1", + "laravel/laravel": "^10.0", "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", "radebatz/openapi-extras": "^2.1", "zircote/swagger-php": "^4.11.1" @@ -50,9 +50,9 @@ "friendsofphp/php-cs-fixer": "^3.0", "nyholm/psr7": "^1.4", "nyholm/psr7-server": "^1.0", - "phpunit/phpunit": "^9.0", - "symfony/cache": "^5.0 || ^6.0", - "symfony/psr-http-message-bridge": "^2.1" + "phpunit/phpunit": "^10.0", + "symfony/cache": "^6.0 || ^7.0", + "symfony/psr-http-message-bridge": "^6.0 || ^7.0" }, "suggest": { "radebatz/openapi-verifier": "Allows your PHPUnit tests to validate your controller response against the OpenAPI annotations." From aed99ce0edd240ad736fe9e520ec24f798ca4d7d Mon Sep 17 00:00:00 2001 From: DerManoMann Date: Wed, 6 Nov 2024 11:40:27 +1300 Subject: [PATCH 3/6] Make @dataProvider static --- .github/workflows/laravel.yml | 4 +++- .github/workflows/lumen.yml | 2 +- .github/workflows/slim.yml | 2 +- README.md | 2 +- TODO | 4 ---- composer.json | 6 +++--- phpunit.xml.dist | 2 +- src/OpenApiRouter.php | 27 +++++++-------------------- tests/Laravel/CachingTest.php | 2 +- 9 files changed, 18 insertions(+), 33 deletions(-) delete mode 100644 TODO diff --git a/.github/workflows/laravel.yml b/.github/workflows/laravel.yml index 1d493df..6ded87f 100644 --- a/.github/workflows/laravel.yml +++ b/.github/workflows/laravel.yml @@ -14,7 +14,7 @@ jobs: COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}' COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} strategy: - fail-fast: false + fail-fast: true matrix: operating-system: [ ubuntu-latest ] php: ${{ fromJson(format('[{0}]', inputs.php-versions)) }} @@ -23,6 +23,8 @@ jobs: exclude: - php: '8.1' laravel: '11.0' + - laravel: '11.0' + dependencies: 'lowest' name: PHP ${{ matrix.php }} / Laravel ${{ matrix.laravel }} on ${{ matrix.operating-system }} with ${{ matrix.dependencies }} dependencies diff --git a/.github/workflows/lumen.yml b/.github/workflows/lumen.yml index 01503be..329621d 100644 --- a/.github/workflows/lumen.yml +++ b/.github/workflows/lumen.yml @@ -14,7 +14,7 @@ jobs: COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}' COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} strategy: - fail-fast: false + fail-fast: true matrix: operating-system: [ ubuntu-latest ] php: ${{ fromJson(format('[{0}]', inputs.php-versions)) }} diff --git a/.github/workflows/slim.yml b/.github/workflows/slim.yml index b8d2277..ff15156 100644 --- a/.github/workflows/slim.yml +++ b/.github/workflows/slim.yml @@ -14,7 +14,7 @@ jobs: COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}' COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} strategy: - fail-fast: false + fail-fast: true matrix: operating-system: [ ubuntu-latest ] php: ${{ fromJson(format('[{0}]', inputs.php-versions)) }} diff --git a/README.md b/README.md index 555ab32..7c4c502 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ following frameworks: ## Requirements -* [PHP 8.1 or higher](http://www.php.net/) - depending on framework version. +* [PHP 8.1 or higher](http://www.php.net/) - depending on framework version. ## Installation diff --git a/TODO b/TODO deleted file mode 100644 index 9c36cb0..0000000 --- a/TODO +++ /dev/null @@ -1,4 +0,0 @@ -* Add support for: - * scheme - * parameter requirements (regex, etc) -* Wrap as service provider / middleware? diff --git a/composer.json b/composer.json index 120ca21..1ee854e 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ }, "require": { "php": ">=8.1", - "laravel/laravel": "^10.0", + "psr/log": "^1.1 || ^2.0 || ^3.0", "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", "radebatz/openapi-extras": "^2.1", "zircote/swagger-php": "^4.11.1" @@ -50,11 +50,11 @@ "friendsofphp/php-cs-fixer": "^3.0", "nyholm/psr7": "^1.4", "nyholm/psr7-server": "^1.0", - "phpunit/phpunit": "^10.0", + "phpunit/phpunit": "^9.0 || ^10.5", "symfony/cache": "^6.0 || ^7.0", "symfony/psr-http-message-bridge": "^6.0 || ^7.0" }, "suggest": { - "radebatz/openapi-verifier": "Allows your PHPUnit tests to validate your controller response against the OpenAPI annotations." + "radebatz/openapi-verifier": "Allows your PHPUnit tests to validate your controller response against your OpenAPI spec." } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 0202aee..365bf44 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -9,7 +9,7 @@ - + tests diff --git a/src/OpenApiRouter.php b/src/OpenApiRouter.php index 85b8b68..5a45447 100644 --- a/src/OpenApiRouter.php +++ b/src/OpenApiRouter.php @@ -2,9 +2,6 @@ namespace Radebatz\OpenApi\Routing; -use OpenApi\Analysers\AttributeAnnotationFactory; -use OpenApi\Analysers\DocBlockAnnotationFactory; -use OpenApi\Analysers\ReflectionAnalyser; use OpenApi\Analysis; use OpenApi\Annotations\Info; use OpenApi\Annotations\OpenApi; @@ -12,9 +9,9 @@ use OpenApi\Annotations\Parameter; use OpenApi\Context; use OpenApi\Generator; -use OpenApi\Processors\BuildPaths; +use Psr\Log\LoggerInterface; use Psr\SimpleCache\CacheInterface; -use Radebatz\OpenApi\Extras\Processors\MergeControllerDefaults; +use Radebatz\OpenApi\Extras\OpenApiBuilder; use Radebatz\OpenApi\Extras\Annotations\Middleware; use Symfony\Component\Finder\Finder; @@ -49,7 +46,7 @@ public function __construct($sources, RoutingAdapterInterface $routingAdapter, a $this->options = $options + [ self::OPTION_RELOAD => true, self::OPTION_CACHE => null, - self::OPTION_OA_INFO_INJECT => true, + self::OPTION_OA_INFO_INJECT => false, self::OPTION_OA_OPERATION_ID_AS_NAME => true, ]; } @@ -190,30 +187,20 @@ protected function parameterMetadata($parameters): array return $metadata; } - public function scan(): OpenApi + public function scan(?LoggerInterface $logger = null): OpenApi { - $generator = $this->generator(); + $generator = (new OpenApiBuilder())->build($logger); + // provide default @OA\Info in case we need to do some scanning $analysis = $generator->withContext(function (Generator $generator, Analysis $analysis, Context $context) { if ($this->options[self::OPTION_OA_INFO_INJECT]) { - $analysis->addAnnotation(new Info(['title' => 'Test', 'version' => '1.0']), $context); + $analysis->addAnnotation(new Info(['title' => 'OpenApi', 'version' => '1.0']), $context); } return $analysis; }); return $generator - ->setAnalyser(new ReflectionAnalyser([new DocBlockAnnotationFactory(), new AttributeAnnotationFactory()])) ->generate($this->sources, $analysis); } - - public function generator(): Generator - { - $generator = new Generator(); - $generator - ->getProcessorPipeline() - ->insert(new MergeControllerDefaults(), BuildPaths::class); - - return $generator; - } } diff --git a/tests/Laravel/CachingTest.php b/tests/Laravel/CachingTest.php index 319727e..dc4e788 100644 --- a/tests/Laravel/CachingTest.php +++ b/tests/Laravel/CachingTest.php @@ -15,7 +15,7 @@ class CachingTest extends LaravelTestCase { use CallsApplicationTrait; - public function reloadTests() + public static function reloadTests(): iterable { return [ [null, true, false], From c9f47e718320744254ae5b217ae97d5805c0cdb2 Mon Sep 17 00:00:00 2001 From: DerManoMann Date: Wed, 6 Nov 2024 20:07:19 +1300 Subject: [PATCH 4/6] Update tests for new options defaults --- tests/Laravel/CachingTest.php | 1 + tests/Laravel/CallsApplicationTrait.php | 7 +++++-- tests/Slim4/CallsControllerTrait.php | 7 +++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/Laravel/CachingTest.php b/tests/Laravel/CachingTest.php index dc4e788..883071f 100644 --- a/tests/Laravel/CachingTest.php +++ b/tests/Laravel/CachingTest.php @@ -31,6 +31,7 @@ public static function reloadTests(): iterable public function testReload(?CacheInterface $cache, $reload, $openapisCached) { $options = [ + OpenApiRouter::OPTION_OA_INFO_INJECT => true, OpenApiRouter::OPTION_RELOAD => $reload, OpenApiRouter::OPTION_CACHE => $cache, ]; diff --git a/tests/Laravel/CallsApplicationTrait.php b/tests/Laravel/CallsApplicationTrait.php index 5f3c55f..94780a7 100644 --- a/tests/Laravel/CallsApplicationTrait.php +++ b/tests/Laravel/CallsApplicationTrait.php @@ -37,9 +37,12 @@ public function createApplication() ]); Facade::setFacadeApplication($app); - (new OpenApiRouter($this->getFixtureFinder(), new LaravelRoutingAdapter($app))) + $options = [ + OpenApiRouter::OPTION_OA_INFO_INJECT => true, + ]; + (new OpenApiRouter($this->getFixtureFinder(), new LaravelRoutingAdapter($app), $options)) ->registerRoutes(); - $openapi = (new OpenApiRouter($this->getFixtureFinder(), new LaravelRoutingAdapter($app))) + $openapi = (new OpenApiRouter($this->getFixtureFinder(), new LaravelRoutingAdapter($app), $options)) ->scan(); file_put_contents(__DIR__ . '/openapi.yaml', $openapi->toYaml()); diff --git a/tests/Slim4/CallsControllerTrait.php b/tests/Slim4/CallsControllerTrait.php index 06e1e03..a84c725 100644 --- a/tests/Slim4/CallsControllerTrait.php +++ b/tests/Slim4/CallsControllerTrait.php @@ -33,9 +33,12 @@ protected function getApp(): App { $app = AppFactory::create(); - (new OpenApiRouter($this->getFixtureFinder(), new SlimRoutingAdapter($app))) + $options = [ + OpenApiRouter::OPTION_OA_INFO_INJECT => true, + ]; + (new OpenApiRouter($this->getFixtureFinder(), new SlimRoutingAdapter($app), $options)) ->registerRoutes(); - $openapi = (new OpenApiRouter($this->getFixtureFinder(), new SlimRoutingAdapter($app))) + $openapi = (new OpenApiRouter($this->getFixtureFinder(), new SlimRoutingAdapter($app), $options)) ->scan(); file_put_contents(__DIR__ . '/openapi.yaml', $openapi->toYaml()); From cf3fcb1400df5fc0ac1c1b4465176d486f0d4538 Mon Sep 17 00:00:00 2001 From: DerManoMann Date: Thu, 7 Nov 2024 08:42:56 +1300 Subject: [PATCH 5/6] Update docs --- README.md | 59 ++++++++--------- composer.json | 1 + docs/AnnotationExtensions.md | 125 ----------------------------------- docs/Configuration.md | 20 ++++-- 4 files changed, 42 insertions(+), 163 deletions(-) delete mode 100644 docs/AnnotationExtensions.md diff --git a/README.md b/README.md index 7c4c502..99f8174 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,16 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ## Introduction -Allows to (re-)use [Swagger-PHP](https://github.com/zircote/swagger-php) attributes to configure routes in the -following frameworks: +Allows to (re-)use [Swagger-PHP](https://github.com/zircote/swagger-php) attributes (docblock annotations are deprecated), +to configure routes in the following frameworks: + * [Laravel](https://github.com/laravel/laravel) * [Lumen](https://github.com/laravel/lumen) * [Slim](https://github.com/slimphp/Slim) ## Requirements -* [PHP 8.1 or higher](http://www.php.net/) - depending on framework version. +* [PHP 8.1 or higher](http://www.php.net/) - depending on framework version. ## Installation @@ -34,7 +35,30 @@ After that all required classes should be availabe in your project to add routin ## Basic usage -Example using the `Slim` framework adapter and standard [OpenApi annotations](https://github.com/zircote/swagger-php/tree/main/src/Annotations) only. +Example using the `Slim` framework adapter and standard [OpenApi attributes](https://zircote.github.io/swagger-php/guide/attributes) only. + +**Controller** +```php +write('Get me'); + } +} +``` **index.php** ```php @@ -53,35 +77,8 @@ $app = new App(); $app->run(); ``` -**Controller** -```php -write('Get me'); - } -} -``` - ## Documentation * [Configuration](docs/Configuration.md) -* [Annotation extensions](docs/AnnotationExtensions.md) ## License diff --git a/composer.json b/composer.json index 1ee854e..81ae2b4 100644 --- a/composer.json +++ b/composer.json @@ -43,6 +43,7 @@ "psr/log": "^1.1 || ^2.0 || ^3.0", "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", "radebatz/openapi-extras": "^2.1", + "slim/slim": "^4.14", "zircote/swagger-php": "^4.11.1" }, "require-dev": { diff --git a/docs/AnnotationExtensions.md b/docs/AnnotationExtensions.md deleted file mode 100644 index 366ecd1..0000000 --- a/docs/AnnotationExtensions.md +++ /dev/null @@ -1,125 +0,0 @@ -# Annotation Extensions - -## Default Annotations -By default the router expects only standard [OpenApi annotations](https://github.com/zircote/swagger-php/tree/main/src/Annotations). - -Theses annotations have only limited build in support for advanced routing features. If you feel like -sticking to those the only way to add more options is to use the -[vendor extension](https://swagger.io/specification/#vendorExtensions) system. - -Vendor extensions are OpenApi properties starting with `x-`. Annotations supports this via the `x` annotation property. - -**Vendor extension example:** -```php - ... - - /** - * @OA\Get( - * path="/login", - * x={ - * "name": "login", - * "middleware": {"auth", "verified"} - * }, - * @OA\Response(response="200", description="All good") - * ) - */ -``` - -The example showcases the two vendor extensions that the router supports: -* **name** - - The name property is used to bind a (unique) name to each route which later can be used to lookup - the route (for example to generate a url). - - name binding is supported by all adapters. - -* **middleware** - - [Middleware](https://www.php-fig.org/psr/psr-15/) is a concept that only some frameworks support. In those cases - one or more middleware can be attached to a route as shown above. - - Middleware binding is supported by all adapters. - -As an alternative to using the x-name property it is also possible to use the standard `operationId` property to configure -a route name. - -**NOTE:** It is worth noticing that by default this property is set to `[Controller class]::[method name]` by the swagger-php -library. If you do not wish to use `operationId` it is recommended to disable using it as name value for route binding -(see the global `OPTION_OA_OPERATION_ID_AS_NAME` config option) - -## Extended Annotations -### Operations -As an alternative to the above syntax the openapi-router project provides its own (extended) versions of annotations for -all operations (`'get', 'post', 'put', 'patch', 'delete', 'options', 'head'`). - -These are registered with a namespace alias of `@OSX`. - -**Extended annotation example:** -```php - ... - - /** - * @OAX\Get( - * path="/foo", - * operationId="foo", - * @OA\Response(response="200", description="All good") - * ) - */ -``` - -### `Controller` Annotation -openapi-router also provides a `Controller` annotation that can be used to: -* apply a path prefix to all controller routes -* configure middlewares shared by all controller routes -* configure responses shared by all controller routes - -This annotation can be used with both standard and extended operation annotations. - -**Controller annotation example:** -```php -... - -/** - * @OAX\Controller( - * prefix="api/v1", - * middleware={"auth"}, - * @OA\Response(response=401, description="Not Authenticated") - * ) - */ -class UserController extends Controller -{ - /** - * @OA\Get( - * path="user/{id}/delete", - * operationId="transfer", - * middleware={"role:admin"}, - * @OA\Response(response="200", description="All good") - * ) - */ - public static function delete($request, $response, $id) - { - // delete user - } -``` - -## Attributes -As of PHP 8.1 swagger-php and openapi-router also allow to use PHP attributes instead of docblock annotations. -Names and features are the same with one exception - for middleware there is a new attribute `Middleware` which avoid having to -use the included customized swagger-php operation annotations. - -Here is an example taken from the test suite: -```php - -use Radebatz\OpenApi\Routing\Annotations as OAX; - - class AttributeController - { - #[OA\Get(path: '/prefixed', x: ['name' => 'attributes'])] - #[OA\Response(response: 200, description: 'All good')] - #[OAX\Middleware([BMiddleware::class])] - public function prefixed() - { - return FakeResponse::create('Get fooya'); - } - } -``` diff --git a/docs/Configuration.md b/docs/Configuration.md index d5a1a82..21f677a 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -4,7 +4,7 @@ The `OpenApiRouter` class takes an array (map) as optional third constructor argument which allows to customise its behaviour. -All option names (keys) are defined as class constants. +All option names (keys) are defined as class constants in `Radebatz\OpenApi\Routing\OpenApiRouter`. **`OPTION_RELOAD`** --- @@ -12,6 +12,8 @@ Enforces loading of route annotations on each request. Typically you want this turned off on production. Requires a cache confgured (annotation caching) or caching support implemented by the used adapter. +**Note**: When using a framework it is recommended to rely on the framework caching rather than using the (simple) build in cache. + Default: `true` **`OPTION_CACHE`** @@ -26,21 +28,24 @@ Default: `null` --- Controls whether to inject a default `@OA\Info` instance while scanning. -This can be useful if your top level OpenApi annotation is inside the scanned folder hierarchy. +This can be useful for testing or small projects. -Default: `true` +Default: `false` **`OPTION_OA_OPERATION_ID_AS_NAME`** --- -Controls whether to default the custom (x-) name property to the `operationId`. +Controls whether to use the configured `operationId` as the route name. If disabled the adapter will look for a vendor property +`x-name` on the operation (`Get`, `Post`, etc.) attribute. + +Allows to set the route name via the standard `operationId` rather than the vendor `x-name`. -Allows to set the route name via the standard `operationId` rather than `x-name`. -By default the `operationId` is populated with the controller (class/method) for the route. +**Note**: The default for `operationId` in `swagger-php` is to generate an operationId and hash it if it is explicitely set. generated Default: `true` ### Example use ```php + Date: Fri, 8 Nov 2024 16:27:59 +1300 Subject: [PATCH 6/6] Bump action deps --- .github/workflows/code-style.yml | 2 +- .github/workflows/laravel.yml | 2 +- .github/workflows/lumen.yml | 2 +- .github/workflows/security-checks.yml | 8 ++++---- .github/workflows/slim.yml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/code-style.yml b/.github/workflows/code-style.yml index d47797b..9ef6404 100644 --- a/.github/workflows/code-style.yml +++ b/.github/workflows/code-style.yml @@ -12,7 +12,7 @@ jobs: php-cs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 name: Checkout repository - name: Setup PHP diff --git a/.github/workflows/laravel.yml b/.github/workflows/laravel.yml index 6ded87f..b0cf3fa 100644 --- a/.github/workflows/laravel.yml +++ b/.github/workflows/laravel.yml @@ -29,7 +29,7 @@ jobs: name: PHP ${{ matrix.php }} / Laravel ${{ matrix.laravel }} on ${{ matrix.operating-system }} with ${{ matrix.dependencies }} dependencies steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 name: Checkout repository - name: Setup PHP diff --git a/.github/workflows/lumen.yml b/.github/workflows/lumen.yml index 329621d..58becd4 100644 --- a/.github/workflows/lumen.yml +++ b/.github/workflows/lumen.yml @@ -24,7 +24,7 @@ jobs: name: PHP ${{ matrix.php }} / Lumen ${{ matrix.lumen }} on ${{ matrix.operating-system }} with ${{ matrix.dependencies }} dependencies steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 name: Checkout repository - name: Setup PHP diff --git a/.github/workflows/security-checks.yml b/.github/workflows/security-checks.yml index 0e58b3a..9db4aa6 100644 --- a/.github/workflows/security-checks.yml +++ b/.github/workflows/security-checks.yml @@ -21,7 +21,7 @@ jobs: name: PHP ${{ matrix.php }} on ${{ matrix.operating-system }} with ${{ matrix.dependencies }} dependencies steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 name: Checkout repository - name: Setup PHP @@ -30,15 +30,15 @@ jobs: php-version: ${{ matrix.php }} - name: Composer install - uses: ramsey/composer-install@v2 + uses: ramsey/composer-install@v3 with: dependency-versions: ${{ matrix.dependencies }} composer-options: ${{ matrix.composer-options }} --no-dev - name: Cache security checker dependencies - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.symfony/cache key: security-checker-db - - uses: symfonycorp/security-checker-action@v3 + - uses: symfonycorp/security-checker-action@v5 diff --git a/.github/workflows/slim.yml b/.github/workflows/slim.yml index ff15156..d0bfc2b 100644 --- a/.github/workflows/slim.yml +++ b/.github/workflows/slim.yml @@ -24,7 +24,7 @@ jobs: name: PHP ${{ matrix.php }} / Slim ${{ matrix.slim }} on ${{ matrix.operating-system }} with ${{ matrix.dependencies }} dependencies steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 name: Checkout repository - name: Setup PHP