From 2953a79caecc2fd1e81cfbd6ea5dc8a770f78ab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frederic=20G=2E=20=C3=98stby?= Date: Thu, 23 Nov 2023 22:32:17 +0100 Subject: [PATCH] It is now possible to generate 3.0.0 and 3.1.0 specs --- .php-cs-fixer.php | 2 ++ CHANGELOG.md | 20 ++++++++++++ src/console/commands/GenerateRoutes.php | 15 +++------ src/console/commands/GenerateSpec.php | 41 +++++++++++++++--------- src/generators/routing/Cached.php | 3 +- src/generators/routing/Generator.php | 42 +++++++++---------------- src/generators/routing/Runtime.php | 7 ++--- src/generators/spec/Generator.php | 9 +++--- 8 files changed, 76 insertions(+), 63 deletions(-) diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 9eb35dc..e418b25 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -15,6 +15,7 @@ 'concat_space' => ['spacing' => 'one'], 'constant_case' => true, 'dir_constant' => true, + 'curly_braces_position' => true, 'elseif' => true, 'encoding' => true, 'full_opening_tag' => true, @@ -83,6 +84,7 @@ 'single_line_after_imports' => true, 'single_line_comment_style' => ['comment_types' => ['hash']], 'single_quote' => true, + 'single_space_around_construct' => true, 'space_after_semicolon' => true, 'standardize_not_equals' => true, 'switch_case_semicolon_to_colon' => true, diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f43ab4..49a3a37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +### 2.1.0 (2023-11-23) + +#### New + +* Now possible to specify the OpenApi version when generating the spec (3.0.0 or 3.1.0). + +#### Fixed + +* The spec generator now supports the new Mako 10 directory structure as well as the legacy structure. + +-------------------------------------------------------- + +### 2.0.0 (2023-11-23) + +#### Changes + +* Bumped requirements to Mako 10+ and PHP 8.1+ + +-------------------------------------------------------- + ### 1.2.4 (2023-04-18) #### Fixed diff --git a/src/console/commands/GenerateRoutes.php b/src/console/commands/GenerateRoutes.php index c090a90..ce51678 100644 --- a/src/console/commands/GenerateRoutes.php +++ b/src/console/commands/GenerateRoutes.php @@ -37,8 +37,7 @@ public function __construct( Output $output, protected Application $app, protected FileSystem $fileSystem - ) - { + ) { parent::__construct($input, $output); } @@ -47,8 +46,7 @@ public function __construct( */ public function getArguments(): array { - return - [ + return [ new Argument('-i|--input', 'The path to the OpenApi specification file you want to generate routes from.', Argument::IS_OPTIONAL), new Argument('-o|--output', 'The path to where you want to store the generated route file.', Argument::IS_OPTIONAL), ]; @@ -69,19 +67,16 @@ public function execute(?string $input = null, ?string $output = null): int { $input = $this->getInputFilePath($input); - if(!$this->fileSystem->has($input)) - { + if (!$this->fileSystem->has($input)) { $this->error("The [ {$input} ] specification file does not exist."); return static::STATUS_ERROR; } - if($output === null) - { + if ($output === null) { $path = "{$this->app->getPath()}/routing"; } - else - { + else { $path = rtrim($output, '/\\'); } diff --git a/src/console/commands/GenerateSpec.php b/src/console/commands/GenerateSpec.php index 1ee3642..8f9c83e 100644 --- a/src/console/commands/GenerateSpec.php +++ b/src/console/commands/GenerateSpec.php @@ -14,6 +14,7 @@ use mako\file\FileSystem; use mako\openapi\generators\spec\Generator as SpecGenerator; use mako\reactor\Command; +use OpenApi\Annotations\OpenApi; use function dirname; use function strpos; @@ -36,8 +37,7 @@ public function __construct( Output $output, protected Application $app, protected FileSystem $fileSystem - ) - { + ) { parent::__construct($input, $output); } @@ -46,13 +46,13 @@ public function __construct( */ public function getArguments(): array { - return - [ + return [ new Argument('-f|--filename', 'The filename you want to use for the documentation (default: openapi).', Argument::IS_OPTIONAL), new Argument('-s|--scan', 'The director(y|ies) you want to scan (default: app).', Argument::IS_ARRAY | Argument::IS_OPTIONAL), new Argument('-e|--exclude', 'The director(y|ies) or filename(s) to exclude (as absolute or relative paths).', Argument::IS_ARRAY | Argument::IS_OPTIONAL), new Argument('-p|--pattern', 'File pattern to scan (default: *.php).', Argument::IS_OPTIONAL), new Argument('-o|--output', 'The output directory where you want to save the OpenAPI documentation (default: project root).', Argument::IS_OPTIONAL), + new Argument('-v|--version', 'The OpenAPI version to use (default: ' . OpenApi::DEFAULT_VERSION . ').', Argument::IS_OPTIONAL), ]; } @@ -61,17 +61,20 @@ public function getArguments(): array */ protected function getScanPaths(?array $paths): array { - if(empty($paths)) - { - return [$this->app->getPath() . '/controllers', $this->app->getPath() . '/models']; + if (empty($paths)) { + if ($this->fileSystem->has("{$this->app->getPath()}/controllers")) { + $controllers = "{$this->app->getPath()}/controllers"; + } else { + $controllers = "{$this->app->getPath()}/http/controllers"; + } + + return [$controllers, "{$this->app->getPath()}'/models"]; } $root = dirname($this->app->getPath()); - foreach($paths as $key => $value) - { - if(strpos($value, DIRECTORY_SEPARATOR) !== 0) - { + foreach ($paths as $key => $value) { + if (strpos($value, DIRECTORY_SEPARATOR) !== 0) { $paths[$key] = "{$root}/{$value}"; } } @@ -86,8 +89,7 @@ protected function getOutputPath(?string $path): string { $root = dirname($this->app->getPath()); - if(empty($path)) - { + if (empty($path)) { return $root; } @@ -97,11 +99,20 @@ protected function getOutputPath(?string $path): string /** * Generates the API documentation. */ - public function execute(string $filename = 'openapi', ?array $scan = null, ?array $exclude = null, ?string $pattern = null, ?string $output = null): void + public function execute(string $filename = 'openapi', ?array $scan = null, ?array $exclude = null, ?string $pattern = null, ?string $output = null, string $version = OpenApi::DEFAULT_VERSION): void { $output = "{$this->getOutputPath($output)}/{$filename}.yml"; - (new SpecGenerator($this->fileSystem, $output, $this->getScanPaths($scan), $exclude, $pattern))->generate(); + $generator = new SpecGenerator( + $this->fileSystem, + $output, + $this->getScanPaths($scan), + $exclude, + $pattern, + $version + ); + + $generator->generate(); $this->write("Successfully wrote OpenApi specification to [ {$output} ]."); } diff --git a/src/generators/routing/Cached.php b/src/generators/routing/Cached.php index cdae5bf..098de33 100644 --- a/src/generators/routing/Cached.php +++ b/src/generators/routing/Cached.php @@ -46,8 +46,7 @@ protected function registerRoute(string $method, string $path, array|Closure|str $registerPatterns = ''; - if(!empty($patterns)) - { + if (!empty($patterns)) { $patterns = var_export($patterns, true); $registerPatterns = "->patterns({$patterns})"; diff --git a/src/generators/routing/Generator.php b/src/generators/routing/Generator.php index 7ee84bd..aecc478 100644 --- a/src/generators/routing/Generator.php +++ b/src/generators/routing/Generator.php @@ -30,16 +30,14 @@ abstract class Generator [ // String formats - 'string' => - [ + 'string' => [ 'no-dot' => '[^/.]++', 'uuid' => '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}', ], // Integer formats - 'integer' => - [ + 'integer' => [ '_' => '-?[0-9]+', 'auto-increment' => '[1-9][0-9]{0,}', ], @@ -55,10 +53,8 @@ public function mergeParameters(array $pathParameters, array $operationParameter { $merged = []; - foreach([$pathParameters, $operationParameters] as $parameters) - { - foreach($parameters as $parameter) - { + foreach ([$pathParameters, $operationParameters] as $parameters) { + foreach ($parameters as $parameter) { $merged[$parameter->name] = $parameter; } } @@ -71,8 +67,7 @@ public function mergeParameters(array $pathParameters, array $operationParameter */ protected function getRouteAction(string $operationId): array|string { - if(strpos($operationId, '::') !== false) - { + if (strpos($operationId, '::') !== false) { return explode('::', $operationId, 2); } @@ -87,10 +82,8 @@ protected function getRouteAction(string $operationId): array|string */ protected function getRoutePath(string $path, array $parameters): string { - foreach($parameters as $parameter) - { - if($parameter->in === 'path' && $parameter->required === false) - { + foreach ($parameters as $parameter) { + if ($parameter->in === 'path' && $parameter->required === false) { $path = str_replace("{{$parameter->name}}", "{{$parameter->name}}?", $path); } } @@ -107,16 +100,12 @@ protected function getRoutePatterns(array $parameters): array { $patterns = []; - foreach($parameters as $parameter) - { - if($parameter->in === 'path') - { - if(isset($this->parameterPatterns[$parameter->schema->type][$parameter->schema->format ?? '_'])) - { + foreach ($parameters as $parameter) { + if ($parameter->in === 'path') { + if (isset($this->parameterPatterns[$parameter->schema->type][$parameter->schema->format ?? '_'])) { $patterns[$parameter->name] = $this->parameterPatterns[$parameter->schema->type][$parameter->schema->format ?? '_']; } - elseif($parameter->schema->format !== null && str_starts_with($parameter->schema->format, 'regex:')) - { + elseif ($parameter->schema->format !== null && str_starts_with($parameter->schema->format, 'regex:')) { [, $regex] = explode(':', $parameter->schema->format); $patterns[$parameter->name] = $regex; @@ -141,12 +130,9 @@ protected function generateRoutes(SpecObjectInterface $openApi): void { $methods = ['get', 'post', 'put', 'patch', 'delete']; - foreach($openApi->paths as $path => $definition) - { - foreach($methods as $method) - { - if($definition->{$method} !== null) - { + foreach ($openApi->paths as $path => $definition) { + foreach ($methods as $method) { + if ($definition->{$method} !== null) { $parameters = $this->mergeParameters($definition->parameters, $definition->{$method}->parameters); $this->registerRoute( diff --git a/src/generators/routing/Runtime.php b/src/generators/routing/Runtime.php index 25093e9..9466324 100644 --- a/src/generators/routing/Runtime.php +++ b/src/generators/routing/Runtime.php @@ -20,8 +20,8 @@ class Runtime extends Generator */ public function __construct( protected Routes $routes - ) - {} + ) { + } /** * {@inheritDoc} @@ -31,8 +31,7 @@ protected function registerRoute(string $method, string $path, array|Closure|str /** @var \mako\http\routing\Route $route */ $route = $this->routes->{$method}($path, $action, $name); - if(!empty($patterns)) - { + if (!empty($patterns)) { $route->patterns($patterns); } } diff --git a/src/generators/spec/Generator.php b/src/generators/spec/Generator.php index 5242ec3..494c382 100644 --- a/src/generators/spec/Generator.php +++ b/src/generators/spec/Generator.php @@ -26,9 +26,10 @@ public function __construct( protected string $outputFile, protected $directory, protected $exclude = null, - protected ?string $pattern = null - ) - {} + protected ?string $pattern = null, + protected string $version = OpenApi::DEFAULT_VERSION + ) { + } /** * Returns a finder instance. @@ -43,7 +44,7 @@ protected function getFinder(): Finder */ protected function getGenerator(): ?OpenApi { - return OpenApiGenerator::scan($this->getFinder(), ['version' => OpenApi::DEFAULT_VERSION]); + return OpenApiGenerator::scan($this->getFinder(), ['version' => $this->version]); } /**