diff --git a/README.md b/README.md index 1cd2090b..7eeb62ce 100644 --- a/README.md +++ b/README.md @@ -309,6 +309,81 @@ Provide custom database table column name in case of relationship column. This w - x-fk-column-name: redelivery_of # this will create `redelivery_of` column instead of `redelivery_of_id` ``` +### `x-route` + +To customize route (controller ID/action ID) for a path, use custom key `x-route` with value `/`. It can be used for non-crud paths. It must be used under HTTP method key but not +directly under the `paths` key of OpenAPI spec. Example: + +```yaml +paths: + /payments/invoice/{invoice}: + parameters: + - name: invoice + in: path + description: lorem ipsum + required: true + schema: + type: integer + post: + x-route: 'payments/invoice' + summary: Pay Invoice + description: Pay for Invoice with given invoice number + requestBody: + description: Record new payment for an invoice + content: + application/json: + schema: + $ref: '#/components/schemas/Payments' + required: true + responses: + '200': + description: Successfully paid the invoice + content: + application/json: + schema: + $ref: '#/components/schemas/Success' +``` + +It won't generate `actionCreateInvoice` in `PaymentsController.php` file, but will generate `actionInvoice` instead in +same file. + +Generated URL rules config for above is (in `urls.rest.php` or pertinent file): +```php + 'POST payments/invoice/' => 'payments/invoice', + 'payments/invoice/' => 'payments/options', +``` + +Also, if same action is needed for HTTP GET and POST then use same value for `x-route`. Example: + +```yaml +paths: + /a1/b1: + get: + x-route: 'abc/xyz' + operationId: opnid1 + summary: List + description: Lists + responses: + '200': + description: The Response + post: + x-route: 'abc/xyz' + operationId: opnid2 + summary: create + description: create + responses: + '200': + description: The Response +``` + +Generated URL rules config for above is (in `urls.rest.php` or pertinent file): +```php + 'GET a1/b1' => 'abc/xyz', + 'POST a1/b1' => 'abc/xyz', + 'a1/b1' => 'abc/options', +``` +`x-route` does not support [Yii Modules](https://www.yiiframework.com/doc/guide/2.0/en/structure-modules). + ## Many-to-Many relation definition There are two ways for define many-to-many relations: diff --git a/src/generator/ApiGenerator.php b/src/generator/ApiGenerator.php index f930f949..fe135c5d 100644 --- a/src/generator/ApiGenerator.php +++ b/src/generator/ApiGenerator.php @@ -7,9 +7,6 @@ namespace cebe\yii2openapi\generator; -use yii\db\mysql\Schema as MySqlSchema; -use SamIT\Yii2\MariaDb\Schema as MariaDbSchema; -use yii\db\pgsql\Schema as PgSqlSchema; use cebe\openapi\Reader; use cebe\openapi\spec\OpenApi; use cebe\yii2openapi\lib\Config; @@ -20,9 +17,13 @@ use cebe\yii2openapi\lib\generators\RestActionGenerator; use cebe\yii2openapi\lib\generators\TransformersGenerator; use cebe\yii2openapi\lib\generators\UrlRulesGenerator; +use cebe\yii2openapi\lib\items\FractalAction; +use cebe\yii2openapi\lib\items\RestAction; use cebe\yii2openapi\lib\PathAutoCompletion; use cebe\yii2openapi\lib\SchemaToDatabase; use Yii; +use yii\db\mysql\Schema as MySqlSchema; +use yii\db\pgsql\Schema as PgSqlSchema; use yii\gii\CodeFile; use yii\gii\Generator; use yii\helpers\Html; @@ -473,6 +474,7 @@ public function generate():array $urlRulesGenerator = Yii::createObject(UrlRulesGenerator::class, [$config, $actions]); $files = $urlRulesGenerator->generate(); + $actions = static::removeDuplicateActions($actions); // in case of non-crud actions having custom route `x-route` set $controllersGenerator = Yii::createObject(ControllersGenerator::class, [$config, $actions]); $files->merge($controllersGenerator->generate()); @@ -521,4 +523,31 @@ public static function isMariaDb():bool { return strpos(Yii::$app->db->schema->getServerVersion(), 'MariaDB') !== false; } + + /** + * @param RestAction[]|FractalAction[] $actions + * @return RestAction[]|FractalAction[] + * https://github.com/cebe/yii2-openapi/issues/84 + */ + public static function removeDuplicateActions(array $actions): array + { + $actions = array_filter($actions, function ($action) { + /** @var $action RestAction|FractalAction */ + if ($action instanceof RestAction && $action->isDuplicate) { + return false; + } + return true; + }); + + $actions = array_map(function ($action) { + /** @var $action RestAction|FractalAction */ + if ($action instanceof RestAction && $action->zeroParams) { + $action->idParam = null; + $action->params = []; + } + return $action; + }, $actions); + + return $actions; + } } diff --git a/src/generator/default/urls.php b/src/generator/default/urls.php index e666a428..302ad533 100644 --- a/src/generator/default/urls.php +++ b/src/generator/default/urls.php @@ -1,3 +1,8 @@ + /** @@ -5,5 +10,6 @@ * * This file is auto generated. */ - + return ; diff --git a/src/lib/CustomSpecAttr.php b/src/lib/CustomSpecAttr.php index 7e02a85d..1c87e4db 100644 --- a/src/lib/CustomSpecAttr.php +++ b/src/lib/CustomSpecAttr.php @@ -40,4 +40,9 @@ class CustomSpecAttr * Foreign key column name. See README for usage docs */ public const FK_COLUMN_NAME = 'x-fk-column-name'; + + /** + * Custom route (controller ID/action ID) instead of auto-generated. See README for usage docs. https://github.com/cebe/yii2-openapi/issues/144 + */ + public const ROUTE = 'x-route'; } diff --git a/src/lib/generators/ControllersGenerator.php b/src/lib/generators/ControllersGenerator.php index 366f5532..bd749c9f 100644 --- a/src/lib/generators/ControllersGenerator.php +++ b/src/lib/generators/ControllersGenerator.php @@ -129,6 +129,7 @@ protected function makeCustomController( $params = array_map(static function ($param) { return ['name' => $param]; }, $action->getParamNames()); + $reflection->addMethod( $action->actionMethodName, $params, diff --git a/src/lib/generators/JsonActionGenerator.php b/src/lib/generators/JsonActionGenerator.php index 696f7974..3cc2de2a 100644 --- a/src/lib/generators/JsonActionGenerator.php +++ b/src/lib/generators/JsonActionGenerator.php @@ -26,8 +26,12 @@ class JsonActionGenerator extends RestActionGenerator * @throws \yii\base\InvalidConfigException * @throws \cebe\openapi\exceptions\UnresolvableReferenceException */ - protected function prepareAction(string $method, Operation $operation, RouteData $routeData):BaseObject - { + protected function prepareAction( + string $method, + Operation $operation, + RouteData $routeData, + ?string $customRoute = null + ): BaseObject { $actionType = $this->resolveActionType($routeData, $method); $modelClass = ResponseSchema::guessModelClass($operation, $actionType); $expectedRelations = in_array($actionType, ['list', 'view']) diff --git a/src/lib/generators/RestActionGenerator.php b/src/lib/generators/RestActionGenerator.php index daedd20f..b8d5998c 100644 --- a/src/lib/generators/RestActionGenerator.php +++ b/src/lib/generators/RestActionGenerator.php @@ -11,6 +11,7 @@ use cebe\openapi\spec\PathItem; use cebe\openapi\spec\Reference; use cebe\yii2openapi\lib\Config; +use cebe\yii2openapi\lib\CustomSpecAttr; use cebe\yii2openapi\lib\items\RestAction; use cebe\yii2openapi\lib\items\RouteData; use cebe\yii2openapi\lib\openapi\ResponseSchema; @@ -58,6 +59,7 @@ public function generate():array return array_merge(...$actions); } + private $allCustomRoutes = []; /** * @param string $path * @param \cebe\openapi\spec\PathItem $pathItem @@ -71,7 +73,24 @@ protected function resolvePath(string $path, PathItem $pathItem):array $routeData = Yii::createObject(RouteData::class, [$pathItem, $path, $this->config->urlPrefixes]); foreach ($pathItem->getOperations() as $method => $operation) { - $actions[] = $this->prepareAction($method, $operation, $routeData); + $customRoute = null; + if (isset($operation->{CustomSpecAttr::ROUTE})) { # https://github.com/cebe/yii2-openapi/issues/144 + $customRoute = $operation->{CustomSpecAttr::ROUTE}; + } + + $action = $this->prepareAction($method, $operation, $routeData, $customRoute); + if ($customRoute !== null) { + if (in_array($customRoute, array_keys($this->allCustomRoutes))) { + $action->isDuplicate = true; + if ($action->params !== $this->allCustomRoutes[$customRoute]->params) { + $this->allCustomRoutes[$customRoute]->zeroParams = true; + } + } else { + $action->isDuplicate = false; + $this->allCustomRoutes[$customRoute] = $action; + } + } + $actions[] = $action; } return $actions; } @@ -84,8 +103,12 @@ protected function resolvePath(string $path, PathItem $pathItem):array * @throws \cebe\openapi\exceptions\UnresolvableReferenceException * @throws \yii\base\InvalidConfigException */ - protected function prepareAction(string $method, Operation $operation, RouteData $routeData):BaseObject - { + protected function prepareAction( + string $method, + Operation $operation, + RouteData $routeData, + ?string $customRoute = null + ): BaseObject { $actionType = $this->resolveActionType($routeData, $method); $modelClass = ResponseSchema::guessModelClass($operation, $actionType); $responseWrapper = ResponseSchema::findResponseWrapper($operation, $modelClass); @@ -106,12 +129,19 @@ protected function prepareAction(string $method, Operation $operation, RouteData $controllerId = isset($this->config->controllerModelMap[$modelClass]) ? Inflector::camel2id($this->config->controllerModelMap[$modelClass]) : Inflector::camel2id($modelClass); + } elseif (!empty($customRoute)) { + $controllerId = explode('/', $customRoute)[0]; } else { $controllerId = $routeData->controller; } + $action = Inflector::camel2id($routeData->action); + if (!empty($customRoute)) { + $actionType = ''; + $action = explode('/', $customRoute)[1]; + } return Yii::createObject(RestAction::class, [ [ - 'id' => trim("$actionType{$routeData->action}", '-'), + 'id' => trim("$actionType-$action", '-'), 'controllerId' => $controllerId, 'urlPath' => $routeData->path, 'requestMethod' => strtoupper($method), diff --git a/src/lib/items/RestAction.php b/src/lib/items/RestAction.php index 6852fafc..5192997a 100644 --- a/src/lib/items/RestAction.php +++ b/src/lib/items/RestAction.php @@ -68,13 +68,32 @@ final class RestAction extends BaseObject */ public $responseWrapper; + /** + * @var bool + * @see $isDuplicate + * https://github.com/cebe/yii2-openapi/issues/84 + * see `x-route` in README.md + * Used for generating only one action for paths like: `GET /calendar/domains` and `GET /calendar/domains/{id}` given that they have same `x-route`. + * If duplicates routes have same params then `false`, else action is generated with no (0) params `true` + */ + public $zeroParams = false; + + /** + * @var bool + * https://github.com/cebe/yii2-openapi/issues/84 + * Generate only one action for paths like: `GET /calendar/domains` and `GET /calendar/domains/{id}` given that they have same `x-route`. + * @see $zeroParams + * see `x-route` in README.md + */ + public $isDuplicate = false; + public function getRoute():string { if ($this->prefix && !empty($this->prefixSettings)) { $prefix = $this->prefixSettings['module'] ?? $this->prefix; - return trim($prefix, '/').'/'.$this->controllerId.'/'.$this->id; + return trim($prefix, '/') . '/' . $this->controllerId . '/' . $this->id; } - return $this->controllerId.'/'.$this->id; + return $this->controllerId . '/' . $this->id; } public function getOptionsRoute():string diff --git a/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/config/urls.rest.php b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/config/urls.rest.php new file mode 100644 index 00000000..1d39a048 --- /dev/null +++ b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/config/urls.rest.php @@ -0,0 +1,25 @@ + 'fruits/mango', + 'GET fruits/mango' => 'fruit/mango', + 'POST fruits/mango' => 'fruit/create-mango', + 'GET animal/goat' => 'animal/goat', + 'POST animal/goat' => 'animal/create-goat', + 'POST payments/invoice/' => 'payments/invoice', + 'GET payments/invoice-payment' => 'payment/invoice-payment', + 'GET a1/b1' => 'abc/xyz', + 'POST a1/b1' => 'abc/xyz', + 'GET aa2/bb2' => 'payments/xyz2', + 'fruit/mango' => 'fruits/options', + 'fruits/mango' => 'fruit/options', + 'animal/goat' => 'animal/options', + 'payments/invoice/' => 'payments/options', + 'payments/invoice-payment' => 'payment/options', + 'a1/b1' => 'abc/options', + 'aa2/bb2' => 'payments/options', +]; diff --git a/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/AbcController.php b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/AbcController.php new file mode 100644 index 00000000..833d931e --- /dev/null +++ b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/AbcController.php @@ -0,0 +1,20 @@ + [ + 'class' => \yii\rest\OptionsAction::class, + ], + ]; + } + + /** + * Checks the privilege of the current user. + * + * This method checks whether the current user has the privilege + * to run the specified action against the specified data model. + * If the user does not have access, a [[ForbiddenHttpException]] should be thrown. + * + * @param string $action the ID of the action to be executed + * @param object $model the model to be accessed. If null, it means no specific model is being accessed. + * @param array $params additional parameters + * @throws \yii\web\ForbiddenHttpException if the user does not have access + */ + abstract public function checkAccess($action, $model = null, $params = []); + + abstract public function actionXyz(); + +} diff --git a/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/AnimalController.php b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/AnimalController.php new file mode 100644 index 00000000..f88ac969 --- /dev/null +++ b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/AnimalController.php @@ -0,0 +1,34 @@ + [ + 'class' => \yii\rest\OptionsAction::class, + ], + ]; + } + + /** + * Checks the privilege of the current user. + * + * This method checks whether the current user has the privilege + * to run the specified action against the specified data model. + * If the user does not have access, a [[ForbiddenHttpException]] should be thrown. + * + * @param string $action the ID of the action to be executed + * @param object $model the model to be accessed. If null, it means no specific model is being accessed. + * @param array $params additional parameters + * @throws \yii\web\ForbiddenHttpException if the user does not have access + */ + abstract public function checkAccess($action, $model = null, $params = []); + + abstract public function actionGoat(); + + abstract public function actionCreateGoat(); + +} diff --git a/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/FruitController.php b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/FruitController.php new file mode 100644 index 00000000..5cef0ed5 --- /dev/null +++ b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/FruitController.php @@ -0,0 +1,34 @@ + [ + 'class' => \yii\rest\OptionsAction::class, + ], + ]; + } + + /** + * Checks the privilege of the current user. + * + * This method checks whether the current user has the privilege + * to run the specified action against the specified data model. + * If the user does not have access, a [[ForbiddenHttpException]] should be thrown. + * + * @param string $action the ID of the action to be executed + * @param object $model the model to be accessed. If null, it means no specific model is being accessed. + * @param array $params additional parameters + * @throws \yii\web\ForbiddenHttpException if the user does not have access + */ + abstract public function checkAccess($action, $model = null, $params = []); + + abstract public function actionMango(); + + abstract public function actionCreateMango(); + +} diff --git a/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/FruitsController.php b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/FruitsController.php new file mode 100644 index 00000000..01549012 --- /dev/null +++ b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/FruitsController.php @@ -0,0 +1,32 @@ + [ + 'class' => \yii\rest\OptionsAction::class, + ], + ]; + } + + /** + * Checks the privilege of the current user. + * + * This method checks whether the current user has the privilege + * to run the specified action against the specified data model. + * If the user does not have access, a [[ForbiddenHttpException]] should be thrown. + * + * @param string $action the ID of the action to be executed + * @param object $model the model to be accessed. If null, it means no specific model is being accessed. + * @param array $params additional parameters + * @throws \yii\web\ForbiddenHttpException if the user does not have access + */ + abstract public function checkAccess($action, $model = null, $params = []); + + abstract public function actionMango(); + +} diff --git a/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/PaymentController.php b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/PaymentController.php new file mode 100644 index 00000000..4d39cdb8 --- /dev/null +++ b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/PaymentController.php @@ -0,0 +1,32 @@ + [ + 'class' => \yii\rest\OptionsAction::class, + ], + ]; + } + + /** + * Checks the privilege of the current user. + * + * This method checks whether the current user has the privilege + * to run the specified action against the specified data model. + * If the user does not have access, a [[ForbiddenHttpException]] should be thrown. + * + * @param string $action the ID of the action to be executed + * @param object $model the model to be accessed. If null, it means no specific model is being accessed. + * @param array $params additional parameters + * @throws \yii\web\ForbiddenHttpException if the user does not have access + */ + abstract public function checkAccess($action, $model = null, $params = []); + + abstract public function actionInvoicePayment(); + +} diff --git a/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/PaymentsController.php b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/PaymentsController.php new file mode 100644 index 00000000..869d64e6 --- /dev/null +++ b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/app/controllers/base/PaymentsController.php @@ -0,0 +1,34 @@ + [ + 'class' => \yii\rest\OptionsAction::class, + ], + ]; + } + + /** + * Checks the privilege of the current user. + * + * This method checks whether the current user has the privilege + * to run the specified action against the specified data model. + * If the user does not have access, a [[ForbiddenHttpException]] should be thrown. + * + * @param string $action the ID of the action to be executed + * @param object $model the model to be accessed. If null, it means no specific model is being accessed. + * @param array $params additional parameters + * @throws \yii\web\ForbiddenHttpException if the user does not have access + */ + abstract public function checkAccess($action, $model = null, $params = []); + + abstract public function actionInvoice($invoice); + + abstract public function actionXyz2(); + +} diff --git a/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/index.php b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/index.php new file mode 100644 index 00000000..d461ae44 --- /dev/null +++ b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/index.php @@ -0,0 +1,13 @@ + '@specs/issue_fix/144_methods_naming_for_non_crud_actions/index.yaml', + 'generateUrls' => true, + 'generateModels' => false, + 'excludeModels' => [ + 'Error', + ], + 'generateControllers' => true, + 'generateMigrations' => false, + 'generateModelFaker' => false, // `generateModels` must be `true` in order to use `generateModelFaker` as `true` +]; diff --git a/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/index.yaml b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/index.yaml new file mode 100644 index 00000000..43435cc4 --- /dev/null +++ b/tests/specs/issue_fix/144_methods_naming_for_non_crud_actions/index.yaml @@ -0,0 +1,156 @@ +openapi: 3.0.3 + +info: + title: 'Custom route for path' + version: 1.0.0 + +tags: + - name: Payments + description: Pay or receive payments for your products from different channels + externalDocs: + description: Find out more + url: https://developer.adiuta.com/book/payments +paths: + /fruit/mango: + get: + x-route: fruits/mango + operationId: opnid91 + summary: Lorem ipsum + description: Lorem ipsum description + responses: + '200': + description: The Response + + + /fruits/mango: + get: + operationId: opnid81 + summary: Lorem ipsum + description: Lorem ipsum description + responses: + '200': + description: The Response + post: + operationId: opnid9 + summary: Lorem ipsum + description: Lorem ipsum description + responses: + '200': + description: The Response + + /animal/goat: + get: + operationId: opnid8 + summary: Lorem ipsum + description: Lorem ipsum description + responses: + '200': + description: The Response + post: + operationId: opnid92 + summary: Lorem ipsum + description: Lorem ipsum description + responses: + '200': + description: The Response + + /payments/invoice/{invoice}: + parameters: + - name: invoice + in: path + description: lorem ipsum + required: true + schema: + type: integer + post: + x-route: 'payments/invoice' + summary: Pay Invoice + description: Pay for Invoice with given invoice number + requestBody: + description: Record new payment for an invoice + content: + application/json: + schema: + $ref: '#/components/schemas/Payments' + required: true + responses: + '200': + description: Successfully paid the invoice + content: + application/json: + schema: + $ref: '#/components/schemas/Success' + + /payments/invoice-payment: + get: + operationId: opnid + summary: List + description: Lists + responses: + '200': + description: The Response + + /a1/b1: + get: + x-route: 'abc/xyz' + operationId: opnid5 + summary: List + description: Lists + responses: + '200': + description: The Response + post: + x-route: 'abc/xyz' + operationId: opnid23 + summary: List + description: Lists + responses: + '200': + description: The Response + + /aa2/bb2: + get: + x-route: 'payments/xyz2' + operationId: opnid7 + summary: List + description: Lists + responses: + '200': + description: The Response + +components: + schemas: + Payments: + required: + - reference + - amount + - currency + properties: + invoice_number: + type: string + amount: + type: integer + format: int64 + currency: + type: string + + Success: + required: + - success + - message + properties: + success: + type: boolean + message: + type: string + + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string \ No newline at end of file diff --git a/tests/specs/issue_fix/158_bug_giiapi_generated_rules_enum_with_trim/index.php b/tests/specs/issue_fix/158_bug_giiapi_generated_rules_enum_with_trim/index.php index 515b362c..70e43b74 100644 --- a/tests/specs/issue_fix/158_bug_giiapi_generated_rules_enum_with_trim/index.php +++ b/tests/specs/issue_fix/158_bug_giiapi_generated_rules_enum_with_trim/index.php @@ -9,6 +9,6 @@ ], 'generateControllers' => false, 'generateMigrations' => false, - 'generateModelFaker' => true, // `generateModels` must be `true` in orde to use `generateModelFaker` as `true` + 'generateModelFaker' => true, // `generateModels` must be `true` in order to use `generateModelFaker` as `true` ]; diff --git a/tests/specs/issue_fix/159_bug_giiapi_generated_rules_emailid/index.php b/tests/specs/issue_fix/159_bug_giiapi_generated_rules_emailid/index.php index b66f036b..645671f2 100644 --- a/tests/specs/issue_fix/159_bug_giiapi_generated_rules_emailid/index.php +++ b/tests/specs/issue_fix/159_bug_giiapi_generated_rules_emailid/index.php @@ -9,6 +9,6 @@ ], 'generateControllers' => false, 'generateMigrations' => false, - 'generateModelFaker' => true, // `generateModels` must be `true` in orde to use `generateModelFaker` as `true` + 'generateModelFaker' => true, // `generateModels` must be `true` in order to use `generateModelFaker` as `true` ]; diff --git a/tests/specs/issue_fix/162_bug_dollarref_with_x_faker/162_bug_dollarref_with_x_faker.php b/tests/specs/issue_fix/162_bug_dollarref_with_x_faker/162_bug_dollarref_with_x_faker.php index 19951cd4..8e6ca8d0 100644 --- a/tests/specs/issue_fix/162_bug_dollarref_with_x_faker/162_bug_dollarref_with_x_faker.php +++ b/tests/specs/issue_fix/162_bug_dollarref_with_x_faker/162_bug_dollarref_with_x_faker.php @@ -9,5 +9,5 @@ ], 'generateControllers' => false, 'generateMigrations' => false, - 'generateModelFaker' => true, // `generateModels` must be `true` in orde to use `generateModelFaker` as `true` + 'generateModelFaker' => true, // `generateModels` must be `true` in order to use `generateModelFaker` as `true` ]; diff --git a/tests/specs/issue_fix/163_generator_crash_when_using_reference_inside_an_object/index.php b/tests/specs/issue_fix/163_generator_crash_when_using_reference_inside_an_object/index.php index 784db168..504db8f9 100644 --- a/tests/specs/issue_fix/163_generator_crash_when_using_reference_inside_an_object/index.php +++ b/tests/specs/issue_fix/163_generator_crash_when_using_reference_inside_an_object/index.php @@ -9,6 +9,6 @@ ], 'generateControllers' => true, 'generateMigrations' => true, - 'generateModelFaker' => true, // `generateModels` must be `true` in orde to use `generateModelFaker` as `true` + 'generateModelFaker' => true, // `generateModels` must be `true` in order to use `generateModelFaker` as `true` ]; diff --git a/tests/specs/issue_fix/172_schemayaml_requestbody_has_no_effect/index.php b/tests/specs/issue_fix/172_schemayaml_requestbody_has_no_effect/index.php index 3debbb46..91969e28 100644 --- a/tests/specs/issue_fix/172_schemayaml_requestbody_has_no_effect/index.php +++ b/tests/specs/issue_fix/172_schemayaml_requestbody_has_no_effect/index.php @@ -9,6 +9,6 @@ ], 'generateControllers' => true, 'generateMigrations' => false, - 'generateModelFaker' => false, // `generateModels` must be `true` in orde to use `generateModelFaker` as `true` + 'generateModelFaker' => false, // `generateModels` must be `true` in order to use `generateModelFaker` as `true` ]; diff --git a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/index.php b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/index.php index 3ccbc836..43e214b1 100644 --- a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/index.php +++ b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/index.php @@ -9,6 +9,6 @@ ], 'generateControllers' => true, 'generateMigrations' => true, - 'generateModelFaker' => true, // `generateModels` must be `true` in orde to use `generateModelFaker` as `true` + 'generateModelFaker' => true, // `generateModels` must be `true` in order to use `generateModelFaker` as `true` ]; diff --git a/tests/specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/app/config/urls.rest.php b/tests/specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/app/config/urls.rest.php new file mode 100644 index 00000000..9bb87c11 --- /dev/null +++ b/tests/specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/app/config/urls.rest.php @@ -0,0 +1,14 @@ + 'calendar/domains', + 'GET calendar/domains/' => 'calendar/domains', + 'GET calendar/domains//' => 'calendar/domains', + 'calendar/domains' => 'calendar/options', + 'calendar/domains/' => 'calendar/options', + 'calendar/domains//' => 'calendar/options', +]; diff --git a/tests/specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/app/controllers/CalendarController.php b/tests/specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/app/controllers/CalendarController.php new file mode 100644 index 00000000..7096a165 --- /dev/null +++ b/tests/specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/app/controllers/CalendarController.php @@ -0,0 +1,20 @@ + [ + 'class' => \yii\rest\OptionsAction::class, + ], + ]; + } + + /** + * Checks the privilege of the current user. + * + * This method checks whether the current user has the privilege + * to run the specified action against the specified data model. + * If the user does not have access, a [[ForbiddenHttpException]] should be thrown. + * + * @param string $action the ID of the action to be executed + * @param object $model the model to be accessed. If null, it means no specific model is being accessed. + * @param array $params additional parameters + * @throws \yii\web\ForbiddenHttpException if the user does not have access + */ + abstract public function checkAccess($action, $model = null, $params = []); + + abstract public function actionDomains(); + +} diff --git a/tests/specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/index.php b/tests/specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/index.php new file mode 100644 index 00000000..6d88068a --- /dev/null +++ b/tests/specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/index.php @@ -0,0 +1,13 @@ + '@specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/index.yaml', + 'generateUrls' => true, + 'generateModels' => false, + 'excludeModels' => [ + 'Error', + ], + 'generateControllers' => true, + 'generateMigrations' => false, + 'generateModelFaker' => false, // `generateModels` must be `true` in order to use `generateModelFaker` as `true` +]; diff --git a/tests/specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/index.yaml b/tests/specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/index.yaml new file mode 100644 index 00000000..681ae664 --- /dev/null +++ b/tests/specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/index.yaml @@ -0,0 +1,99 @@ +openapi: 3.0.3 + +info: + title: 'Custom route for path' + version: 1.0.0 + +tags: + - name: Payments + description: Pay or receive payments for your products from different channels + externalDocs: + description: Find out more + url: https://developer.adiuta.com/book/payments +paths: + /calendar/domains: + get: + x-route: calendar/domains + summary: Lorem ipsum + description: Lorem ipsum description + responses: + '200': + description: The Response + + + /calendar/domains/{id}: + parameters: + - name: id + in: path + description: lorem ipsum + required: true + schema: + type: integer + get: + x-route: calendar/domains + summary: Lorem ipsum + description: Lorem ipsum description + responses: + '200': + description: The Response + + /calendar/domains/{id}/{id2}: + parameters: + - name: id + in: path + description: lorem ipsum + required: true + schema: + type: integer + - name: id2 + in: path + description: lorem ipsum + required: true + schema: + type: integer + get: + x-route: calendar/domains + summary: Lorem ipsum + description: Lorem ipsum description + responses: + '200': + description: The Response + + + +components: + schemas: + Payments: + required: + - reference + - amount + - currency + properties: + invoice_number: + type: string + amount: + type: integer + format: int64 + currency: + type: string + + Success: + required: + - success + - message + properties: + success: + type: boolean + message: + type: string + + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string \ No newline at end of file diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index b6c7abdb..5daf9786 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -360,4 +360,32 @@ public function test158BugGiiapiGeneratedRulesEnumWithTrim() ]); $this->checkFiles($actualFiles, $expectedFiles); } + + // https://github.com/cebe/yii2-openapi/issues/144 + public function test144MethodsNamingForNonCrudActions() + { + $testFile = Yii::getAlias("@specs/issue_fix/144_methods_naming_for_non_crud_actions/index.php"); + $this->runGenerator($testFile); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/144_methods_naming_for_non_crud_actions/app"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + } + + // https://github.com/cebe/yii2-openapi/issues/84 + public function test84HowToGenerateControllerCodeWithDistinctMethodNamesInCaseOfPrefixInPaths() + { + $testFile = Yii::getAlias("@specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/index.php"); + $this->runGenerator($testFile); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/84_how_to_generate_controller_code_with_distinct_method_names_in_case_of_prefix_in_paths/app"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + } }