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 7087b53..a5ba8d2 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -3,15 +3,21 @@ 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
+ with:
+ php-versions: '8.1,8.2,8.3,8.4'
call-lumen:
- uses: DerManoMann/openapi-router/.github/workflows/lumen.yml@master
+ uses: ./.github/workflows/lumen.yml
+ with:
+ php-versions: '8.1,8.2,8.3,8.4'
call-slim:
- uses: DerManoMann/openapi-router/.github/workflows/slim.yml@master
+ uses: ./.github/workflows/slim.yml
+ with:
+ php-versions: '8.1,8.2,8.3,8.4'
diff --git a/.github/workflows/code-style.yml b/.github/workflows/code-style.yml
index 84b8512..9ef6404 100644
--- a/.github/workflows/code-style.yml
+++ b/.github/workflows/code-style.yml
@@ -3,22 +3,22 @@ name: code-style
on:
push:
branches:
- - master
+ - main
pull_request:
branches:
- - master
+ - main
jobs:
php-cs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
name: Checkout repository
- 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/laravel.yml b/.github/workflows/laravel.yml
index d068dcd..b0cf3fa 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:
@@ -13,26 +17,19 @@ jobs:
fail-fast: true
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'
+ - laravel: '11.0'
+ dependencies: 'lowest'
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 3907592..58becd4 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:
@@ -13,27 +17,14 @@ jobs:
fail-fast: true
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
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 173d87b..9db4aa6 100644
--- a/.github/workflows/security-checks.yml
+++ b/.github/workflows/security-checks.yml
@@ -3,28 +3,25 @@ name: security-checks
on:
push:
branches:
- - master
+ - main
pull_request:
branches:
- - master
+ - main
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: [ '8.0', '8.1' ]
+ php: [ '8.1', '8.2', '8.3', '8.4' ]
dependencies: [ 'highest' ]
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
@@ -33,15 +30,15 @@ jobs:
php-version: ${{ matrix.php }}
- name: Composer install
- uses: ramsey/composer-install@v1
+ 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@v2
+ - uses: symfonycorp/security-checker-action@v5
diff --git a/.github/workflows/slim.yml b/.github/workflows/slim.yml
index 02484a6..d0bfc2b 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:
@@ -13,17 +17,14 @@ jobs:
fail-fast: true
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
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
name: Checkout repository
- name: Setup PHP
diff --git a/README.md b/README.md
index 79f08c3..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) annotations 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 7.2 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/master/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,33 +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/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 b447386..81ae2b4 100644
--- a/composer.json
+++ b/composer.json
@@ -35,24 +35,27 @@
},
"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": ">=8.1",
+ "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": {
- "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",
- "symfony/cache": "^5.0 || ^6.0",
- "symfony/psr-http-message-bridge": "^2.1"
+ "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/docs/AnnotationExtensions.md b/docs/AnnotationExtensions.md
deleted file mode 100644
index 652847a..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/master/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
+
-
+
tests
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..5a45447 100644
--- a/src/OpenApiRouter.php
+++ b/src/OpenApiRouter.php
@@ -2,24 +2,17 @@
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;
use OpenApi\Annotations\Operation;
use OpenApi\Annotations\Parameter;
-use OpenApi\Annotations\PathItem;
use OpenApi\Context;
use OpenApi\Generator;
-use OpenApi\Processors\BuildPaths;
+use Psr\Log\LoggerInterface;
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\OpenApiBuilder;
+use Radebatz\OpenApi\Extras\Annotations\Middleware;
use Symfony\Component\Finder\Finder;
/**
@@ -53,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,
];
}
@@ -118,12 +111,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 +174,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':
@@ -200,65 +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);
}
-
- /**
- * 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));
-
- 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/CachingTest.php b/tests/Laravel/CachingTest.php
index 319727e..883071f 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],
@@ -31,6 +31,7 @@ public function reloadTests()
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/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/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());
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()