From cbb5adb788a8eb333741a828f90e728dfea4ba0f Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Wed, 12 Feb 2025 15:41:38 +0530 Subject: [PATCH 01/12] Create PR --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f68df469..4cc1d72a 100644 --- a/README.md +++ b/README.md @@ -779,3 +779,4 @@ Professional support, consulting as well as software development services are av https://www.cebe.cc/en/contact Development of this library is sponsored by [cebe.:cloud: "Your Professional Deployment Platform"](https://cebe.cloud). + From ca8e804144cf3a13a03b480219694278d1bd099c Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Fri, 14 Feb 2025 15:28:15 +0530 Subject: [PATCH 02/12] Add passing test --- README.md | 1 - .../index.php | 13 ++ .../index.yaml | 24 +++ .../mysql/models/BaseModelFaker.php | 144 ++++++++++++++++++ .../mysql/models/Payment.php | 10 ++ .../mysql/models/PaymentFaker.php | 42 +++++ .../mysql/models/base/Payment.php | 31 ++++ tests/unit/IssueFixTest.php | 13 ++ 8 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/index.php create mode 100644 tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/index.yaml create mode 100644 tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql/models/BaseModelFaker.php create mode 100644 tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql/models/Payment.php create mode 100644 tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql/models/PaymentFaker.php create mode 100644 tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql/models/base/Payment.php diff --git a/README.md b/README.md index 4cc1d72a..f68df469 100644 --- a/README.md +++ b/README.md @@ -779,4 +779,3 @@ Professional support, consulting as well as software development services are av https://www.cebe.cc/en/contact Development of this library is sponsored by [cebe.:cloud: "Your Professional Deployment Platform"](https://cebe.cloud). - diff --git a/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/index.php b/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/index.php new file mode 100644 index 00000000..9a6fa0f2 --- /dev/null +++ b/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/index.php @@ -0,0 +1,13 @@ + '@specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/index.yaml', + 'generateUrls' => false, + 'generateModels' => true, + 'excludeModels' => [ + 'Error', + ], + 'generateControllers' => false, + 'generateMigrations' => false, + 'generateModelFaker' => true, // `generateModels` must be `true` in order to use `generateModelFaker` as `true` +]; diff --git a/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/index.yaml b/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/index.yaml new file mode 100644 index 00000000..8f748b8e --- /dev/null +++ b/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/index.yaml @@ -0,0 +1,24 @@ +openapi: 3.0.3 + +info: + title: '#78' + version: 1.0.0 + +paths: + /: + get: + responses: + '200': + description: The Response + +components: + schemas: + Payment: + properties: + id: + type: integer + amount: + type: integer + readOnly: true + currency: + type: string diff --git a/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql/models/BaseModelFaker.php b/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql/models/BaseModelFaker.php new file mode 100644 index 00000000..c367fbb4 --- /dev/null +++ b/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql/models/BaseModelFaker.php @@ -0,0 +1,144 @@ +faker = FakerFactory::create(str_replace('-', '_', \Yii::$app->language)); + $this->uniqueFaker = new UniqueGenerator($this->faker); + } + + abstract public function generateModel($attributes = []); + + public function getFaker():Generator + { + return $this->faker; + } + + public function getUniqueFaker():UniqueGenerator + { + return $this->uniqueFaker; + } + + public function setFaker(Generator $faker):void + { + $this->faker = $faker; + } + + public function setUniqueFaker(UniqueGenerator $faker):void + { + $this->uniqueFaker = $faker; + } + + /** + * Generate and return model + * @param array|callable $attributes + * @param UniqueGenerator|null $uniqueFaker + * @return \yii\db\ActiveRecord + * @example MyFaker::makeOne(['user_id' => 1, 'title' => 'foo']); + * @example MyFaker::makeOne( function($model, $faker) { + * $model->scenario = 'create'; + * $model->setAttributes(['user_id' => 1, 'title' => $faker->sentence]); + * return $model; + * }); + */ + public static function makeOne($attributes = [], ?UniqueGenerator $uniqueFaker = null) + { + $fakeBuilder = new static(); + if ($uniqueFaker !== null) { + $fakeBuilder->setUniqueFaker($uniqueFaker); + } + $model = $fakeBuilder->generateModel($attributes); + return $model; + } + + /** + * Generate, save and return model + * @param array|callable $attributes + * @param UniqueGenerator|null $uniqueFaker + * @return \yii\db\ActiveRecord + * @example MyFaker::saveOne(['user_id' => 1, 'title' => 'foo']); + * @example MyFaker::saveOne( function($model, $faker) { + * $model->scenario = 'create'; + * $model->setAttributes(['user_id' => 1, 'title' => $faker->sentence]); + * return $model; + * }); + */ + public static function saveOne($attributes = [], ?UniqueGenerator $uniqueFaker = null) + { + $model = static::makeOne($attributes, $uniqueFaker); + $model->save(); + return $model; + } + + /** + * Generate and return multiple models + * @param int $number + * @param array|callable $commonAttributes + * @return \yii\db\ActiveRecord[]|array + * @example TaskFaker::make(5, ['project_id'=>1, 'user_id' => 2]); + * @example TaskFaker::make(5, function($model, $faker, $uniqueFaker) { + * $model->setAttributes(['name' => $uniqueFaker->username, 'state'=>$faker->boolean(20)]); + * return $model; + * }); + */ + public static function make(int $number, $commonAttributes = [], ?UniqueGenerator $uniqueFaker = null):array + { + if ($number < 1) { + return []; + } + $fakeBuilder = new static(); + if ($uniqueFaker !== null) { + $fakeBuilder->setUniqueFaker($uniqueFaker); + } + return array_map(function () use ($commonAttributes, $fakeBuilder) { + $model = $fakeBuilder->generateModel($commonAttributes); + return $model; + }, range(0, $number -1)); + } + + /** + * Generate, save and return multiple models + * @param int $number + * @param array|callable $commonAttributes + * @return \yii\db\ActiveRecord[]|array + * @example TaskFaker::save(5, ['project_id'=>1, 'user_id' => 2]); + * @example TaskFaker::save(5, function($model, $faker, $uniqueFaker) { + * $model->setAttributes(['name' => $uniqueFaker->username, 'state'=>$faker->boolean(20)]); + * return $model; + * }); + */ + public static function save(int $number, $commonAttributes = [], ?UniqueGenerator $uniqueFaker = null):array + { + if ($number < 1) { + return []; + } + $fakeBuilder = new static(); + if ($uniqueFaker !== null) { + $fakeBuilder->setUniqueFaker($uniqueFaker); + } + return array_map(function () use ($commonAttributes, $fakeBuilder) { + $model = $fakeBuilder->generateModel($commonAttributes); + $model->save(); + return $model; + }, range(0, $number -1)); + } +} diff --git a/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql/models/Payment.php b/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql/models/Payment.php new file mode 100644 index 00000000..660670f4 --- /dev/null +++ b/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql/models/Payment.php @@ -0,0 +1,10 @@ +generateModels(['author_id' => 1]); + * $model = (new PostFaker())->generateModels(function($model, $faker, $uniqueFaker) { + * $model->scenario = 'create'; + * $model->author_id = 1; + * return $model; + * }); + **/ + public function generateModel($attributes = []) + { + $faker = $this->faker; + $uniqueFaker = $this->uniqueFaker; + $model = new Payment(); + //$model->id = $uniqueFaker->numberBetween(0, 1000000); + $model->amount = $faker->numberBetween(0, 1000000); + $model->currency = $faker->currencyCode; + if (!is_callable($attributes)) { + $model->setAttributes($attributes, false); + } else { + $model = $attributes($model, $faker, $uniqueFaker); + } + return $model; + } +} diff --git a/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql/models/base/Payment.php b/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql/models/base/Payment.php new file mode 100644 index 00000000..129cce90 --- /dev/null +++ b/tests/specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql/models/base/Payment.php @@ -0,0 +1,31 @@ + [['currency'], 'trim'], + 'currency_string' => [['currency'], 'string'], + ]; + } +} diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index 64ca764d..c2d8796c 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -1001,4 +1001,17 @@ public function test74InvalidSchemaReferenceError() $this->runActualMigrations(); } + // https://github.com/php-openapi/yii2-openapi/issues/78 + public function test78PropertiesThatAreMarkedAsReadonlyAreNotReadOnly() + { + $testFile = Yii::getAlias("@specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/index.php"); + $this->runGenerator($testFile); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + } } From 426fecb1c5afcb2c100f2549112be9398f7091a8 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Fri, 7 Mar 2025 16:20:29 +0530 Subject: [PATCH 03/12] Modify a file to create pull request at GitHub --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f68df469..4cc1d72a 100644 --- a/README.md +++ b/README.md @@ -779,3 +779,4 @@ Professional support, consulting as well as software development services are av https://www.cebe.cc/en/contact Development of this library is sponsored by [cebe.:cloud: "Your Professional Deployment Platform"](https://cebe.cloud). + From 49cd50e33135debecf375cff2b3ba81e7d4f821a Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Fri, 7 Mar 2025 18:18:19 +0530 Subject: [PATCH 04/12] Add message --- README.md | 1 - src/lib/generators/ControllersGenerator.php | 13 +++++-- .../index.php | 13 +++++++ .../index.yml | 36 +++++++++++++++++++ tests/unit/IssueFixTest.php | 14 ++++++++ 5 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.php create mode 100644 tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.yml diff --git a/README.md b/README.md index 4cc1d72a..f68df469 100644 --- a/README.md +++ b/README.md @@ -779,4 +779,3 @@ Professional support, consulting as well as software development services are av https://www.cebe.cc/en/contact Development of this library is sponsored by [cebe.:cloud: "Your Professional Deployment Platform"](https://cebe.cloud). - diff --git a/src/lib/generators/ControllersGenerator.php b/src/lib/generators/ControllersGenerator.php index bd749c9f..e3ddcf23 100644 --- a/src/lib/generators/ControllersGenerator.php +++ b/src/lib/generators/ControllersGenerator.php @@ -59,7 +59,7 @@ public function generate():CodeFiles $controllerPath = $path; /** * @var RestAction|FractalAction $action - **/ + **/ $action = $actions[0]; if ($action->prefix && !empty($action->prefixSettings)) { $controllerNamespace = trim($action->prefixSettings['namespace'], '\\'); @@ -126,15 +126,22 @@ protected function makeCustomController( ]; $reflection->addMethod('checkAccess', $params, AbstractMemberGenerator::FLAG_PUBLIC, '//TODO implement checkAccess'); foreach ($abstractActions as $action) { + + $responseHttpStatusCodes = ''; + foreach ($this->config->getOpenApi()->paths->getPaths()[$action->urlPath]->getOperations() as $verb => $operation) { + if ($verb === strtolower($action->requestMethod)) { + $responseHttpStatusCodes = implode(', ', array_keys($operation->responses->getResponses())); + } + } + $params = array_map(static function ($param) { return ['name' => $param]; }, $action->getParamNames()); - $reflection->addMethod( $action->actionMethodName, $params, AbstractMemberGenerator::FLAG_PUBLIC, - '//TODO implement ' . $action->actionMethodName + '// TODO implement ' . $action->actionMethodName . PHP_EOL . '// In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: ' . $responseHttpStatusCodes ); } $classFileGenerator->setClasses([$reflection]); diff --git a/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.php b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.php new file mode 100644 index 00000000..cf88e27a --- /dev/null +++ b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.php @@ -0,0 +1,13 @@ + '@specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.yml', + 'generateUrls' => false, + 'generateModels' => false, + 'excludeModels' => [ + 'Error', + ], + 'generateControllers' => true, + 'generateMigrations' => false, + 'generateModelFaker' => false, +]; diff --git a/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.yml b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.yml new file mode 100644 index 00000000..df5b1314 --- /dev/null +++ b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.yml @@ -0,0 +1,36 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: 79_response_status_codes_are_not_the_codes_defined_in_spec +paths: + /mango/cake: + get: + responses: + '200': + description: The information + '403': + description: The information + '404': + description: The information + post: + responses: + '201': + description: The information + '403': + description: The information + '404': + description: The information + '422': + description: The information + +components: + schemas: + Address: + type: object + description: desc + properties: + id: + type: integer + name: + type: string + maxLength: 64 diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index ad3ff8fd..cda4e714 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -1014,4 +1014,18 @@ public function test22BugRulesRequiredIsGeneratedBeforeDefault() ]); $this->checkFiles($actualFiles, $expectedFiles); } + + // https://github.com/php-openapi/yii2-openapi/issues/79 + public function test79ResponseStatusCodesAreNotTheCodesDefinedInSpec() + { + $testFile = Yii::getAlias("@specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.php"); + $this->runGenerator($testFile); +// $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ +// 'recursive' => true, +// ]); +// $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql"), [ +// 'recursive' => true, +// ]); +// $this->checkFiles($actualFiles, $expectedFiles); + } } From ecbee9432dc6581367e0983c338be3656d125af1 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Fri, 7 Mar 2025 18:19:17 +0530 Subject: [PATCH 05/12] Complete the test --- .../mysql/controllers/MangoController.php | 27 +++++++++++++++ .../controllers/base/MangoController.php | 34 +++++++++++++++++++ tests/unit/IssueFixTest.php | 14 ++++---- 3 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/MangoController.php create mode 100644 tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/base/MangoController.php diff --git a/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/MangoController.php b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/MangoController.php new file mode 100644 index 00000000..4b3e60e3 --- /dev/null +++ b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/MangoController.php @@ -0,0 +1,27 @@ + [ + '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 actionCake(); + + abstract public function actionCreateCake(); + +} diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index cda4e714..13bf8702 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -1020,12 +1020,12 @@ public function test79ResponseStatusCodesAreNotTheCodesDefinedInSpec() { $testFile = Yii::getAlias("@specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.php"); $this->runGenerator($testFile); -// $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ -// 'recursive' => true, -// ]); -// $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql"), [ -// 'recursive' => true, -// ]); -// $this->checkFiles($actualFiles, $expectedFiles); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); } } From 229c0034438060e562aee47ad230c9db564ea8ee Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Sat, 8 Mar 2025 07:31:40 +0530 Subject: [PATCH 06/12] Refactor --- src/lib/generators/ControllersGenerator.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib/generators/ControllersGenerator.php b/src/lib/generators/ControllersGenerator.php index e3ddcf23..372af037 100644 --- a/src/lib/generators/ControllersGenerator.php +++ b/src/lib/generators/ControllersGenerator.php @@ -129,8 +129,9 @@ protected function makeCustomController( $responseHttpStatusCodes = ''; foreach ($this->config->getOpenApi()->paths->getPaths()[$action->urlPath]->getOperations() as $verb => $operation) { - if ($verb === strtolower($action->requestMethod)) { - $responseHttpStatusCodes = implode(', ', array_keys($operation->responses->getResponses())); + $codes = array_keys($operation->responses->getResponses()); + if ($verb === strtolower($action->requestMethod) && $codes !== [200]) { + $responseHttpStatusCodes = implode(', ', $codes); } } @@ -141,7 +142,7 @@ protected function makeCustomController( $action->actionMethodName, $params, AbstractMemberGenerator::FLAG_PUBLIC, - '// TODO implement ' . $action->actionMethodName . PHP_EOL . '// In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: ' . $responseHttpStatusCodes + '//TODO implement ' . $action->actionMethodName . ($responseHttpStatusCodes ? PHP_EOL . '// In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: ' . $responseHttpStatusCodes : '') ); } $classFileGenerator->setClasses([$reflection]); From d89fe286ae94d906092e809d36d09e6a7ee8b844 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Sat, 8 Mar 2025 08:12:43 +0530 Subject: [PATCH 07/12] Refactor and fix failing test --- src/lib/generators/ControllersGenerator.php | 12 ++++++++++-- .../specs/blog_v2/controllers/CommentController.php | 2 ++ .../pgsql/controllers/ContactController.php | 2 ++ .../pgsql/controllers/AccountController.php | 1 + .../mysql/controllers/MangoController.php | 4 ++-- 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/lib/generators/ControllersGenerator.php b/src/lib/generators/ControllersGenerator.php index 372af037..ea0c73c4 100644 --- a/src/lib/generators/ControllersGenerator.php +++ b/src/lib/generators/ControllersGenerator.php @@ -126,11 +126,19 @@ protected function makeCustomController( ]; $reflection->addMethod('checkAccess', $params, AbstractMemberGenerator::FLAG_PUBLIC, '//TODO implement checkAccess'); foreach ($abstractActions as $action) { - $responseHttpStatusCodes = ''; foreach ($this->config->getOpenApi()->paths->getPaths()[$action->urlPath]->getOperations() as $verb => $operation) { $codes = array_keys($operation->responses->getResponses()); - if ($verb === strtolower($action->requestMethod) && $codes !== [200]) { + + $only200OrDefault = false; + if ($codes === [200] || $codes === ['default']) { + $only200OrDefault = true; + } + if (in_array('default', $codes) && in_array(200, $codes) && count($codes) === 2) { + $only200OrDefault = true; + } + + if ($verb === strtolower($action->requestMethod) && !$only200OrDefault) { $responseHttpStatusCodes = implode(', ', $codes); } } diff --git a/tests/specs/blog_v2/controllers/CommentController.php b/tests/specs/blog_v2/controllers/CommentController.php index 0448ec72..c46307ed 100644 --- a/tests/specs/blog_v2/controllers/CommentController.php +++ b/tests/specs/blog_v2/controllers/CommentController.php @@ -18,6 +18,7 @@ public function actionListForPost($postId) public function actionCreateForPost($postId) { //TODO implement actionCreateForPost + // In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 201, default } public function actionViewForPost($slug, $id) @@ -28,6 +29,7 @@ public function actionViewForPost($slug, $id) public function actionDeleteForPost($slug, $id) { //TODO implement actionDeleteForPost + // In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 204 } public function actionUpdateForPost($slug, $id) diff --git a/tests/specs/issue_fix/163_generator_crash_when_using_reference_inside_an_object/pgsql/controllers/ContactController.php b/tests/specs/issue_fix/163_generator_crash_when_using_reference_inside_an_object/pgsql/controllers/ContactController.php index 10422b18..5f21cabb 100644 --- a/tests/specs/issue_fix/163_generator_crash_when_using_reference_inside_an_object/pgsql/controllers/ContactController.php +++ b/tests/specs/issue_fix/163_generator_crash_when_using_reference_inside_an_object/pgsql/controllers/ContactController.php @@ -13,11 +13,13 @@ public function checkAccess($action, $model = null, $params = []) public function actionListForAccount($accountId) { //TODO implement actionListForAccount + // In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 200, 403 } public function actionViewForAccount($accountId, $contactId) { //TODO implement actionViewForAccount + // In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 200, 403 } diff --git a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/controllers/AccountController.php b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/controllers/AccountController.php index b4044b8f..cfa4a6d3 100644 --- a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/controllers/AccountController.php +++ b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/controllers/AccountController.php @@ -13,6 +13,7 @@ public function checkAccess($action, $model = null, $params = []) public function actionView($id) { //TODO implement actionView + // In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 200, 404 } diff --git a/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/MangoController.php b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/MangoController.php index 4b3e60e3..46c40ad1 100644 --- a/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/MangoController.php +++ b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/MangoController.php @@ -12,13 +12,13 @@ public function checkAccess($action, $model = null, $params = []) public function actionCake() { - // TODO implement actionCake + //TODO implement actionCake // In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 200, 403, 404 } public function actionCreateCake() { - // TODO implement actionCreateCake + //TODO implement actionCreateCake // In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 201, 403, 404, 422 } From 4aa7668657b8f56a9c434c5e7c62d7961124081d Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Sat, 8 Mar 2025 10:24:38 +0530 Subject: [PATCH 08/12] Fix --- src/lib/SchemaToDatabase.php | 4 +- .../index.php | 13 ++ .../index.yml | 13 ++ .../mysql/models/BaseModelFaker.php | 144 ++++++++++++++++++ tests/unit/IssueFixTest.php | 14 ++ 5 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 tests/specs/issue_fix/96_component_schema_should_be_optional/index.php create mode 100644 tests/specs/issue_fix/96_component_schema_should_be_optional/index.yml create mode 100644 tests/specs/issue_fix/96_component_schema_should_be_optional/mysql/models/BaseModelFaker.php diff --git a/src/lib/SchemaToDatabase.php b/src/lib/SchemaToDatabase.php index ccb230a3..beb27180 100644 --- a/src/lib/SchemaToDatabase.php +++ b/src/lib/SchemaToDatabase.php @@ -94,7 +94,7 @@ public function prepareModels(): array $openApi = $this->config->getOpenApi(); $junctions = $this->findJunctionSchemas(); - foreach ($openApi->components->schemas as $schemaName => $openApiSchema) { + foreach ($openApi->components->schemas ?? [] as $schemaName => $openApiSchema) { $schema = Yii::createObject(ComponentSchema::class, [$openApiSchema, $schemaName]); if (!$this->canGenerateModel($schemaName, $schema)) { @@ -153,7 +153,7 @@ public function findJunctionSchemas(): JunctionSchemas { $junctions = []; $openApi = $this->config->getOpenApi(); - foreach ($openApi->components->schemas as $schemaName => $openApiSchema) { + foreach ($openApi->components->schemas ?? [] as $schemaName => $openApiSchema) { /**@var ComponentSchema $schema */ $schema = Yii::createObject(ComponentSchema::class, [$openApiSchema, $schemaName]); if ($schema->isNonDb()) { diff --git a/tests/specs/issue_fix/96_component_schema_should_be_optional/index.php b/tests/specs/issue_fix/96_component_schema_should_be_optional/index.php new file mode 100644 index 00000000..34db291a --- /dev/null +++ b/tests/specs/issue_fix/96_component_schema_should_be_optional/index.php @@ -0,0 +1,13 @@ + '@specs/issue_fix/96_component_schema_should_be_optional/index.yml', + 'generateUrls' => false, + 'generateModels' => true, + 'excludeModels' => [ + 'Error', + ], + 'generateControllers' => false, + 'generateMigrations' => false, + 'generateModelFaker' => true, +]; diff --git a/tests/specs/issue_fix/96_component_schema_should_be_optional/index.yml b/tests/specs/issue_fix/96_component_schema_should_be_optional/index.yml new file mode 100644 index 00000000..5dcbc3cb --- /dev/null +++ b/tests/specs/issue_fix/96_component_schema_should_be_optional/index.yml @@ -0,0 +1,13 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: 96_component_schema_should_be_optional + +paths: + /: + get: + summary: List + operationId: list + responses: + '200': + description: The information diff --git a/tests/specs/issue_fix/96_component_schema_should_be_optional/mysql/models/BaseModelFaker.php b/tests/specs/issue_fix/96_component_schema_should_be_optional/mysql/models/BaseModelFaker.php new file mode 100644 index 00000000..c367fbb4 --- /dev/null +++ b/tests/specs/issue_fix/96_component_schema_should_be_optional/mysql/models/BaseModelFaker.php @@ -0,0 +1,144 @@ +faker = FakerFactory::create(str_replace('-', '_', \Yii::$app->language)); + $this->uniqueFaker = new UniqueGenerator($this->faker); + } + + abstract public function generateModel($attributes = []); + + public function getFaker():Generator + { + return $this->faker; + } + + public function getUniqueFaker():UniqueGenerator + { + return $this->uniqueFaker; + } + + public function setFaker(Generator $faker):void + { + $this->faker = $faker; + } + + public function setUniqueFaker(UniqueGenerator $faker):void + { + $this->uniqueFaker = $faker; + } + + /** + * Generate and return model + * @param array|callable $attributes + * @param UniqueGenerator|null $uniqueFaker + * @return \yii\db\ActiveRecord + * @example MyFaker::makeOne(['user_id' => 1, 'title' => 'foo']); + * @example MyFaker::makeOne( function($model, $faker) { + * $model->scenario = 'create'; + * $model->setAttributes(['user_id' => 1, 'title' => $faker->sentence]); + * return $model; + * }); + */ + public static function makeOne($attributes = [], ?UniqueGenerator $uniqueFaker = null) + { + $fakeBuilder = new static(); + if ($uniqueFaker !== null) { + $fakeBuilder->setUniqueFaker($uniqueFaker); + } + $model = $fakeBuilder->generateModel($attributes); + return $model; + } + + /** + * Generate, save and return model + * @param array|callable $attributes + * @param UniqueGenerator|null $uniqueFaker + * @return \yii\db\ActiveRecord + * @example MyFaker::saveOne(['user_id' => 1, 'title' => 'foo']); + * @example MyFaker::saveOne( function($model, $faker) { + * $model->scenario = 'create'; + * $model->setAttributes(['user_id' => 1, 'title' => $faker->sentence]); + * return $model; + * }); + */ + public static function saveOne($attributes = [], ?UniqueGenerator $uniqueFaker = null) + { + $model = static::makeOne($attributes, $uniqueFaker); + $model->save(); + return $model; + } + + /** + * Generate and return multiple models + * @param int $number + * @param array|callable $commonAttributes + * @return \yii\db\ActiveRecord[]|array + * @example TaskFaker::make(5, ['project_id'=>1, 'user_id' => 2]); + * @example TaskFaker::make(5, function($model, $faker, $uniqueFaker) { + * $model->setAttributes(['name' => $uniqueFaker->username, 'state'=>$faker->boolean(20)]); + * return $model; + * }); + */ + public static function make(int $number, $commonAttributes = [], ?UniqueGenerator $uniqueFaker = null):array + { + if ($number < 1) { + return []; + } + $fakeBuilder = new static(); + if ($uniqueFaker !== null) { + $fakeBuilder->setUniqueFaker($uniqueFaker); + } + return array_map(function () use ($commonAttributes, $fakeBuilder) { + $model = $fakeBuilder->generateModel($commonAttributes); + return $model; + }, range(0, $number -1)); + } + + /** + * Generate, save and return multiple models + * @param int $number + * @param array|callable $commonAttributes + * @return \yii\db\ActiveRecord[]|array + * @example TaskFaker::save(5, ['project_id'=>1, 'user_id' => 2]); + * @example TaskFaker::save(5, function($model, $faker, $uniqueFaker) { + * $model->setAttributes(['name' => $uniqueFaker->username, 'state'=>$faker->boolean(20)]); + * return $model; + * }); + */ + public static function save(int $number, $commonAttributes = [], ?UniqueGenerator $uniqueFaker = null):array + { + if ($number < 1) { + return []; + } + $fakeBuilder = new static(); + if ($uniqueFaker !== null) { + $fakeBuilder->setUniqueFaker($uniqueFaker); + } + return array_map(function () use ($commonAttributes, $fakeBuilder) { + $model = $fakeBuilder->generateModel($commonAttributes); + $model->save(); + return $model; + }, range(0, $number -1)); + } +} diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index ad3ff8fd..c92d1f70 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -1014,4 +1014,18 @@ public function test22BugRulesRequiredIsGeneratedBeforeDefault() ]); $this->checkFiles($actualFiles, $expectedFiles); } + + // https://github.com/php-openapi/yii2-openapi/issues/96 + public function test96ComponentSchemaShouldBeOptional() + { + $testFile = Yii::getAlias("@specs/issue_fix/96_component_schema_should_be_optional/index.php"); + $this->runGenerator($testFile); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/96_component_schema_should_be_optional/mysql"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + } } From 0df26456e79a95db39898367646bfbb88f564be0 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Wed, 12 Mar 2025 15:01:35 +0530 Subject: [PATCH 09/12] Fix merge conflict --- .github/workflows/test.yml | 7 +- CONTRIBUTING.md | 2 +- Makefile | 30 +-- README.md | 220 +++++++++++++++++- docker-compose.yml | 3 +- src/generator/ApiGenerator.php | 2 +- src/generator/default/dbmodel.php | 6 +- src/lib/Config.php | 2 +- src/lib/ValidationRulesBuilder.php | 49 ++-- src/lib/items/DbModel.php | 2 +- src/lib/openapi/ComponentSchema.php | 6 +- src/lib/openapi/PropertySchema.php | 14 +- tests/DbTestCase.php | 8 +- tests/specs/blog/models/base/Category.php | 4 +- tests/specs/blog/models/base/Comment.php | 6 +- tests/specs/blog/models/base/Fakerable.php | 2 +- tests/specs/blog/models/base/Post.php | 14 +- tests/specs/blog/models/base/User.php | 10 +- tests/specs/blog_v2/models/base/Comment.php | 8 +- tests/specs/blog_v2/models/base/Post.php | 12 +- tests/specs/blog_v2/models/base/Tag.php | 2 +- tests/specs/blog_v2/models/base/User.php | 6 +- .../fk_col_name/app/models/base/Webhook.php | 2 +- .../app/models/base/Webhook.php | 14 +- .../mysql/models/base/Ubigpk.php | 2 +- .../app/models/base/Pristine.php | 2 +- .../maria/models/base/Contact.php | 6 +- .../app/models/base/Order.php | 4 +- .../pgsql/models/base/Contact.php | 6 +- .../pgsql/models/base/PaymentMethod.php | 2 +- .../m200000_000001_create_table_pets.php | 30 +-- .../mysql/models/base/Pet.php | 8 +- .../index.php | 13 ++ .../index.yaml | 36 +++ .../m200000_000000_create_table_accounts.php | 22 ++ .../mysql/models/Account.php | 10 + .../mysql/models/AccountFaker.php | 43 ++++ .../mysql/models/BaseModelFaker.php | 144 ++++++++++++ .../mysql/models/base/Account.php | 37 +++ .../index.php | 13 ++ .../index.yaml | 35 +++ .../m200000_000000_create_table_payments.php | 21 ++ .../m200000_000001_create_table_samples.php | 20 ++ .../mysql/models/BaseModelFaker.php | 144 ++++++++++++ .../mysql/models/Payments.php | 10 + .../mysql/models/PaymentsFaker.php | 44 ++++ .../mysql/models/Sample.php | 10 + .../mysql/models/SampleFaker.php | 41 ++++ .../mysql/models/base/Payments.php | 32 +++ .../mysql/models/base/Sample.php | 30 +++ .../mysql/models/base/Account.php | 4 +- .../mysql/models/base/Menu.php | 2 +- .../mysql/models/base/Post.php | 2 +- .../mysql/models/base/Address.php | 6 +- .../mysql/models/base/Invoice.php | 2 +- .../mysql/models/base/Product.php | 2 +- .../Product.json | 22 ++ .../index.json | 39 ++++ .../index.php | 13 ++ .../app/models/base/E123.php | 2 +- .../many2many/models/base/PostsGallery.php | 2 +- tests/specs/menu/models/base/Menu.php | 8 +- tests/specs/petstore/models/base/Pet.php | 4 +- .../models/base/PetStatistic.php | 4 +- .../petstore_namespace/mymodels/base/Pet.php | 4 +- .../postgres_custom/models/base/Custom.php | 6 +- .../app/models/base/A123.php | 2 +- .../app/models/base/B123.php | 2 +- .../app/models/base/Domain.php | 2 +- .../app/models/base/E123.php | 2 +- .../app/models/base/Routing.php | 8 +- .../maria/edit/app/models/base/Fruit.php | 20 +- .../edit_expression/app/models/base/Fruit.php | 20 +- .../maria/simple/app/models/base/Fruit.php | 20 +- .../mysql/edit/app/models/base/Fruit.php | 20 +- .../edit_expression/app/models/base/Fruit.php | 20 +- .../mysql/simple/app/models/base/Fruit.php | 20 +- .../pgsql/edit/app/models/base/Fruit.php | 20 +- .../edit_expression/app/models/base/Fruit.php | 20 +- .../pgsql/simple/app/models/base/Fruit.php | 20 +- .../models/mariamodel/base/Alldbdatatype.php | 18 +- .../app/models/mariamodel/base/Editcolumn.php | 12 +- .../app/models/mariamodel/base/Newcolumn.php | 2 +- .../app/models/mariamodel/base/Pristine.php | 4 +- .../mysql/app/models/base/Alldbdatatype.php | 18 +- .../mysql/app/models/base/Editcolumn.php | 12 +- .../mysql/app/models/base/Newcolumn.php | 2 +- .../mysql/app/models/base/Pristine.php | 4 +- .../models/pgsqlmodel/base/Alldbdatatype.php | 22 +- .../app/models/pgsqlmodel/base/Editcolumn.php | 12 +- .../app/models/pgsqlmodel/base/Newcolumn.php | 4 +- .../app/models/pgsqlmodel/base/Pristine.php | 4 +- tests/unit/IssueFixTest.php | 44 ++++ 93 files changed, 1362 insertions(+), 310 deletions(-) create mode 100644 tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/index.php create mode 100644 tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/index.yaml create mode 100644 tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/migrations_mysql_db/m200000_000000_create_table_accounts.php create mode 100644 tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/models/Account.php create mode 100644 tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/models/AccountFaker.php create mode 100644 tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/models/BaseModelFaker.php create mode 100644 tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/models/base/Account.php create mode 100644 tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/index.php create mode 100644 tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/index.yaml create mode 100644 tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/migrations_mysql_db/m200000_000000_create_table_payments.php create mode 100644 tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/migrations_mysql_db/m200000_000001_create_table_samples.php create mode 100644 tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/BaseModelFaker.php create mode 100644 tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/Payments.php create mode 100644 tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/PaymentsFaker.php create mode 100644 tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/Sample.php create mode 100644 tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/SampleFaker.php create mode 100644 tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/base/Payments.php create mode 100644 tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/base/Sample.php create mode 100644 tests/specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/Product.json create mode 100644 tests/specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/index.json create mode 100644 tests/specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/index.php diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8487efc3..462cb33e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,14 +31,11 @@ jobs: # Run every tests inside Docker container - name: Docker Compose Setup uses: ndeloof/install-compose-action@v0.0.1 - with: - # version: v3.5 # defaults to 'latest' - legacy: true # will also install in PATH as `docker-compose` - name: Clean run: make clean_all - - name: docker-compose up + - name: docker compose up run: make up # https://github.com/shivammathur/setup-php?tab=readme-ov-file#cache-composer-dependencies @@ -57,7 +54,7 @@ jobs: restore-keys: ${{ runner.os }}-composer- - name: Install Docker and composer dependencies - run: docker-compose exec php php -v && make installdocker + run: docker compose exec php php -v && make installdocker - name: Migrate run: make UID=0 migrate diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 053e65a9..534aba0d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -84,7 +84,7 @@ Creating yii2-openapi_maria_1 ... done Creating yii2-openapi_mysql_1 ... done Creating yii2-openapi_postgres_1 ... done Creating yii2-openapi_php_1 ... done -docker-compose exec php bash +docker compose exec php bash root@f9928598f841:/app# php -v diff --git a/Makefile b/Makefile index 72e173f8..9a23ae35 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ check-style: vendor/bin/php-cs-fixer fix --diff --dry-run check-style-from-host: - docker-compose run --rm php sh -c 'vendor/bin/php-cs-fixer fix --diff --dry-run' + docker compose run --rm php sh -c 'vendor/bin/php-cs-fixer fix --diff --dry-run' fix-style: vendor/bin/indent --tabs composer.json @@ -24,7 +24,7 @@ test: php $(PHPARGS) vendor/bin/phpunit clean_all: - docker-compose down + docker compose down --remove-orphans sudo rm -rf tests/tmp/* clean: @@ -32,38 +32,38 @@ clean: sudo rm -rf tests/tmp/docker_app/* down: - docker-compose down --remove-orphans + docker compose down --remove-orphans up: - docker-compose up -d + docker compose up -d echo "Waiting for mariadb to start up..." - docker-compose exec -T mysql timeout 60s sh -c "while ! (mysql -udbuser -pdbpass -h maria --execute 'SELECT 1;' > /dev/null 2>&1); do echo -n '.'; sleep 0.1 ; done; echo 'ok'" || (docker-compose ps; docker-compose logs; exit 1) + docker compose exec -T mysql timeout 60s sh -c "while ! (mysql -udbuser -pdbpass -h maria --execute 'SELECT 1;' > /dev/null 2>&1); do echo -n '.'; sleep 0.1 ; done; echo 'ok'" || (docker compose ps; docker compose logs; exit 1) echo "Waiting for Mysql to start up..." - docker-compose exec -T mysql timeout 60s sh -c "while ! (mysql -udbuser -pdbpass -h mysql --execute 'SELECT 1;' > /dev/null 2>&1); do echo -n '.'; sleep 0.1 ; done; echo 'ok'" || (docker-compose ps; docker-compose logs; exit 1) + docker compose exec -T mysql timeout 60s sh -c "while ! (mysql -udbuser -pdbpass -h mysql --execute 'SELECT 1;' > /dev/null 2>&1); do echo -n '.'; sleep 0.1 ; done; echo 'ok'" || (docker compose ps; docker compose logs; exit 1) cli: - docker-compose exec --user=$(UID) php bash + docker compose exec --user=$(UID) php bash cli_root: - docker-compose exec --user="root" php bash + docker compose exec --user="root" php bash cli_mysql: - docker-compose exec --user=$(UID) mysql bash + docker compose exec --user=$(UID) mysql bash migrate: - docker-compose run --user=$(UID) --rm php sh -c 'mkdir -p "tests/tmp/app"' - docker-compose run --user=$(UID) --rm php sh -c 'mkdir -p "tests/tmp/docker_app"' - docker-compose run --user=$(UID) --rm php sh -c 'cd /app/tests && ./yii migrate --interactive=0' + docker compose run --user=$(UID) --rm php sh -c 'mkdir -p "tests/tmp/app"' + docker compose run --user=$(UID) --rm php sh -c 'mkdir -p "tests/tmp/docker_app"' + docker compose run --user=$(UID) --rm php sh -c 'cd /app/tests && ./yii migrate --interactive=0' installdocker: - docker-compose run --user=$(UID) --rm php composer install && chmod +x tests/yii + docker compose run --user=$(UID) --rm php composer install && chmod +x tests/yii tests_dir_write_permission: - docker-compose run --user="root" --rm php chmod -R 777 tests/tmp/ # TODO avoid 777 https://github.com/cebe/yii2-openapi/issues/156 + docker compose run --user="root" --rm php chmod -R 777 tests/tmp/ # TODO avoid 777 https://github.com/cebe/yii2-openapi/issues/156 testdocker: - docker-compose run --user=$(UID) --rm php sh -c 'vendor/bin/phpunit --repeat 3' + docker compose run --user=$(UID) --rm php sh -c 'vendor/bin/phpunit --repeat 3' efs: clean_all up migrate # Everything From Scratch diff --git a/README.md b/README.md index f68df469..1ff3e2b4 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,224 @@ Such values are not allowed: If `enum` and `x-db-type` both are provided then for database column schema (migrations), only `x-db-type` will be considered ignoring `enum`. +### `x-scenarios` + +Automatically generated scenarios from the model 'x-scenarios'. +Each scenario is assigned attributes as in the 'default' scenario. +The advantage is that the scenario can be used immediately. +This can be overridden in the child model if needed. + +The 'default' scenario and all scenarios mentioned in the rules() using 'on' and 'except' +are automatically included in the scenarios() function for the model. + +There are three ways to define the scenarios `description`: +- use scenario description default settings `public $scenarioDefaultDescription = "Scenario {scenarioName}"`. +- use custom `scenarioDefaultDescription` at `dbModel`. +- use custom `description` for individual scenario. + +1. Example with default setting. + ```yaml + Invoice: + type: object + x-scenarios: + - name: create + - name: update + ``` + + The following code is generated in the abstract model: + ```php + abstract class Invoice extends \yii\db\ActiveRecord + { + /** + * Scenario create + */ + public const SCENARIO_CREATE = 'create'; + + /** + * Scenario update + */ + public const SCENARIO_UPDATE = 'update'; + + /** + * Automatically generated scenarios from the model 'x-scenarios'. + * @return array a list of scenarios and the corresponding active attributes. + */ + public function scenarios() + { + $parentScenarios = parent::scenarios(); + + /** + * Each scenario is assigned attributes as in the 'default' scenario. + * The advantage is that the scenario can be used immediately. + * This can be overridden in the child model if needed. + */ + $default = $parentScenarios[self::SCENARIO_DEFAULT]; + + return [ + self::SCENARIO_CREATE => $default, + self::SCENARIO_UPDATE => $default, + /** + * The 'default' scenario and all scenarios mentioned in the rules() using 'on' and 'except' + * are automatically included in the scenarios() function for the model. + */ + ...$parentScenarios, + ]; + } + } + ``` + +2. Example with custom `description` for individual scenario. + ```yaml + Invoice: + type: object + x-scenarios: + - name: create + description: My custom description for scenario create + - name: update + ``` + + The following code is generated in the abstract model: + ```php + abstract class Invoice extends \yii\db\ActiveRecord + { + /** + * My custom description for scenario create + */ + public const SCENARIO_CREATE = 'create'; + + /** + * Scenario update + */ + public const SCENARIO_UPDATE = 'update'; + + /** + * Automatically generated scenarios from the model 'x-scenarios'. + * @return array a list of scenarios and the corresponding active attributes. + */ + public function scenarios() + {...} + } + ``` + +3. Example with custom `scenarioDefaultDescription`. + + Set custom `scenarioDefaultDescription` at `dbModel`. + `scenarioDefaultDescription` Accepted-Placeholder: {scenarioName}, {scenarioConst}, {modelName}. + + For example, for the `create` scenario in the `Invoice` model, the placeholders would result in the following: + `{scenarioName}` = `create` + `{scenarioConst}` = `SCENARIO_CREATE` + `{modelName}` = `Invoice` + + php-config-settings + ```php + $config['modules']['gii']['generators']['api'] = [ + 'class' => \cebe\yii2openapi\generator\ApiGenerator::class, + 'dbModel' => [ + /** Accepted-Placeholder: {scenarioName}, {scenarioConst}, {modelName}. @see DbModel::$scenarioDefaultDescription */ + 'scenarioDefaultDescription' => "This scenario \"{scenarioName}\" at Model \"{modelName}\" has Constant {scenarioConst}.", + ], + ... + ]; + ``` + + ```yaml + Invoice: + type: object + x-scenarios: + - name: create + description: My custom description for scenario create + - name: update + ``` + + The following code is generated in the abstract model: + ```php + abstract class Invoice extends \yii\db\ActiveRecord + { + /** + * My custom description for scenario create + */ + public const SCENARIO_CREATE = 'create'; + + /** + * This scenario "update" at Model "Invoice" has Constant SCENARIO_UPDATE. + */ + public const SCENARIO_UPDATE = 'update'; + + /** + * Automatically generated scenarios from the model 'x-scenarios'. + * @return array a list of scenarios and the corresponding active attributes. + */ + public function scenarios() + {...} + } + ``` + +4. Example with custom `scenarioDefaultDescription` + and use-case: both '\cebe\yii2openapi\generator\ApiGenerator::class' and '\common\client_generator\{your_ApiClientGenerator}::class' are used. + + Set custom `scenarioDefaultDescription` at `dbModel`. + `scenarioDefaultDescription` Accepted-Placeholder: {scenarioName}, {scenarioConst}, {modelName}. + + php-config-settings + ```php + $config['modules']['gii']['generators']['api'] = [ + 'class' => \cebe\yii2openapi\generator\ApiGenerator::class, + 'dbModel' => [ + /** Accepted-Placeholder: {scenarioName}, {scenarioConst}, {modelName}. @see DbModel::$scenarioDefaultDescription */ + 'scenarioDefaultDescription' => implode("\n", [ + "This Backend-Scenario \"{scenarioName}\" exist in both the frontend model and the backend model.", + "@see \common\client\models\{modelName}::{scenarioConst}", + ]), + ], + ... + ]; + + $config['modules']['gii']['generators']['api-client'] = [ + 'class' => \common\client_generator\{your_ApiClientGenerator}::class, + 'dbModel' => [ + /** AcceptedInputs: {scenarioName}, {scenarioConst}, {modelName}. @see DbModel::$scenarioDefaultDescription */ + 'scenarioDefaultDescription' => implode("\n", [ + "This Frontend-Scenario \"{scenarioName}\" exist in both the frontend model and the backend model.", + "@see \common\models\base\{modelName}::{scenarioConst}", + ]), + ], + ... + ``` + + ```yaml + Invoice: + type: object + x-scenarios: + - name: create + - name: update + ``` + + The following code is generated in the abstract model: + ```php + abstract class Invoice extends \yii\db\ActiveRecord + { + /** + * This Backend-Scenario "create" exist in both the frontend model and the backend model. + * @see \common\client\models\Invoice::SCENARIO_CREATE + */ + public const SCENARIO_CREATE = 'create'; + + /** + * This Backend-Scenario "update" exist in both the frontend model and the backend model. + * @see \common\client\models\Invoice::SCENARIO_UPDATE + */ + public const SCENARIO_UPDATE = 'update'; + + /** + * Automatically generated scenarios from the model 'x-scenarios'. + * @return array a list of scenarios and the corresponding active attributes. + */ + public function scenarios() + {...} + } + ``` + ### `x-indexes` Specify table indexes @@ -350,7 +568,7 @@ related objects, `x-no-relation` (type: boolean, default: false) is used. This will not generate 'comments' column in database migrations. But it will generate `getComments()` relation in Yii model file. -In order to make it real database column, extension `x-no-relation` can be used. +In order to make it real database column, OpenAPI extension `x-no-relation` can be used. ```yaml comments: diff --git a/docker-compose.yml b/docker-compose.yml index 2eda366e..67d220d1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: "3.5" +name: yii2-docker services: php: image: yii2-openapi-php:${PHP_VERSION:-8.3} @@ -73,4 +73,3 @@ networks: ipam: config: - subnet: 172.14.0.0/24 - diff --git a/src/generator/ApiGenerator.php b/src/generator/ApiGenerator.php index 40df4315..d95405d5 100644 --- a/src/generator/ApiGenerator.php +++ b/src/generator/ApiGenerator.php @@ -143,7 +143,7 @@ class ApiGenerator extends Generator /** * @var array Map for custom dbModels * - * @see DbModel::$scenarioDefaultDescription with acceptedInputs: {scenarioName}, {scenarioConst}, {modelName}. + * @see DbModel::$scenarioDefaultDescription with Accepted-Placeholder: {scenarioName}, {scenarioConst}, {modelName}. * @example * 'dbModel' => [ * 'scenarioDefaultDescription' => "Scenario {scenarioName}", diff --git a/src/generator/default/dbmodel.php b/src/generator/default/dbmodel.php index a85fa7bb..f8c3ba3c 100644 --- a/src/generator/default/dbmodel.php +++ b/src/generator/default/dbmodel.php @@ -84,12 +84,14 @@ public static function tableName() */ public function scenarios() { + $parentScenarios = parent::scenarios(); + /** * Each scenario is assigned attributes as in the 'default' scenario. * The advantage is that the scenario can be used immediately. * This can be overridden in the child model if needed. */ - $default = parent::scenarios()[self::SCENARIO_DEFAULT]; + $default = $parentScenarios[self::SCENARIO_DEFAULT]; return [ @@ -99,7 +101,7 @@ public function scenarios() * The 'default' scenario and all scenarios mentioned in the rules() using 'on' and 'except' * are automatically included in the scenarios() function for the model. */ - ...parent::scenarios(), + ...$parentScenarios, ]; } diff --git a/src/lib/Config.php b/src/lib/Config.php index bd4934a0..a2531046 100644 --- a/src/lib/Config.php +++ b/src/lib/Config.php @@ -112,7 +112,7 @@ class Config extends BaseObject /** * @var array Map for custom dbModels * - * @see DbModel::$scenarioDefaultDescription with acceptedInputs: {scenarioName}, {scenarioConst}, {modelName}. + * @see DbModel::$scenarioDefaultDescription with Accepted-Placeholder: {scenarioName}, {scenarioConst}, {modelName}. * @example * 'dbModel' => [ * 'scenarioDefaultDescription' => "Scenario {scenarioName}", diff --git a/src/lib/ValidationRulesBuilder.php b/src/lib/ValidationRulesBuilder.php index 1397938a..33347314 100644 --- a/src/lib/ValidationRulesBuilder.php +++ b/src/lib/ValidationRulesBuilder.php @@ -53,30 +53,38 @@ public function build():array $this->rules['trim'] = new ValidationRule($this->typeScope['trim'], 'trim'); } + foreach ($this->model->attributes as $attribute) { + if ($this->isIdColumn($attribute)) { + continue; + } + $this->defaultRule($attribute); + } + if (!empty($this->typeScope['required'])) { $this->rules['required'] = new ValidationRule($this->typeScope['required'], 'required'); } - if (!empty($this->typeScope['ref'])) { - $this->addExistRules($this->typeScope['ref']); + + foreach ($this->model->attributes as $attribute) { + if ($this->isIdColumn($attribute)) { + continue; + } + $this->resolveAttributeRules($attribute); } + foreach ($this->model->indexes as $index) { if ($index->isUnique) { $this->addUniqueRule($index->columns); } } - foreach ($this->model->attributes as $attribute) { - // column/field/property with name `id` is considered as Primary Key by this library, and it is automatically handled by DB/Yii; so remove it from validation `rules()` - if (in_array($attribute->columnName, ['id', $this->model->pkName]) || - in_array($attribute->propertyName, ['id', $this->model->pkName]) - ) { - continue; - } - $this->resolveAttributeRules($attribute); + + if (!empty($this->typeScope['ref'])) { + $this->addExistRules($this->typeScope['ref']); } if (!empty($this->typeScope['safe'])) { $this->rules['safe'] = new ValidationRule($this->typeScope['safe'], 'safe'); } + return $this->rules; } @@ -93,7 +101,6 @@ private function resolveAttributeRules(Attribute $attribute):void } if ($attribute->phpType === 'bool' || $attribute->phpType === 'boolean') { $this->rules[$attribute->columnName . '_boolean'] = new ValidationRule([$attribute->columnName], 'boolean'); - $this->defaultRule($attribute); return; } @@ -111,13 +118,11 @@ private function resolveAttributeRules(Attribute $attribute):void } $this->rules[$key] = new ValidationRule([$attribute->columnName], $attribute->dbType, $params); - $this->defaultRule($attribute); return; } if (in_array($attribute->phpType, ['int', 'integer', 'double', 'float']) && !$attribute->isReference()) { $this->addNumericRule($attribute); - $this->defaultRule($attribute); return; } if ($attribute->phpType === 'string' && !$attribute->isReference()) { @@ -127,10 +132,8 @@ private function resolveAttributeRules(Attribute $attribute):void $key = $attribute->columnName . '_in'; $this->rules[$key] = new ValidationRule([$attribute->columnName], 'in', ['range' => $attribute->enumValues]); - $this->defaultRule($attribute); return; } - $this->defaultRule($attribute); $this->addRulesByAttributeName($attribute); } @@ -240,10 +243,7 @@ private function prepareTypeScope():void if ($attribute->isReadOnly()) { continue; } - // column/field/property with name `id` is considered as Primary Key by this library, and it is automatically handled by DB/Yii; so remove it from validation `rules()` - if (in_array($attribute->columnName, ['id', $this->model->pkName]) || - in_array($attribute->propertyName, ['id', $this->model->pkName]) - ) { + if ($this->isIdColumn($attribute)) { continue; } if (/*$attribute->defaultValue === null &&*/ $attribute->isRequired()) { @@ -278,4 +278,15 @@ public function __toString() } }; } + + private function isIdColumn(Attribute $attribute): bool + { + // column/field/property with name `id` is considered as Primary Key by this library, and it is automatically handled by DB/Yii; so remove it from validation `rules()` + if (in_array($attribute->columnName, ['id', $this->model->pkName]) || + in_array($attribute->propertyName, ['id', $this->model->pkName]) + ) { + return true; + } + return false; + } } diff --git a/src/lib/items/DbModel.php b/src/lib/items/DbModel.php index 08135d71..fcfa6d40 100644 --- a/src/lib/items/DbModel.php +++ b/src/lib/items/DbModel.php @@ -84,7 +84,7 @@ class DbModel extends BaseObject /** * @var string * Here, you can set your own default description for the scenario. - * AcceptedInputs: {scenarioName}, {scenarioConst}, {modelName}. + * Accepted-Placeholder: {scenarioName}, {scenarioConst}, {modelName}. */ public $scenarioDefaultDescription = "Scenario {scenarioName}"; diff --git a/src/lib/openapi/ComponentSchema.php b/src/lib/openapi/ComponentSchema.php index 809f0958..9386bf2a 100644 --- a/src/lib/openapi/ComponentSchema.php +++ b/src/lib/openapi/ComponentSchema.php @@ -14,8 +14,6 @@ use cebe\yii2openapi\lib\SchemaToDatabase; use Generator; use Yii; -use yii\helpers\Inflector; -use yii\helpers\StringHelper; use function in_array; class ComponentSchema @@ -106,7 +104,9 @@ public function isRequiredProperty(string $propName):bool public function isNonDb():bool { - return isset($this->schema->{CustomSpecAttr::TABLE}) && $this->schema->{CustomSpecAttr::TABLE} === false; + return + isset($this->schema->{CustomSpecAttr::TABLE}) && + $this->schema->{CustomSpecAttr::TABLE} === false; } public function resolveTableName(string $schemaName):string diff --git a/src/lib/openapi/PropertySchema.php b/src/lib/openapi/PropertySchema.php index eade252e..227e2011 100644 --- a/src/lib/openapi/PropertySchema.php +++ b/src/lib/openapi/PropertySchema.php @@ -145,6 +145,11 @@ public function __construct(SpecObjectInterface $property, string $name, Compone $property = $this->property; } + // don't go reference part if `x-no-relation` is true + if ($this->getAttr(CustomSpecAttr::NO_RELATION)) { + return; + } + if ($property instanceof Reference) { $this->initReference(); } elseif ( @@ -268,8 +273,10 @@ public function getSelfTargetProperty():?PropertySchema public function isRefPointerToSchema():bool { return $this->refPointer && - ((strpos($this->refPointer, self::REFERENCE_PATH) === 0) || - (str_ends_with($this->uri, '.yml')) || (str_ends_with($this->uri, '.yaml'))); + ( + (strpos($this->refPointer, self::REFERENCE_PATH) === 0) || + (str_ends_with($this->uri, '.yml')) || (str_ends_with($this->uri, '.yaml')) || (str_ends_with($this->uri, '.json')) + ); } public function isRefPointerToSelf():bool @@ -305,7 +312,7 @@ public function getRefSchemaName():string $pattern = strpos($this->refPointer, '/properties/') !== false ? '~^'.self::REFERENCE_PATH.'(?.+)/properties/(?.+)$~' : '~^'.self::REFERENCE_PATH.'(?.+)$~'; - $separateFilePattern = '/((\.\/)*)(?.+)(\.)(yml|yaml)(.*)/'; # https://github.com/php-openapi/yii2-openapi/issues/74 + $separateFilePattern = '/((\.\/)*)(?.+)(\.)(yml|yaml|json)(.*)/'; # https://github.com/php-openapi/yii2-openapi/issues/74 if (!\preg_match($pattern, $this->refPointer, $matches)) { if (!\preg_match($separateFilePattern, $this->uri, $separateFilePatternMatches)) { throw new InvalidDefinitionException('Invalid schema reference'); @@ -497,6 +504,7 @@ public function guessDbType($forReference = false):string } return YiiDbSchema::TYPE_TEXT; case 'object': + case 'array': { return YiiDbSchema::TYPE_JSON; } diff --git a/tests/DbTestCase.php b/tests/DbTestCase.php index fd3eebb4..e9a04a0b 100644 --- a/tests/DbTestCase.php +++ b/tests/DbTestCase.php @@ -3,13 +3,13 @@ namespace tests; use cebe\yii2openapi\generator\ApiGenerator; +use SamIT\Yii2\MariaDb\Schema as MariaDbSchema; use Yii; use yii\db\IndexConstraint; -use yii\di\Container; use yii\db\mysql\Schema as MySqlSchema; use yii\db\pgsql\Schema as PgSqlSchema; -use \SamIT\Yii2\MariaDb\Schema as MariaDbSchema; -use yii\helpers\{ArrayHelper, VarDumper, StringHelper, Console}; +use yii\di\Container; +use yii\helpers\{ArrayHelper, StringHelper}; use yii\helpers\FileHelper; class DbTestCase extends \PHPUnit\Framework\TestCase @@ -102,7 +102,6 @@ protected function compareFiles(array $actual, string $testFile) foreach ($actual as $file) { $expectedFile = str_replace('@app', substr($testFile, 0, -4), $file); $actualFile = str_replace('@app', Yii::getAlias('@app'), $file); - // exec('cp '.$actualFile.' '.$expectedFile); $this->checkFiles([$actualFile], [$expectedFile]); } } @@ -128,6 +127,7 @@ protected function checkFiles(array $actual, array $expected) ); } + // exec('cp '.$file.' '.$expectedFilePath); $this->assertFileEquals($expectedFilePath, $file, "Failed asserting that file contents of\n$file\nare equal to file contents of\n$expectedFilePath \n\n cp $file $expectedFilePath \n\n "); } } diff --git a/tests/specs/blog/models/base/Category.php b/tests/specs/blog/models/base/Category.php index 5a71d5fa..188ec03c 100644 --- a/tests/specs/blog/models/base/Category.php +++ b/tests/specs/blog/models/base/Category.php @@ -26,11 +26,11 @@ public function rules() { return [ 'trim' => [['title'], 'trim'], + 'active_default' => [['active'], 'default', 'value' => false], 'required' => [['title', 'active'], 'required'], - 'title_unique' => [['title'], 'unique'], 'title_string' => [['title'], 'string', 'max' => 255], 'active_boolean' => [['active'], 'boolean'], - 'active_default' => [['active'], 'default', 'value' => false], + 'title_unique' => [['title'], 'unique'], ]; } diff --git a/tests/specs/blog/models/base/Comment.php b/tests/specs/blog/models/base/Comment.php index 34007be9..f6e03bca 100644 --- a/tests/specs/blog/models/base/Comment.php +++ b/tests/specs/blog/models/base/Comment.php @@ -30,14 +30,14 @@ public function rules() { return [ 'trim' => [['post_id'], 'trim'], + 'message_default' => [['message'], 'default', 'value' => []], + 'meta_data_default' => [['meta_data'], 'default', 'value' => []], 'required' => [['post_id', 'author_id', 'message', 'created_at'], 'required'], + 'created_at_integer' => [['created_at'], 'integer'], 'post_id_string' => [['post_id'], 'string', 'max' => 128], 'post_id_exist' => [['post_id'], 'exist', 'targetRelation' => 'post'], 'author_id_integer' => [['author_id'], 'integer'], 'author_id_exist' => [['author_id'], 'exist', 'targetRelation' => 'author'], - 'message_default' => [['message'], 'default', 'value' => []], - 'meta_data_default' => [['meta_data'], 'default', 'value' => []], - 'created_at_integer' => [['created_at'], 'integer'], 'safe' => [['message', 'meta_data'], 'safe'], ]; } diff --git a/tests/specs/blog/models/base/Fakerable.php b/tests/specs/blog/models/base/Fakerable.php index a00ac9ae..9ba7a049 100644 --- a/tests/specs/blog/models/base/Fakerable.php +++ b/tests/specs/blog/models/base/Fakerable.php @@ -37,12 +37,12 @@ public function rules() { return [ 'trim' => [['str_text', 'str_varchar', 'str_date', 'str_datetime', 'str_country'], 'trim'], + 'int_min_default' => [['int_min'], 'default', 'value' => 3], 'active_boolean' => [['active'], 'boolean'], 'floatval_double' => [['floatval'], 'double'], 'floatval_lim_double' => [['floatval_lim'], 'double', 'min' => 0, 'max' => 1], 'doubleval_double' => [['doubleval'], 'double'], 'int_min_integer' => [['int_min'], 'integer', 'min' => 5], - 'int_min_default' => [['int_min'], 'default', 'value' => 3], 'int_max_integer' => [['int_max'], 'integer', 'max' => 5], 'int_minmax_integer' => [['int_minmax'], 'integer', 'min' => 5, 'max' => 25], 'int_created_at_integer' => [['int_created_at'], 'integer'], diff --git a/tests/specs/blog/models/base/Post.php b/tests/specs/blog/models/base/Post.php index f937aabd..633de3f4 100644 --- a/tests/specs/blog/models/base/Post.php +++ b/tests/specs/blog/models/base/Post.php @@ -32,18 +32,18 @@ public function rules() { return [ 'trim' => [['title', 'slug', 'created_at'], 'trim'], + 'active_default' => [['active'], 'default', 'value' => false], 'required' => [['title', 'category_id', 'active'], 'required'], - 'category_id_integer' => [['category_id'], 'integer'], - 'category_id_exist' => [['category_id'], 'exist', 'targetRelation' => 'category'], - 'created_by_id_integer' => [['created_by_id'], 'integer'], - 'created_by_id_exist' => [['created_by_id'], 'exist', 'targetRelation' => 'createdBy'], - 'title_unique' => [['title'], 'unique'], - 'slug_unique' => [['slug'], 'unique'], 'title_string' => [['title'], 'string', 'max' => 255], 'slug_string' => [['slug'], 'string', 'min' => 1, 'max' => 200], 'active_boolean' => [['active'], 'boolean'], - 'active_default' => [['active'], 'default', 'value' => false], 'created_at_date' => [['created_at'], 'date', 'format' => 'php:Y-m-d'], + 'title_unique' => [['title'], 'unique'], + 'slug_unique' => [['slug'], 'unique'], + 'category_id_integer' => [['category_id'], 'integer'], + 'category_id_exist' => [['category_id'], 'exist', 'targetRelation' => 'category'], + 'created_by_id_integer' => [['created_by_id'], 'integer'], + 'created_by_id_exist' => [['created_by_id'], 'exist', 'targetRelation' => 'createdBy'], ]; } diff --git a/tests/specs/blog/models/base/User.php b/tests/specs/blog/models/base/User.php index 61508cd6..dbd3a708 100644 --- a/tests/specs/blog/models/base/User.php +++ b/tests/specs/blog/models/base/User.php @@ -29,19 +29,19 @@ public function rules() { return [ 'trim' => [['username', 'email', 'password', 'role', 'created_at'], 'trim'], + 'role_default' => [['role'], 'default', 'value' => 'reader'], + 'flags_default' => [['flags'], 'default', 'value' => 0], + 'created_at_default' => [['created_at'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], 'required' => [['username', 'email', 'password'], 'required'], - 'username_unique' => [['username'], 'unique'], - 'email_unique' => [['email'], 'unique'], 'username_string' => [['username'], 'string', 'max' => 200], 'email_string' => [['email'], 'string', 'max' => 200], 'email_email' => [['email'], 'email'], 'password_string' => [['password'], 'string'], 'role_string' => [['role'], 'string', 'max' => 20], - 'role_default' => [['role'], 'default', 'value' => 'reader'], 'flags_integer' => [['flags'], 'integer'], - 'flags_default' => [['flags'], 'default', 'value' => 0], 'created_at_datetime' => [['created_at'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], - 'created_at_default' => [['created_at'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], + 'username_unique' => [['username'], 'unique'], + 'email_unique' => [['email'], 'unique'], ]; } diff --git a/tests/specs/blog_v2/models/base/Comment.php b/tests/specs/blog_v2/models/base/Comment.php index ae9d146b..2b4f404a 100644 --- a/tests/specs/blog_v2/models/base/Comment.php +++ b/tests/specs/blog_v2/models/base/Comment.php @@ -30,15 +30,15 @@ public function rules() { return [ 'trim' => [['message', 'meta_data', 'created_at'], 'trim'], + 'meta_data_default' => [['meta_data'], 'default', 'value' => ''], 'required' => [['post_id', 'message', 'created_at'], 'required'], + 'message_string' => [['message'], 'string'], + 'meta_data_string' => [['meta_data'], 'string', 'min' => 1, 'max' => 300], + 'created_at_datetime' => [['created_at'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'post_id_integer' => [['post_id'], 'integer'], 'post_id_exist' => [['post_id'], 'exist', 'targetRelation' => 'post'], 'user_id_integer' => [['user_id'], 'integer'], 'user_id_exist' => [['user_id'], 'exist', 'targetRelation' => 'user'], - 'message_string' => [['message'], 'string'], - 'meta_data_string' => [['meta_data'], 'string', 'min' => 1, 'max' => 300], - 'meta_data_default' => [['meta_data'], 'default', 'value' => ''], - 'created_at_datetime' => [['created_at'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], ]; } diff --git a/tests/specs/blog_v2/models/base/Post.php b/tests/specs/blog_v2/models/base/Post.php index 14e8829f..debc5008 100644 --- a/tests/specs/blog_v2/models/base/Post.php +++ b/tests/specs/blog_v2/models/base/Post.php @@ -34,12 +34,8 @@ public function rules() { return [ 'trim' => [['title', 'slug', 'created_at'], 'trim'], + 'lang_default' => [['lang'], 'default', 'value' => 'ru'], 'required' => [['title', 'category_id', 'active'], 'required'], - 'category_id_integer' => [['category_id'], 'integer'], - 'category_id_exist' => [['category_id'], 'exist', 'targetRelation' => 'category'], - 'created_by_id_integer' => [['created_by_id'], 'integer'], - 'created_by_id_exist' => [['created_by_id'], 'exist', 'targetRelation' => 'createdBy'], - 'title_unique' => [['title'], 'unique'], 'title_string' => [['title'], 'string', 'max' => 255], 'slug_string' => [['slug'], 'string', 'min' => 1, 'max' => 200], 'lang_string' => [['lang'], 'string'], @@ -47,9 +43,13 @@ public function rules() 'ru', 'eng', ]], - 'lang_default' => [['lang'], 'default', 'value' => 'ru'], 'active_boolean' => [['active'], 'boolean'], 'created_at_date' => [['created_at'], 'date', 'format' => 'php:Y-m-d'], + 'title_unique' => [['title'], 'unique'], + 'category_id_integer' => [['category_id'], 'integer'], + 'category_id_exist' => [['category_id'], 'exist', 'targetRelation' => 'category'], + 'created_by_id_integer' => [['created_by_id'], 'integer'], + 'created_by_id_exist' => [['created_by_id'], 'exist', 'targetRelation' => 'createdBy'], ]; } diff --git a/tests/specs/blog_v2/models/base/Tag.php b/tests/specs/blog_v2/models/base/Tag.php index b4e9c94a..b81a84b2 100644 --- a/tests/specs/blog_v2/models/base/Tag.php +++ b/tests/specs/blog_v2/models/base/Tag.php @@ -27,13 +27,13 @@ public function rules() return [ 'trim' => [['name'], 'trim'], 'required' => [['name', 'lang'], 'required'], - 'name_unique' => [['name'], 'unique'], 'name_string' => [['name'], 'string', 'max' => 100], 'lang_string' => [['lang'], 'string'], 'lang_in' => [['lang'], 'in', 'range' => [ 'ru', 'eng', ]], + 'name_unique' => [['name'], 'unique'], ]; } diff --git a/tests/specs/blog_v2/models/base/User.php b/tests/specs/blog_v2/models/base/User.php index 28f832d8..45c5b4e0 100644 --- a/tests/specs/blog_v2/models/base/User.php +++ b/tests/specs/blog_v2/models/base/User.php @@ -29,9 +29,8 @@ public function rules() { return [ 'trim' => [['login', 'email', 'password', 'created_at'], 'trim'], + 'flags_default' => [['flags'], 'default', 'value' => 0], 'required' => [['login', 'email', 'password'], 'required'], - 'login_unique' => [['login'], 'unique'], - 'email_unique' => [['email'], 'unique'], 'login_string' => [['login'], 'string'], 'email_string' => [['email'], 'string', 'max' => 255], 'email_email' => [['email'], 'email'], @@ -43,8 +42,9 @@ public function rules() 'reader', ]], 'flags_integer' => [['flags'], 'integer'], - 'flags_default' => [['flags'], 'default', 'value' => 0], 'created_at_datetime' => [['created_at'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'login_unique' => [['login'], 'unique'], + 'email_unique' => [['email'], 'unique'], ]; } diff --git a/tests/specs/fk_col_name/app/models/base/Webhook.php b/tests/specs/fk_col_name/app/models/base/Webhook.php index 5360f302..a4176122 100644 --- a/tests/specs/fk_col_name/app/models/base/Webhook.php +++ b/tests/specs/fk_col_name/app/models/base/Webhook.php @@ -28,11 +28,11 @@ public function rules() { return [ 'trim' => [['name'], 'trim'], + 'name_string' => [['name'], 'string'], 'user_id_integer' => [['user_id'], 'integer'], 'user_id_exist' => [['user_id'], 'exist', 'targetRelation' => 'user'], 'redelivery_of_integer' => [['redelivery_of'], 'integer'], 'redelivery_of_exist' => [['redelivery_of'], 'exist', 'targetRelation' => 'redeliveryOf'], - 'name_string' => [['name'], 'string'], ]; } diff --git a/tests/specs/fk_col_name_index/app/models/base/Webhook.php b/tests/specs/fk_col_name_index/app/models/base/Webhook.php index 0325e083..433d8098 100644 --- a/tests/specs/fk_col_name_index/app/models/base/Webhook.php +++ b/tests/specs/fk_col_name_index/app/models/base/Webhook.php @@ -30,12 +30,7 @@ public function rules() { return [ 'trim' => [['name'], 'trim'], - 'user_id_integer' => [['user_id'], 'integer'], - 'user_id_exist' => [['user_id'], 'exist', 'targetRelation' => 'user'], - 'redelivery_of_integer' => [['redelivery_of'], 'integer'], - 'redelivery_of_exist' => [['redelivery_of'], 'exist', 'targetRelation' => 'redeliveryOf'], - 'rd_abc_2_integer' => [['rd_abc_2'], 'integer'], - 'rd_abc_2_exist' => [['rd_abc_2'], 'exist', 'targetRelation' => 'rd2'], + 'name_string' => [['name'], 'string', 'max' => 255], 'user_id_name_unique' => [['user_id', 'name'], 'unique', 'targetAttribute' => [ 'user_id', 'name', @@ -48,7 +43,12 @@ public function rules() 'rd_abc_2', 'name', ]], - 'name_string' => [['name'], 'string', 'max' => 255], + 'user_id_integer' => [['user_id'], 'integer'], + 'user_id_exist' => [['user_id'], 'exist', 'targetRelation' => 'user'], + 'redelivery_of_integer' => [['redelivery_of'], 'integer'], + 'redelivery_of_exist' => [['redelivery_of'], 'exist', 'targetRelation' => 'redeliveryOf'], + 'rd_abc_2_integer' => [['rd_abc_2'], 'integer'], + 'rd_abc_2_exist' => [['rd_abc_2'], 'exist', 'targetRelation' => 'rd2'], ]; } diff --git a/tests/specs/issue_fix/132_create_migration_for_drop_table/mysql/models/base/Ubigpk.php b/tests/specs/issue_fix/132_create_migration_for_drop_table/mysql/models/base/Ubigpk.php index 5f8cbf5f..d1ebaa65 100644 --- a/tests/specs/issue_fix/132_create_migration_for_drop_table/mysql/models/base/Ubigpk.php +++ b/tests/specs/issue_fix/132_create_migration_for_drop_table/mysql/models/base/Ubigpk.php @@ -30,6 +30,7 @@ public function rules() { return [ 'trim' => [['name', 'f'], 'trim'], + 'size_default' => [['size'], 'default', 'value' => 'x-small'], 'name_string' => [['name'], 'string', 'max' => 150], 'size_string' => [['size'], 'string'], 'size_in' => [['size'], 'in', 'range' => [ @@ -39,7 +40,6 @@ public function rules() 'large', 'x-large', ]], - 'size_default' => [['size'], 'default', 'value' => 'x-small'], 'd_integer' => [['d'], 'integer'], 'e_integer' => [['e'], 'integer'], 'f_string' => [['f'], 'string', 'max' => 12], diff --git a/tests/specs/issue_fix/153_nullable_false_in_required/app/models/base/Pristine.php b/tests/specs/issue_fix/153_nullable_false_in_required/app/models/base/Pristine.php index b6b497bd..0aab2fad 100644 --- a/tests/specs/issue_fix/153_nullable_false_in_required/app/models/base/Pristine.php +++ b/tests/specs/issue_fix/153_nullable_false_in_required/app/models/base/Pristine.php @@ -23,9 +23,9 @@ public static function tableName() public function rules() { return [ + 'billing_factor_default' => [['billing_factor'], 'default', 'value' => 100], 'required' => [['billing_factor'], 'required'], 'billing_factor_integer' => [['billing_factor'], 'integer'], - 'billing_factor_default' => [['billing_factor'], 'default', 'value' => 100], ]; } } diff --git a/tests/specs/issue_fix/159_bug_giiapi_generated_rules_emailid/maria/models/base/Contact.php b/tests/specs/issue_fix/159_bug_giiapi_generated_rules_emailid/maria/models/base/Contact.php index 086cb6c4..a7df2b21 100644 --- a/tests/specs/issue_fix/159_bug_giiapi_generated_rules_emailid/maria/models/base/Contact.php +++ b/tests/specs/issue_fix/159_bug_giiapi_generated_rules_emailid/maria/models/base/Contact.php @@ -27,12 +27,12 @@ public function rules() { return [ 'trim' => [['nickname'], 'trim'], + 'active_default' => [['active'], 'default', 'value' => false], 'required' => [['mailing_id'], 'required'], - 'mailing_id_integer' => [['mailing_id'], 'integer'], - 'mailing_id_exist' => [['mailing_id'], 'exist', 'targetRelation' => 'mailing'], 'active_boolean' => [['active'], 'boolean'], - 'active_default' => [['active'], 'default', 'value' => false], 'nickname_string' => [['nickname'], 'string'], + 'mailing_id_integer' => [['mailing_id'], 'integer'], + 'mailing_id_exist' => [['mailing_id'], 'exist', 'targetRelation' => 'mailing'], ]; } diff --git a/tests/specs/issue_fix/162_bug_dollarref_with_x_faker/app/models/base/Order.php b/tests/specs/issue_fix/162_bug_dollarref_with_x_faker/app/models/base/Order.php index 9f23f63a..722e3c53 100644 --- a/tests/specs/issue_fix/162_bug_dollarref_with_x_faker/app/models/base/Order.php +++ b/tests/specs/issue_fix/162_bug_dollarref_with_x_faker/app/models/base/Order.php @@ -27,10 +27,10 @@ public function rules() { return [ 'trim' => [['name', 'name2'], 'trim'], - 'invoice_id_integer' => [['invoice_id'], 'integer'], - 'invoice_id_exist' => [['invoice_id'], 'exist', 'targetRelation' => 'invoice'], 'name_string' => [['name'], 'string'], 'name2_string' => [['name2'], 'string'], + 'invoice_id_integer' => [['invoice_id'], 'integer'], + 'invoice_id_exist' => [['invoice_id'], 'exist', 'targetRelation' => 'invoice'], ]; } diff --git a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/models/base/Contact.php b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/models/base/Contact.php index fb0a54ae..47eeecc0 100644 --- a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/models/base/Contact.php +++ b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/models/base/Contact.php @@ -27,12 +27,12 @@ public function rules() { return [ 'trim' => [['nickname'], 'trim'], + 'active_default' => [['active'], 'default', 'value' => false], 'required' => [['account_id'], 'required'], - 'account_id_integer' => [['account_id'], 'integer'], - 'account_id_exist' => [['account_id'], 'exist', 'targetRelation' => 'account'], 'active_boolean' => [['active'], 'boolean'], - 'active_default' => [['active'], 'default', 'value' => false], 'nickname_string' => [['nickname'], 'string'], + 'account_id_integer' => [['account_id'], 'integer'], + 'account_id_exist' => [['account_id'], 'exist', 'targetRelation' => 'account'], ]; } diff --git a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/models/base/PaymentMethod.php b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/models/base/PaymentMethod.php index 8b3f3c64..0bc51c6d 100644 --- a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/models/base/PaymentMethod.php +++ b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/models/base/PaymentMethod.php @@ -25,8 +25,8 @@ public function rules() return [ 'trim' => [['name'], 'trim'], 'required' => [['name'], 'required'], - 'name_unique' => [['name'], 'unique'], 'name_string' => [['name'], 'string', 'max' => 150], + 'name_unique' => [['name'], 'unique'], ]; } } diff --git a/tests/specs/issue_fix/20_consider_openapi_spec_examples_in_faker_code_generation/mysql/migrations_mysql_db/m200000_000001_create_table_pets.php b/tests/specs/issue_fix/20_consider_openapi_spec_examples_in_faker_code_generation/mysql/migrations_mysql_db/m200000_000001_create_table_pets.php index 01df98f3..3099e6fe 100644 --- a/tests/specs/issue_fix/20_consider_openapi_spec_examples_in_faker_code_generation/mysql/migrations_mysql_db/m200000_000001_create_table_pets.php +++ b/tests/specs/issue_fix/20_consider_openapi_spec_examples_in_faker_code_generation/mysql/migrations_mysql_db/m200000_000001_create_table_pets.php @@ -11,21 +11,21 @@ public function up() 'id' => $this->primaryKey(), 'name' => $this->text()->notNull(), 'age' => $this->integer()->null()->defaultValue(null), - 'tags' => $this->text()->null(), - 'tags_arbit' => $this->text()->null(), - 'number_arr' => $this->text()->null(), - 'number_arr_min_uniq' => $this->text()->null(), - 'int_arr' => $this->text()->null(), - 'int_arr_min_uniq' => $this->text()->null(), - 'bool_arr' => $this->text()->null(), - 'arr_arr_int' => $this->text()->null(), - 'arr_arr_str' => $this->text()->null(), - 'arr_arr_arr_str' => $this->text()->null(), - 'arr_of_obj' => $this->text()->null(), - 'user_ref_obj_arr' => $this->string()->null()->defaultValue(null), - 'one_of_arr' => $this->text()->null(), - 'one_of_arr_complex' => $this->text()->null(), - 'one_of_from_multi_ref_arr' => $this->text()->null(), + 'tags' => 'json NOT NULL', + 'tags_arbit' => 'json NOT NULL', + 'number_arr' => 'json NOT NULL', + 'number_arr_min_uniq' => 'json NOT NULL', + 'int_arr' => 'json NOT NULL', + 'int_arr_min_uniq' => 'json NOT NULL', + 'bool_arr' => 'json NOT NULL', + 'arr_arr_int' => 'json NOT NULL', + 'arr_arr_str' => 'json NOT NULL', + 'arr_arr_arr_str' => 'json NOT NULL', + 'arr_of_obj' => 'json NOT NULL', + 'user_ref_obj_arr' => 'json NOT NULL', + 'one_of_arr' => 'json NOT NULL', + 'one_of_arr_complex' => 'json NOT NULL', + 'one_of_from_multi_ref_arr' => 'json NOT NULL', ]); } diff --git a/tests/specs/issue_fix/20_consider_openapi_spec_examples_in_faker_code_generation/mysql/models/base/Pet.php b/tests/specs/issue_fix/20_consider_openapi_spec_examples_in_faker_code_generation/mysql/models/base/Pet.php index c0621fd6..ae87e515 100644 --- a/tests/specs/issue_fix/20_consider_openapi_spec_examples_in_faker_code_generation/mysql/models/base/Pet.php +++ b/tests/specs/issue_fix/20_consider_openapi_spec_examples_in_faker_code_generation/mysql/models/base/Pet.php @@ -23,13 +23,12 @@ * @property array $arr_arr_str * @property array $arr_arr_arr_str * @property array $arr_of_obj - * @property User[] $user_ref_obj_arr + * @property array $user_ref_obj_arr * @property array $one_of_arr * @property array $one_of_arr_complex * @property array $one_of_from_multi_ref_arr * * @property array|\app\models\User[] $userRefObjArrNormal - * @property array|\app\models\User[] $userRefObjArr */ abstract class Pet extends \yii\db\ActiveRecord { @@ -53,9 +52,4 @@ public function getUserRefObjArrNormal() { return $this->hasMany(\app\models\User::class, ['pet_id' => 'id'])->inverseOf('pet'); } - - public function getUserRefObjArr() - { - return $this->hasMany(\app\models\User::class, ['pet_id' => 'id'])->inverseOf('pet'); - } } diff --git a/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/index.php b/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/index.php new file mode 100644 index 00000000..ebfdd29d --- /dev/null +++ b/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/index.php @@ -0,0 +1,13 @@ + '@specs/issue_fix/22_bug_rules_required_is_generated_before_default/index.yaml', + 'generateUrls' => false, + 'generateModels' => true, + 'excludeModels' => [ + 'Error', + ], + 'generateControllers' => false, + 'generateMigrations' => true, + 'generateModelFaker' => true, // `generateModels` must be `true` in order to use `generateModelFaker` as `true` +]; diff --git a/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/index.yaml b/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/index.yaml new file mode 100644 index 00000000..7081de94 --- /dev/null +++ b/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/index.yaml @@ -0,0 +1,36 @@ +openapi: 3.0.3 + +info: + title: 'Bug: rules() "required" is generated before "*_default" #22' + version: 1.0.0 + +components: + schemas: + Account: + description: Account + type: object + required: + - id + - name + - verified + properties: + id: + type: integer + readOnly: true + name: + description: account name + type: string + maxLength: 128 + paymentMethodName: + type: string + default: card + verified: + type: boolean + default: false + +paths: + '/account': + get: + responses: + '200': + description: Account info diff --git a/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/migrations_mysql_db/m200000_000000_create_table_accounts.php b/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/migrations_mysql_db/m200000_000000_create_table_accounts.php new file mode 100644 index 00000000..584fc0ee --- /dev/null +++ b/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/migrations_mysql_db/m200000_000000_create_table_accounts.php @@ -0,0 +1,22 @@ +createTable('{{%accounts}}', [ + 'id' => $this->primaryKey(), + 'name' => $this->string(128)->notNull()->comment('account name'), + 'paymentMethodName' => $this->text()->null(), + 'verified' => $this->boolean()->notNull()->defaultValue(false), + ]); + } + + public function down() + { + $this->dropTable('{{%accounts}}'); + } +} diff --git a/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/models/Account.php b/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/models/Account.php new file mode 100644 index 00000000..2d25d7fc --- /dev/null +++ b/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/models/Account.php @@ -0,0 +1,10 @@ +generateModels(['author_id' => 1]); + * $model = (new PostFaker())->generateModels(function($model, $faker, $uniqueFaker) { + * $model->scenario = 'create'; + * $model->author_id = 1; + * return $model; + * }); + **/ + public function generateModel($attributes = []) + { + $faker = $this->faker; + $uniqueFaker = $this->uniqueFaker; + $model = new Account(); + //$model->id = $uniqueFaker->numberBetween(0, 1000000); + $model->name = substr($faker->text(128), 0, 128); + $model->paymentMethodName = $faker->sentence; + $model->verified = $faker->boolean; + if (!is_callable($attributes)) { + $model->setAttributes($attributes, false); + } else { + $model = $attributes($model, $faker, $uniqueFaker); + } + return $model; + } +} diff --git a/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/models/BaseModelFaker.php b/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/models/BaseModelFaker.php new file mode 100644 index 00000000..c367fbb4 --- /dev/null +++ b/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/models/BaseModelFaker.php @@ -0,0 +1,144 @@ +faker = FakerFactory::create(str_replace('-', '_', \Yii::$app->language)); + $this->uniqueFaker = new UniqueGenerator($this->faker); + } + + abstract public function generateModel($attributes = []); + + public function getFaker():Generator + { + return $this->faker; + } + + public function getUniqueFaker():UniqueGenerator + { + return $this->uniqueFaker; + } + + public function setFaker(Generator $faker):void + { + $this->faker = $faker; + } + + public function setUniqueFaker(UniqueGenerator $faker):void + { + $this->uniqueFaker = $faker; + } + + /** + * Generate and return model + * @param array|callable $attributes + * @param UniqueGenerator|null $uniqueFaker + * @return \yii\db\ActiveRecord + * @example MyFaker::makeOne(['user_id' => 1, 'title' => 'foo']); + * @example MyFaker::makeOne( function($model, $faker) { + * $model->scenario = 'create'; + * $model->setAttributes(['user_id' => 1, 'title' => $faker->sentence]); + * return $model; + * }); + */ + public static function makeOne($attributes = [], ?UniqueGenerator $uniqueFaker = null) + { + $fakeBuilder = new static(); + if ($uniqueFaker !== null) { + $fakeBuilder->setUniqueFaker($uniqueFaker); + } + $model = $fakeBuilder->generateModel($attributes); + return $model; + } + + /** + * Generate, save and return model + * @param array|callable $attributes + * @param UniqueGenerator|null $uniqueFaker + * @return \yii\db\ActiveRecord + * @example MyFaker::saveOne(['user_id' => 1, 'title' => 'foo']); + * @example MyFaker::saveOne( function($model, $faker) { + * $model->scenario = 'create'; + * $model->setAttributes(['user_id' => 1, 'title' => $faker->sentence]); + * return $model; + * }); + */ + public static function saveOne($attributes = [], ?UniqueGenerator $uniqueFaker = null) + { + $model = static::makeOne($attributes, $uniqueFaker); + $model->save(); + return $model; + } + + /** + * Generate and return multiple models + * @param int $number + * @param array|callable $commonAttributes + * @return \yii\db\ActiveRecord[]|array + * @example TaskFaker::make(5, ['project_id'=>1, 'user_id' => 2]); + * @example TaskFaker::make(5, function($model, $faker, $uniqueFaker) { + * $model->setAttributes(['name' => $uniqueFaker->username, 'state'=>$faker->boolean(20)]); + * return $model; + * }); + */ + public static function make(int $number, $commonAttributes = [], ?UniqueGenerator $uniqueFaker = null):array + { + if ($number < 1) { + return []; + } + $fakeBuilder = new static(); + if ($uniqueFaker !== null) { + $fakeBuilder->setUniqueFaker($uniqueFaker); + } + return array_map(function () use ($commonAttributes, $fakeBuilder) { + $model = $fakeBuilder->generateModel($commonAttributes); + return $model; + }, range(0, $number -1)); + } + + /** + * Generate, save and return multiple models + * @param int $number + * @param array|callable $commonAttributes + * @return \yii\db\ActiveRecord[]|array + * @example TaskFaker::save(5, ['project_id'=>1, 'user_id' => 2]); + * @example TaskFaker::save(5, function($model, $faker, $uniqueFaker) { + * $model->setAttributes(['name' => $uniqueFaker->username, 'state'=>$faker->boolean(20)]); + * return $model; + * }); + */ + public static function save(int $number, $commonAttributes = [], ?UniqueGenerator $uniqueFaker = null):array + { + if ($number < 1) { + return []; + } + $fakeBuilder = new static(); + if ($uniqueFaker !== null) { + $fakeBuilder->setUniqueFaker($uniqueFaker); + } + return array_map(function () use ($commonAttributes, $fakeBuilder) { + $model = $fakeBuilder->generateModel($commonAttributes); + $model->save(); + return $model; + }, range(0, $number -1)); + } +} diff --git a/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/models/base/Account.php b/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/models/base/Account.php new file mode 100644 index 00000000..dc19672e --- /dev/null +++ b/tests/specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql/models/base/Account.php @@ -0,0 +1,37 @@ + [['name', 'paymentMethodName'], 'trim'], + 'paymentMethodName_default' => [['paymentMethodName'], 'default', 'value' => 'card'], + 'verified_default' => [['verified'], 'default', 'value' => false], + 'required' => [['name', 'verified'], 'required'], + 'name_string' => [['name'], 'string', 'max' => 128], + 'paymentMethodName_string' => [['paymentMethodName'], 'string'], + 'verified_boolean' => [['verified'], 'boolean'], + ]; + } +} diff --git a/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/index.php b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/index.php new file mode 100644 index 00000000..d10773f1 --- /dev/null +++ b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/index.php @@ -0,0 +1,13 @@ + '@specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/index.yaml', + 'generateUrls' => false, + 'generateModels' => true, + 'excludeModels' => [ + 'Error', + ], + 'generateControllers' => false, + 'generateMigrations' => true, + 'generateModelFaker' => true, // `generateModels` must be `true` in order to use `generateModelFaker` as `true` +]; diff --git a/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/index.yaml b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/index.yaml new file mode 100644 index 00000000..669f6239 --- /dev/null +++ b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/index.yaml @@ -0,0 +1,35 @@ +openapi: 3.0.3 + +info: + title: '#23' + version: 1.0.0 + +paths: + /: + get: + responses: + '200': + description: The Response + + + +components: + schemas: + Payments: + properties: + id: + type: integer + currency: + type: string + samples: + type: array + x-no-relation: true + items: + $ref: '#/components/schemas/Sample' + + Sample: + properties: + id: + type: integer + message: + type: string \ No newline at end of file diff --git a/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/migrations_mysql_db/m200000_000000_create_table_payments.php b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/migrations_mysql_db/m200000_000000_create_table_payments.php new file mode 100644 index 00000000..5579f4e7 --- /dev/null +++ b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/migrations_mysql_db/m200000_000000_create_table_payments.php @@ -0,0 +1,21 @@ +createTable('{{%payments}}', [ + 'id' => $this->primaryKey(), + 'currency' => $this->text()->null(), + 'samples' => 'json NOT NULL', + ]); + } + + public function down() + { + $this->dropTable('{{%payments}}'); + } +} diff --git a/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/migrations_mysql_db/m200000_000001_create_table_samples.php b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/migrations_mysql_db/m200000_000001_create_table_samples.php new file mode 100644 index 00000000..b5b3a86c --- /dev/null +++ b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/migrations_mysql_db/m200000_000001_create_table_samples.php @@ -0,0 +1,20 @@ +createTable('{{%samples}}', [ + 'id' => $this->primaryKey(), + 'message' => $this->text()->null(), + ]); + } + + public function down() + { + $this->dropTable('{{%samples}}'); + } +} diff --git a/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/BaseModelFaker.php b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/BaseModelFaker.php new file mode 100644 index 00000000..c367fbb4 --- /dev/null +++ b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/BaseModelFaker.php @@ -0,0 +1,144 @@ +faker = FakerFactory::create(str_replace('-', '_', \Yii::$app->language)); + $this->uniqueFaker = new UniqueGenerator($this->faker); + } + + abstract public function generateModel($attributes = []); + + public function getFaker():Generator + { + return $this->faker; + } + + public function getUniqueFaker():UniqueGenerator + { + return $this->uniqueFaker; + } + + public function setFaker(Generator $faker):void + { + $this->faker = $faker; + } + + public function setUniqueFaker(UniqueGenerator $faker):void + { + $this->uniqueFaker = $faker; + } + + /** + * Generate and return model + * @param array|callable $attributes + * @param UniqueGenerator|null $uniqueFaker + * @return \yii\db\ActiveRecord + * @example MyFaker::makeOne(['user_id' => 1, 'title' => 'foo']); + * @example MyFaker::makeOne( function($model, $faker) { + * $model->scenario = 'create'; + * $model->setAttributes(['user_id' => 1, 'title' => $faker->sentence]); + * return $model; + * }); + */ + public static function makeOne($attributes = [], ?UniqueGenerator $uniqueFaker = null) + { + $fakeBuilder = new static(); + if ($uniqueFaker !== null) { + $fakeBuilder->setUniqueFaker($uniqueFaker); + } + $model = $fakeBuilder->generateModel($attributes); + return $model; + } + + /** + * Generate, save and return model + * @param array|callable $attributes + * @param UniqueGenerator|null $uniqueFaker + * @return \yii\db\ActiveRecord + * @example MyFaker::saveOne(['user_id' => 1, 'title' => 'foo']); + * @example MyFaker::saveOne( function($model, $faker) { + * $model->scenario = 'create'; + * $model->setAttributes(['user_id' => 1, 'title' => $faker->sentence]); + * return $model; + * }); + */ + public static function saveOne($attributes = [], ?UniqueGenerator $uniqueFaker = null) + { + $model = static::makeOne($attributes, $uniqueFaker); + $model->save(); + return $model; + } + + /** + * Generate and return multiple models + * @param int $number + * @param array|callable $commonAttributes + * @return \yii\db\ActiveRecord[]|array + * @example TaskFaker::make(5, ['project_id'=>1, 'user_id' => 2]); + * @example TaskFaker::make(5, function($model, $faker, $uniqueFaker) { + * $model->setAttributes(['name' => $uniqueFaker->username, 'state'=>$faker->boolean(20)]); + * return $model; + * }); + */ + public static function make(int $number, $commonAttributes = [], ?UniqueGenerator $uniqueFaker = null):array + { + if ($number < 1) { + return []; + } + $fakeBuilder = new static(); + if ($uniqueFaker !== null) { + $fakeBuilder->setUniqueFaker($uniqueFaker); + } + return array_map(function () use ($commonAttributes, $fakeBuilder) { + $model = $fakeBuilder->generateModel($commonAttributes); + return $model; + }, range(0, $number -1)); + } + + /** + * Generate, save and return multiple models + * @param int $number + * @param array|callable $commonAttributes + * @return \yii\db\ActiveRecord[]|array + * @example TaskFaker::save(5, ['project_id'=>1, 'user_id' => 2]); + * @example TaskFaker::save(5, function($model, $faker, $uniqueFaker) { + * $model->setAttributes(['name' => $uniqueFaker->username, 'state'=>$faker->boolean(20)]); + * return $model; + * }); + */ + public static function save(int $number, $commonAttributes = [], ?UniqueGenerator $uniqueFaker = null):array + { + if ($number < 1) { + return []; + } + $fakeBuilder = new static(); + if ($uniqueFaker !== null) { + $fakeBuilder->setUniqueFaker($uniqueFaker); + } + return array_map(function () use ($commonAttributes, $fakeBuilder) { + $model = $fakeBuilder->generateModel($commonAttributes); + $model->save(); + return $model; + }, range(0, $number -1)); + } +} diff --git a/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/Payments.php b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/Payments.php new file mode 100644 index 00000000..ea2262fe --- /dev/null +++ b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/Payments.php @@ -0,0 +1,10 @@ +generateModels(['author_id' => 1]); + * $model = (new PostFaker())->generateModels(function($model, $faker, $uniqueFaker) { + * $model->scenario = 'create'; + * $model->author_id = 1; + * return $model; + * }); + **/ + public function generateModel($attributes = []) + { + $faker = $this->faker; + $uniqueFaker = $this->uniqueFaker; + $model = new Payments(); + //$model->id = $uniqueFaker->numberBetween(0, 1000000); + $model->currency = $faker->currencyCode; + $model->samples = array_map(function () use ($faker, $uniqueFaker) { + return (new SampleFaker)->generateModel()->attributes; + }, range(1, 4)); + if (!is_callable($attributes)) { + $model->setAttributes($attributes, false); + } else { + $model = $attributes($model, $faker, $uniqueFaker); + } + return $model; + } +} diff --git a/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/Sample.php b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/Sample.php new file mode 100644 index 00000000..4e8b4547 --- /dev/null +++ b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/Sample.php @@ -0,0 +1,10 @@ +generateModels(['author_id' => 1]); + * $model = (new PostFaker())->generateModels(function($model, $faker, $uniqueFaker) { + * $model->scenario = 'create'; + * $model->author_id = 1; + * return $model; + * }); + **/ + public function generateModel($attributes = []) + { + $faker = $this->faker; + $uniqueFaker = $this->uniqueFaker; + $model = new Sample(); + //$model->id = $uniqueFaker->numberBetween(0, 1000000); + $model->message = $faker->sentence; + if (!is_callable($attributes)) { + $model->setAttributes($attributes, false); + } else { + $model = $attributes($model, $faker, $uniqueFaker); + } + return $model; + } +} diff --git a/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/base/Payments.php b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/base/Payments.php new file mode 100644 index 00000000..6e797741 --- /dev/null +++ b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/base/Payments.php @@ -0,0 +1,32 @@ + [['currency'], 'trim'], + 'currency_string' => [['currency'], 'string'], + 'safe' => [['samples'], 'safe'], + ]; + } +} diff --git a/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/base/Sample.php b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/base/Sample.php new file mode 100644 index 00000000..656ff1eb --- /dev/null +++ b/tests/specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql/models/base/Sample.php @@ -0,0 +1,30 @@ + [['message'], 'trim'], + 'message_string' => [['message'], 'string'], + ]; + } +} diff --git a/tests/specs/issue_fix/25_generate_inverse_relations/mysql/models/base/Account.php b/tests/specs/issue_fix/25_generate_inverse_relations/mysql/models/base/Account.php index d3846586..dc8c02f8 100644 --- a/tests/specs/issue_fix/25_generate_inverse_relations/mysql/models/base/Account.php +++ b/tests/specs/issue_fix/25_generate_inverse_relations/mysql/models/base/Account.php @@ -32,14 +32,14 @@ public function rules() return [ 'trim' => [['name', 'paymentMethodName'], 'trim'], 'required' => [['name'], 'required'], + 'name_string' => [['name'], 'string', 'max' => 128], + 'paymentMethodName_string' => [['paymentMethodName'], 'string'], 'user_id_integer' => [['user_id'], 'integer'], 'user_id_exist' => [['user_id'], 'exist', 'targetRelation' => 'user'], 'user2_id_integer' => [['user2_id'], 'integer'], 'user2_id_exist' => [['user2_id'], 'exist', 'targetRelation' => 'user2'], 'user3_integer' => [['user3'], 'integer'], 'user3_exist' => [['user3'], 'exist', 'targetRelation' => 'user3Rel'], - 'name_string' => [['name'], 'string', 'max' => 128], - 'paymentMethodName_string' => [['paymentMethodName'], 'string'], ]; } diff --git a/tests/specs/issue_fix/25_generate_inverse_relations/mysql/models/base/Menu.php b/tests/specs/issue_fix/25_generate_inverse_relations/mysql/models/base/Menu.php index 7f2eb9aa..5360d9cd 100644 --- a/tests/specs/issue_fix/25_generate_inverse_relations/mysql/models/base/Menu.php +++ b/tests/specs/issue_fix/25_generate_inverse_relations/mysql/models/base/Menu.php @@ -28,9 +28,9 @@ public function rules() return [ 'trim' => [['name'], 'trim'], 'required' => [['name'], 'required'], + 'name_string' => [['name'], 'string', 'min' => 3, 'max' => 100], 'parent_id_integer' => [['parent_id'], 'integer'], 'parent_id_exist' => [['parent_id'], 'exist', 'targetRelation' => 'parent'], - 'name_string' => [['name'], 'string', 'min' => 3, 'max' => 100], ]; } diff --git a/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/base/Post.php b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/base/Post.php index 3cc065c0..605dc271 100644 --- a/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/base/Post.php +++ b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/base/Post.php @@ -26,9 +26,9 @@ public function rules() { return [ 'trim' => [['content'], 'trim'], + 'content_string' => [['content'], 'string'], 'user_integer' => [['user'], 'integer'], 'user_exist' => [['user'], 'exist', 'targetRelation' => 'userRel'], - 'content_string' => [['content'], 'string'], ]; } diff --git a/tests/specs/issue_fix/3_bug_add_remove_property_and_at_the_same_time_change_it_at_x_indexes/mysql/models/base/Address.php b/tests/specs/issue_fix/3_bug_add_remove_property_and_at_the_same_time_change_it_at_x_indexes/mysql/models/base/Address.php index a429e822..fba0ce27 100644 --- a/tests/specs/issue_fix/3_bug_add_remove_property_and_at_the_same_time_change_it_at_x_indexes/mysql/models/base/Address.php +++ b/tests/specs/issue_fix/3_bug_add_remove_property_and_at_the_same_time_change_it_at_x_indexes/mysql/models/base/Address.php @@ -26,13 +26,13 @@ public function rules() { return [ 'trim' => [['name', 'shortName', 'postCode'], 'trim'], + 'name_string' => [['name'], 'string', 'max' => 64], + 'shortName_string' => [['shortName'], 'string', 'max' => 64], + 'postCode_string' => [['postCode'], 'string', 'max' => 64], 'shortName_postCode_unique' => [['shortName', 'postCode'], 'unique', 'targetAttribute' => [ 'shortName', 'postCode', ]], - 'name_string' => [['name'], 'string', 'max' => 64], - 'shortName_string' => [['shortName'], 'string', 'max' => 64], - 'postCode_string' => [['postCode'], 'string', 'max' => 64], ]; } } diff --git a/tests/specs/issue_fix/74_invalid_schema_reference_error/mysql/models/base/Invoice.php b/tests/specs/issue_fix/74_invalid_schema_reference_error/mysql/models/base/Invoice.php index d81c8ce3..e46064b8 100644 --- a/tests/specs/issue_fix/74_invalid_schema_reference_error/mysql/models/base/Invoice.php +++ b/tests/specs/issue_fix/74_invalid_schema_reference_error/mysql/models/base/Invoice.php @@ -23,13 +23,13 @@ public static function tableName() public function rules() { return [ + 'vat_rate_default' => [['vat_rate'], 'default', 'value' => 'standard'], 'required' => [['vat_rate'], 'required'], 'vat_rate_string' => [['vat_rate'], 'string'], 'vat_rate_in' => [['vat_rate'], 'in', 'range' => [ 'standard', 'none', ]], - 'vat_rate_default' => [['vat_rate'], 'default', 'value' => 'standard'], ]; } } diff --git a/tests/specs/issue_fix/74_invalid_schema_reference_error/mysql/models/base/Product.php b/tests/specs/issue_fix/74_invalid_schema_reference_error/mysql/models/base/Product.php index 184a6395..e83f3b9e 100644 --- a/tests/specs/issue_fix/74_invalid_schema_reference_error/mysql/models/base/Product.php +++ b/tests/specs/issue_fix/74_invalid_schema_reference_error/mysql/models/base/Product.php @@ -23,13 +23,13 @@ public static function tableName() public function rules() { return [ + 'vat_rate_default' => [['vat_rate'], 'default', 'value' => 'standard'], 'required' => [['vat_rate'], 'required'], 'vat_rate_string' => [['vat_rate'], 'string'], 'vat_rate_in' => [['vat_rate'], 'in', 'range' => [ 'standard', 'none', ]], - 'vat_rate_default' => [['vat_rate'], 'default', 'value' => 'standard'], ]; } } diff --git a/tests/specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/Product.json b/tests/specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/Product.json new file mode 100644 index 00000000..91514ab4 --- /dev/null +++ b/tests/specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/Product.json @@ -0,0 +1,22 @@ +{ + "title": "Product", + "x-table": "products", + "type": "object", + "required": [ + "id", + "vat_rate" + ], + "properties": { + "id": { + "type": "integer" + }, + "vat_rate": { + "type": "string", + "enum": [ + "standard", + "none" + ], + "default": "standard" + } + } +} \ No newline at end of file diff --git a/tests/specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/index.json b/tests/specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/index.json new file mode 100644 index 00000000..a879d24c --- /dev/null +++ b/tests/specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/index.json @@ -0,0 +1,39 @@ +{ + "openapi": "3.0.0", + "info": { + "version": "1.0.0", + "title": "\\#87" + }, + "paths": { + "/": { + "get": { + "responses": { + "200": { + "description": "The information" + } + } + } + } + }, + "components": { + "schemas": { + "Invoice": { + "type": "object", + "required": [ + "vat_rate" + ], + "properties": { + "id": { + "type": "integer" + }, + "vat_rate": { + "$ref": "./Product.json#/properties/vat_rate" + } + } + }, + "Product": { + "$ref": "./Product.json" + } + } + } +} \ No newline at end of file diff --git a/tests/specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/index.php b/tests/specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/index.php new file mode 100644 index 00000000..0fd4dc27 --- /dev/null +++ b/tests/specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/index.php @@ -0,0 +1,13 @@ + '@specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/index.json', + 'generateUrls' => false, + 'generateModels' => true, + 'excludeModels' => [ + 'Error', + ], + 'generateControllers' => false, + 'generateMigrations' => true, + 'generateModelFaker' => true, +]; diff --git a/tests/specs/issue_fix/model_name_more_than_once_in_faker_148/app/models/base/E123.php b/tests/specs/issue_fix/model_name_more_than_once_in_faker_148/app/models/base/E123.php index 74685405..f0f30935 100644 --- a/tests/specs/issue_fix/model_name_more_than_once_in_faker_148/app/models/base/E123.php +++ b/tests/specs/issue_fix/model_name_more_than_once_in_faker_148/app/models/base/E123.php @@ -30,13 +30,13 @@ public function rules() { return [ 'trim' => [['name'], 'trim'], + 'name_string' => [['name'], 'string'], 'account_id_integer' => [['account_id'], 'integer'], 'account_id_exist' => [['account_id'], 'exist', 'targetRelation' => 'account'], 'account_2_id_integer' => [['account_2_id'], 'integer'], 'account_2_id_exist' => [['account_2_id'], 'exist', 'targetRelation' => 'account2'], 'account_3_id_integer' => [['account_3_id'], 'integer'], 'account_3_id_exist' => [['account_3_id'], 'exist', 'targetRelation' => 'account3'], - 'name_string' => [['name'], 'string'], ]; } diff --git a/tests/specs/many2many/models/base/PostsGallery.php b/tests/specs/many2many/models/base/PostsGallery.php index 30e01949..f92d0508 100644 --- a/tests/specs/many2many/models/base/PostsGallery.php +++ b/tests/specs/many2many/models/base/PostsGallery.php @@ -26,11 +26,11 @@ public static function tableName() public function rules() { return [ + 'is_cover_boolean' => [['is_cover'], 'boolean'], 'image_id_integer' => [['image_id'], 'integer'], 'image_id_exist' => [['image_id'], 'exist', 'targetRelation' => 'image'], 'article_id_integer' => [['article_id'], 'integer'], 'article_id_exist' => [['article_id'], 'exist', 'targetRelation' => 'article'], - 'is_cover_boolean' => [['is_cover'], 'boolean'], ]; } diff --git a/tests/specs/menu/models/base/Menu.php b/tests/specs/menu/models/base/Menu.php index 4c5f0fa0..db5a24da 100644 --- a/tests/specs/menu/models/base/Menu.php +++ b/tests/specs/menu/models/base/Menu.php @@ -29,10 +29,6 @@ public function rules() { return [ 'trim' => [['name'], 'trim'], - 'required' => [['name'], 'required'], - 'parent_id_integer' => [['parent_id'], 'integer'], - 'parent_id_exist' => [['parent_id'], 'exist', 'targetRelation' => 'parent'], - 'name_string' => [['name'], 'string', 'min' => 3, 'max' => 100], 'args_default' => [['args'], 'default', 'value' => [ 'foo', 'bar', @@ -46,6 +42,10 @@ public function rules() 'buzz' => 'fizz', ], ]], + 'required' => [['name'], 'required'], + 'name_string' => [['name'], 'string', 'min' => 3, 'max' => 100], + 'parent_id_integer' => [['parent_id'], 'integer'], + 'parent_id_exist' => [['parent_id'], 'exist', 'targetRelation' => 'parent'], 'safe' => [['args', 'kwargs'], 'safe'], ]; } diff --git a/tests/specs/petstore/models/base/Pet.php b/tests/specs/petstore/models/base/Pet.php index b461998d..eb6fc009 100644 --- a/tests/specs/petstore/models/base/Pet.php +++ b/tests/specs/petstore/models/base/Pet.php @@ -28,10 +28,10 @@ public function rules() return [ 'trim' => [['name', 'tag'], 'trim'], 'required' => [['name'], 'required'], - 'store_id_integer' => [['store_id'], 'integer'], - 'store_id_exist' => [['store_id'], 'exist', 'targetRelation' => 'store'], 'name_string' => [['name'], 'string'], 'tag_string' => [['tag'], 'string'], + 'store_id_integer' => [['store_id'], 'integer'], + 'store_id_exist' => [['store_id'], 'exist', 'targetRelation' => 'store'], ]; } diff --git a/tests/specs/petstore_jsonapi/models/base/PetStatistic.php b/tests/specs/petstore_jsonapi/models/base/PetStatistic.php index adc6e8fd..444acfac 100644 --- a/tests/specs/petstore_jsonapi/models/base/PetStatistic.php +++ b/tests/specs/petstore_jsonapi/models/base/PetStatistic.php @@ -53,12 +53,12 @@ public function rules() { return [ 'trim' => [['title', 'summary'], 'trim'], - 'parentPet_id_integer' => [['parentPet_id'], 'integer'], - 'parentPet_id_exist' => [['parentPet_id'], 'exist', 'targetRelation' => 'parentPet'], 'title_string' => [['title'], 'string'], 'dogsCount_integer' => [['dogsCount'], 'integer'], 'catsCount_integer' => [['catsCount'], 'integer'], 'summary_string' => [['summary'], 'string'], + 'parentPet_id_integer' => [['parentPet_id'], 'integer'], + 'parentPet_id_exist' => [['parentPet_id'], 'exist', 'targetRelation' => 'parentPet'], ]; } } diff --git a/tests/specs/petstore_namespace/mymodels/base/Pet.php b/tests/specs/petstore_namespace/mymodels/base/Pet.php index e631edf5..4ab206a3 100644 --- a/tests/specs/petstore_namespace/mymodels/base/Pet.php +++ b/tests/specs/petstore_namespace/mymodels/base/Pet.php @@ -28,10 +28,10 @@ public function rules() return [ 'trim' => [['name', 'tag'], 'trim'], 'required' => [['name'], 'required'], - 'store_id_integer' => [['store_id'], 'integer'], - 'store_id_exist' => [['store_id'], 'exist', 'targetRelation' => 'store'], 'name_string' => [['name'], 'string'], 'tag_string' => [['tag'], 'string'], + 'store_id_integer' => [['store_id'], 'integer'], + 'store_id_exist' => [['store_id'], 'exist', 'targetRelation' => 'store'], ]; } diff --git a/tests/specs/postgres_custom/models/base/Custom.php b/tests/specs/postgres_custom/models/base/Custom.php index aa1eedd7..9f13aace 100644 --- a/tests/specs/postgres_custom/models/base/Custom.php +++ b/tests/specs/postgres_custom/models/base/Custom.php @@ -30,7 +30,6 @@ public static function tableName() public function rules() { return [ - 'num_integer' => [['num'], 'integer'], 'num_default' => [['num'], 'default', 'value' => 0], 'json1_default' => [['json1'], 'default', 'value' => []], 'json2_default' => [['json2'], 'default', 'value' => []], @@ -46,18 +45,19 @@ public function rules() 'foo' => 'bar', 'bar' => 'baz', ]], + 'status_default' => [['status'], 'default', 'value' => 'draft'], + 'status_x_default' => [['status_x'], 'default', 'value' => 'draft'], + 'num_integer' => [['num'], 'integer'], 'status_string' => [['status'], 'string'], 'status_in' => [['status'], 'in', 'range' => [ 'active', 'draft', ]], - 'status_default' => [['status'], 'default', 'value' => 'draft'], 'status_x_string' => [['status_x'], 'string', 'max' => 10], 'status_x_in' => [['status_x'], 'in', 'range' => [ 'active', 'draft', ]], - 'status_x_default' => [['status_x'], 'default', 'value' => 'draft'], 'safe' => [['json1', 'json2', 'json3', 'json4'], 'safe'], ]; } diff --git a/tests/specs/relations_in_faker/app/models/base/A123.php b/tests/specs/relations_in_faker/app/models/base/A123.php index 9be6a778..0c733222 100644 --- a/tests/specs/relations_in_faker/app/models/base/A123.php +++ b/tests/specs/relations_in_faker/app/models/base/A123.php @@ -26,9 +26,9 @@ public function rules() { return [ 'trim' => [['name'], 'trim'], + 'name_string' => [['name'], 'string'], 'b123_id_integer' => [['b123_id'], 'integer'], 'b123_id_exist' => [['b123_id'], 'exist', 'targetRelation' => 'b123'], - 'name_string' => [['name'], 'string'], ]; } diff --git a/tests/specs/relations_in_faker/app/models/base/B123.php b/tests/specs/relations_in_faker/app/models/base/B123.php index f85ffee5..7ad4eb77 100644 --- a/tests/specs/relations_in_faker/app/models/base/B123.php +++ b/tests/specs/relations_in_faker/app/models/base/B123.php @@ -26,9 +26,9 @@ public function rules() { return [ 'trim' => [['name'], 'trim'], + 'name_string' => [['name'], 'string'], 'c123_id_integer' => [['c123_id'], 'integer'], 'c123_id_exist' => [['c123_id'], 'exist', 'targetRelation' => 'c123'], - 'name_string' => [['name'], 'string'], ]; } diff --git a/tests/specs/relations_in_faker/app/models/base/Domain.php b/tests/specs/relations_in_faker/app/models/base/Domain.php index e6ed86e2..df6e0822 100644 --- a/tests/specs/relations_in_faker/app/models/base/Domain.php +++ b/tests/specs/relations_in_faker/app/models/base/Domain.php @@ -29,9 +29,9 @@ public function rules() return [ 'trim' => [['name'], 'trim'], 'required' => [['name', 'account_id'], 'required'], + 'name_string' => [['name'], 'string', 'max' => 128], 'account_id_integer' => [['account_id'], 'integer'], 'account_id_exist' => [['account_id'], 'exist', 'targetRelation' => 'account'], - 'name_string' => [['name'], 'string', 'max' => 128], ]; } diff --git a/tests/specs/relations_in_faker/app/models/base/E123.php b/tests/specs/relations_in_faker/app/models/base/E123.php index cefdb5ce..eb950129 100644 --- a/tests/specs/relations_in_faker/app/models/base/E123.php +++ b/tests/specs/relations_in_faker/app/models/base/E123.php @@ -26,9 +26,9 @@ public function rules() { return [ 'trim' => [['name'], 'trim'], + 'name_string' => [['name'], 'string'], 'b123_id_integer' => [['b123_id'], 'integer'], 'b123_id_exist' => [['b123_id'], 'exist', 'targetRelation' => 'b123'], - 'name_string' => [['name'], 'string'], ]; } diff --git a/tests/specs/relations_in_faker/app/models/base/Routing.php b/tests/specs/relations_in_faker/app/models/base/Routing.php index 53e428e1..f61885fc 100644 --- a/tests/specs/relations_in_faker/app/models/base/Routing.php +++ b/tests/specs/relations_in_faker/app/models/base/Routing.php @@ -35,16 +35,16 @@ public function rules() return [ 'trim' => [['path', 'service'], 'trim'], 'required' => [['domain_id'], 'required'], + 'path_string' => [['path'], 'string', 'max' => 255], + 'ssl_boolean' => [['ssl'], 'boolean'], + 'redirect_to_ssl_boolean' => [['redirect_to_ssl'], 'boolean'], + 'service_string' => [['service'], 'string', 'max' => 255], 'domain_id_integer' => [['domain_id'], 'integer'], 'domain_id_exist' => [['domain_id'], 'exist', 'targetRelation' => 'domain'], 'd123_id_integer' => [['d123_id'], 'integer'], 'd123_id_exist' => [['d123_id'], 'exist', 'targetRelation' => 'd123'], 'a123_id_integer' => [['a123_id'], 'integer'], 'a123_id_exist' => [['a123_id'], 'exist', 'targetRelation' => 'a123'], - 'path_string' => [['path'], 'string', 'max' => 255], - 'ssl_boolean' => [['ssl'], 'boolean'], - 'redirect_to_ssl_boolean' => [['redirect_to_ssl'], 'boolean'], - 'service_string' => [['service'], 'string', 'max' => 255], ]; } diff --git a/tests/specs/x_db_default_expression/maria/edit/app/models/base/Fruit.php b/tests/specs/x_db_default_expression/maria/edit/app/models/base/Fruit.php index 77c97900..adea7459 100644 --- a/tests/specs/x_db_default_expression/maria/edit/app/models/base/Fruit.php +++ b/tests/specs/x_db_default_expression/maria/edit/app/models/base/Fruit.php @@ -32,26 +32,26 @@ public function rules() { return [ 'trim' => [['ts', 'ts2', 'ts3', 'ts4', 'ts5', 'ts6', 'd', 'd2', 'd3', 'ts7'], 'trim'], - 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts_default' => [['ts'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts2_default' => [['ts2'], 'default', 'value' => '2011-11-11 00:00:00'], - 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts3_default' => [['ts3'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts4_string' => [['ts4'], 'string'], 'ts4_default' => [['ts4'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts5_string' => [['ts5'], 'string'], 'ts5_default' => [['ts5'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts6_string' => [['ts6'], 'string'], 'ts6_default' => [['ts6'], 'default', 'value' => '2000-11-11 00:00:00'], - 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], 'd_default' => [['d'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd2_string' => [['d2'], 'string'], 'd2_default' => [['d2'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd3_string' => [['d3'], 'string'], 'd3_default' => [['d3'], 'default', 'value' => 'text default'], - 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], 'ts7_default' => [['ts7'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], + 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts4_string' => [['ts4'], 'string'], + 'ts5_string' => [['ts5'], 'string'], + 'ts6_string' => [['ts6'], 'string'], + 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], + 'd2_string' => [['d2'], 'string'], + 'd3_string' => [['d3'], 'string'], + 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], ]; } } diff --git a/tests/specs/x_db_default_expression/maria/edit_expression/app/models/base/Fruit.php b/tests/specs/x_db_default_expression/maria/edit_expression/app/models/base/Fruit.php index 77c97900..adea7459 100644 --- a/tests/specs/x_db_default_expression/maria/edit_expression/app/models/base/Fruit.php +++ b/tests/specs/x_db_default_expression/maria/edit_expression/app/models/base/Fruit.php @@ -32,26 +32,26 @@ public function rules() { return [ 'trim' => [['ts', 'ts2', 'ts3', 'ts4', 'ts5', 'ts6', 'd', 'd2', 'd3', 'ts7'], 'trim'], - 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts_default' => [['ts'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts2_default' => [['ts2'], 'default', 'value' => '2011-11-11 00:00:00'], - 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts3_default' => [['ts3'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts4_string' => [['ts4'], 'string'], 'ts4_default' => [['ts4'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts5_string' => [['ts5'], 'string'], 'ts5_default' => [['ts5'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts6_string' => [['ts6'], 'string'], 'ts6_default' => [['ts6'], 'default', 'value' => '2000-11-11 00:00:00'], - 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], 'd_default' => [['d'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd2_string' => [['d2'], 'string'], 'd2_default' => [['d2'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd3_string' => [['d3'], 'string'], 'd3_default' => [['d3'], 'default', 'value' => 'text default'], - 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], 'ts7_default' => [['ts7'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], + 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts4_string' => [['ts4'], 'string'], + 'ts5_string' => [['ts5'], 'string'], + 'ts6_string' => [['ts6'], 'string'], + 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], + 'd2_string' => [['d2'], 'string'], + 'd3_string' => [['d3'], 'string'], + 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], ]; } } diff --git a/tests/specs/x_db_default_expression/maria/simple/app/models/base/Fruit.php b/tests/specs/x_db_default_expression/maria/simple/app/models/base/Fruit.php index 77c97900..adea7459 100644 --- a/tests/specs/x_db_default_expression/maria/simple/app/models/base/Fruit.php +++ b/tests/specs/x_db_default_expression/maria/simple/app/models/base/Fruit.php @@ -32,26 +32,26 @@ public function rules() { return [ 'trim' => [['ts', 'ts2', 'ts3', 'ts4', 'ts5', 'ts6', 'd', 'd2', 'd3', 'ts7'], 'trim'], - 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts_default' => [['ts'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts2_default' => [['ts2'], 'default', 'value' => '2011-11-11 00:00:00'], - 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts3_default' => [['ts3'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts4_string' => [['ts4'], 'string'], 'ts4_default' => [['ts4'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts5_string' => [['ts5'], 'string'], 'ts5_default' => [['ts5'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts6_string' => [['ts6'], 'string'], 'ts6_default' => [['ts6'], 'default', 'value' => '2000-11-11 00:00:00'], - 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], 'd_default' => [['d'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd2_string' => [['d2'], 'string'], 'd2_default' => [['d2'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd3_string' => [['d3'], 'string'], 'd3_default' => [['d3'], 'default', 'value' => 'text default'], - 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], 'ts7_default' => [['ts7'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], + 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts4_string' => [['ts4'], 'string'], + 'ts5_string' => [['ts5'], 'string'], + 'ts6_string' => [['ts6'], 'string'], + 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], + 'd2_string' => [['d2'], 'string'], + 'd3_string' => [['d3'], 'string'], + 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], ]; } } diff --git a/tests/specs/x_db_default_expression/mysql/edit/app/models/base/Fruit.php b/tests/specs/x_db_default_expression/mysql/edit/app/models/base/Fruit.php index 77c97900..adea7459 100644 --- a/tests/specs/x_db_default_expression/mysql/edit/app/models/base/Fruit.php +++ b/tests/specs/x_db_default_expression/mysql/edit/app/models/base/Fruit.php @@ -32,26 +32,26 @@ public function rules() { return [ 'trim' => [['ts', 'ts2', 'ts3', 'ts4', 'ts5', 'ts6', 'd', 'd2', 'd3', 'ts7'], 'trim'], - 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts_default' => [['ts'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts2_default' => [['ts2'], 'default', 'value' => '2011-11-11 00:00:00'], - 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts3_default' => [['ts3'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts4_string' => [['ts4'], 'string'], 'ts4_default' => [['ts4'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts5_string' => [['ts5'], 'string'], 'ts5_default' => [['ts5'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts6_string' => [['ts6'], 'string'], 'ts6_default' => [['ts6'], 'default', 'value' => '2000-11-11 00:00:00'], - 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], 'd_default' => [['d'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd2_string' => [['d2'], 'string'], 'd2_default' => [['d2'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd3_string' => [['d3'], 'string'], 'd3_default' => [['d3'], 'default', 'value' => 'text default'], - 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], 'ts7_default' => [['ts7'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], + 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts4_string' => [['ts4'], 'string'], + 'ts5_string' => [['ts5'], 'string'], + 'ts6_string' => [['ts6'], 'string'], + 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], + 'd2_string' => [['d2'], 'string'], + 'd3_string' => [['d3'], 'string'], + 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], ]; } } diff --git a/tests/specs/x_db_default_expression/mysql/edit_expression/app/models/base/Fruit.php b/tests/specs/x_db_default_expression/mysql/edit_expression/app/models/base/Fruit.php index 77c97900..adea7459 100644 --- a/tests/specs/x_db_default_expression/mysql/edit_expression/app/models/base/Fruit.php +++ b/tests/specs/x_db_default_expression/mysql/edit_expression/app/models/base/Fruit.php @@ -32,26 +32,26 @@ public function rules() { return [ 'trim' => [['ts', 'ts2', 'ts3', 'ts4', 'ts5', 'ts6', 'd', 'd2', 'd3', 'ts7'], 'trim'], - 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts_default' => [['ts'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts2_default' => [['ts2'], 'default', 'value' => '2011-11-11 00:00:00'], - 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts3_default' => [['ts3'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts4_string' => [['ts4'], 'string'], 'ts4_default' => [['ts4'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts5_string' => [['ts5'], 'string'], 'ts5_default' => [['ts5'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts6_string' => [['ts6'], 'string'], 'ts6_default' => [['ts6'], 'default', 'value' => '2000-11-11 00:00:00'], - 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], 'd_default' => [['d'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd2_string' => [['d2'], 'string'], 'd2_default' => [['d2'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd3_string' => [['d3'], 'string'], 'd3_default' => [['d3'], 'default', 'value' => 'text default'], - 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], 'ts7_default' => [['ts7'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], + 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts4_string' => [['ts4'], 'string'], + 'ts5_string' => [['ts5'], 'string'], + 'ts6_string' => [['ts6'], 'string'], + 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], + 'd2_string' => [['d2'], 'string'], + 'd3_string' => [['d3'], 'string'], + 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], ]; } } diff --git a/tests/specs/x_db_default_expression/mysql/simple/app/models/base/Fruit.php b/tests/specs/x_db_default_expression/mysql/simple/app/models/base/Fruit.php index 77c97900..adea7459 100644 --- a/tests/specs/x_db_default_expression/mysql/simple/app/models/base/Fruit.php +++ b/tests/specs/x_db_default_expression/mysql/simple/app/models/base/Fruit.php @@ -32,26 +32,26 @@ public function rules() { return [ 'trim' => [['ts', 'ts2', 'ts3', 'ts4', 'ts5', 'ts6', 'd', 'd2', 'd3', 'ts7'], 'trim'], - 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts_default' => [['ts'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts2_default' => [['ts2'], 'default', 'value' => '2011-11-11 00:00:00'], - 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts3_default' => [['ts3'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts4_string' => [['ts4'], 'string'], 'ts4_default' => [['ts4'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts5_string' => [['ts5'], 'string'], 'ts5_default' => [['ts5'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts6_string' => [['ts6'], 'string'], 'ts6_default' => [['ts6'], 'default', 'value' => '2000-11-11 00:00:00'], - 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], 'd_default' => [['d'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd2_string' => [['d2'], 'string'], 'd2_default' => [['d2'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd3_string' => [['d3'], 'string'], 'd3_default' => [['d3'], 'default', 'value' => 'text default'], - 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], 'ts7_default' => [['ts7'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], + 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts4_string' => [['ts4'], 'string'], + 'ts5_string' => [['ts5'], 'string'], + 'ts6_string' => [['ts6'], 'string'], + 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], + 'd2_string' => [['d2'], 'string'], + 'd3_string' => [['d3'], 'string'], + 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], ]; } } diff --git a/tests/specs/x_db_default_expression/pgsql/edit/app/models/base/Fruit.php b/tests/specs/x_db_default_expression/pgsql/edit/app/models/base/Fruit.php index 77c97900..adea7459 100644 --- a/tests/specs/x_db_default_expression/pgsql/edit/app/models/base/Fruit.php +++ b/tests/specs/x_db_default_expression/pgsql/edit/app/models/base/Fruit.php @@ -32,26 +32,26 @@ public function rules() { return [ 'trim' => [['ts', 'ts2', 'ts3', 'ts4', 'ts5', 'ts6', 'd', 'd2', 'd3', 'ts7'], 'trim'], - 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts_default' => [['ts'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts2_default' => [['ts2'], 'default', 'value' => '2011-11-11 00:00:00'], - 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts3_default' => [['ts3'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts4_string' => [['ts4'], 'string'], 'ts4_default' => [['ts4'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts5_string' => [['ts5'], 'string'], 'ts5_default' => [['ts5'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts6_string' => [['ts6'], 'string'], 'ts6_default' => [['ts6'], 'default', 'value' => '2000-11-11 00:00:00'], - 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], 'd_default' => [['d'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd2_string' => [['d2'], 'string'], 'd2_default' => [['d2'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd3_string' => [['d3'], 'string'], 'd3_default' => [['d3'], 'default', 'value' => 'text default'], - 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], 'ts7_default' => [['ts7'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], + 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts4_string' => [['ts4'], 'string'], + 'ts5_string' => [['ts5'], 'string'], + 'ts6_string' => [['ts6'], 'string'], + 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], + 'd2_string' => [['d2'], 'string'], + 'd3_string' => [['d3'], 'string'], + 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], ]; } } diff --git a/tests/specs/x_db_default_expression/pgsql/edit_expression/app/models/base/Fruit.php b/tests/specs/x_db_default_expression/pgsql/edit_expression/app/models/base/Fruit.php index 77c97900..adea7459 100644 --- a/tests/specs/x_db_default_expression/pgsql/edit_expression/app/models/base/Fruit.php +++ b/tests/specs/x_db_default_expression/pgsql/edit_expression/app/models/base/Fruit.php @@ -32,26 +32,26 @@ public function rules() { return [ 'trim' => [['ts', 'ts2', 'ts3', 'ts4', 'ts5', 'ts6', 'd', 'd2', 'd3', 'ts7'], 'trim'], - 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts_default' => [['ts'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts2_default' => [['ts2'], 'default', 'value' => '2011-11-11 00:00:00'], - 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts3_default' => [['ts3'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts4_string' => [['ts4'], 'string'], 'ts4_default' => [['ts4'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts5_string' => [['ts5'], 'string'], 'ts5_default' => [['ts5'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts6_string' => [['ts6'], 'string'], 'ts6_default' => [['ts6'], 'default', 'value' => '2000-11-11 00:00:00'], - 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], 'd_default' => [['d'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd2_string' => [['d2'], 'string'], 'd2_default' => [['d2'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd3_string' => [['d3'], 'string'], 'd3_default' => [['d3'], 'default', 'value' => 'text default'], - 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], 'ts7_default' => [['ts7'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], + 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts4_string' => [['ts4'], 'string'], + 'ts5_string' => [['ts5'], 'string'], + 'ts6_string' => [['ts6'], 'string'], + 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], + 'd2_string' => [['d2'], 'string'], + 'd3_string' => [['d3'], 'string'], + 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], ]; } } diff --git a/tests/specs/x_db_default_expression/pgsql/simple/app/models/base/Fruit.php b/tests/specs/x_db_default_expression/pgsql/simple/app/models/base/Fruit.php index 77c97900..adea7459 100644 --- a/tests/specs/x_db_default_expression/pgsql/simple/app/models/base/Fruit.php +++ b/tests/specs/x_db_default_expression/pgsql/simple/app/models/base/Fruit.php @@ -32,26 +32,26 @@ public function rules() { return [ 'trim' => [['ts', 'ts2', 'ts3', 'ts4', 'ts5', 'ts6', 'd', 'd2', 'd3', 'ts7'], 'trim'], - 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts_default' => [['ts'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts2_default' => [['ts2'], 'default', 'value' => '2011-11-11 00:00:00'], - 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'ts3_default' => [['ts3'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts4_string' => [['ts4'], 'string'], 'ts4_default' => [['ts4'], 'default', 'value' => '2022-11-11 00:00:00'], - 'ts5_string' => [['ts5'], 'string'], 'ts5_default' => [['ts5'], 'default', 'value' => new \yii\db\Expression("(CURRENT_TIMESTAMP)")], - 'ts6_string' => [['ts6'], 'string'], 'ts6_default' => [['ts6'], 'default', 'value' => '2000-11-11 00:00:00'], - 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], 'd_default' => [['d'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd2_string' => [['d2'], 'string'], 'd2_default' => [['d2'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], - 'd3_string' => [['d3'], 'string'], 'd3_default' => [['d3'], 'default', 'value' => 'text default'], - 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], 'ts7_default' => [['ts7'], 'default', 'value' => new \yii\db\Expression("(CURRENT_DATE + INTERVAL 1 YEAR)")], + 'ts_datetime' => [['ts'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts2_datetime' => [['ts2'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts3_datetime' => [['ts3'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + 'ts4_string' => [['ts4'], 'string'], + 'ts5_string' => [['ts5'], 'string'], + 'ts6_string' => [['ts6'], 'string'], + 'd_date' => [['d'], 'date', 'format' => 'php:Y-m-d'], + 'd2_string' => [['d2'], 'string'], + 'd3_string' => [['d3'], 'string'], + 'ts7_date' => [['ts7'], 'date', 'format' => 'php:Y-m-d'], ]; } } diff --git a/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Alldbdatatype.php b/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Alldbdatatype.php index 4d0fe38b..dbbd7ebc 100644 --- a/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Alldbdatatype.php +++ b/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Alldbdatatype.php @@ -66,6 +66,15 @@ public function rules() { return [ 'trim' => [['string_col', 'varchar_col', 'text_col', 'varchar_4_col', 'char_4_col', 'char_5_col', 'char_6_col', 'char_7_col', 'char_8_col', 'date_col', 'time_col', 'datetime_col', 'timestamp_col', 'year_col', 'text_def'], 'trim'], + 'char_8_col_default' => [['char_8_col'], 'default', 'value' => 'd'], + 'mi_default' => [['mi'], 'default', 'value' => 7], + 'json_col_def_default' => [['json_col_def'], 'default', 'value' => []], + 'json_col_def_2_default' => [['json_col_def_2'], 'default', 'value' => []], + 'blob_def_default' => [['blob_def'], 'default', 'value' => 'the blob'], + 'text_def_default' => [['text_def'], 'default', 'value' => 'the text'], + 'json_def_default' => [['json_def'], 'default', 'value' => [ + 'a' => 'b', + ]], 'required' => [['char_6_col', 'char_7_col'], 'required'], 'string_col_string' => [['string_col'], 'string', 'max' => 255], 'varchar_col_string' => [['varchar_col'], 'string', 'max' => 132], @@ -76,7 +85,6 @@ public function rules() 'char_6_col_string' => [['char_6_col'], 'string'], 'char_7_col_string' => [['char_7_col'], 'string', 'max' => 6], 'char_8_col_string' => [['char_8_col'], 'string'], - 'char_8_col_default' => [['char_8_col'], 'default', 'value' => 'd'], 'decimal_col_double' => [['decimal_col'], 'double'], 'bit_col_integer' => [['bit_col'], 'integer'], 'bit_2_integer' => [['bit_2'], 'integer'], @@ -87,7 +95,6 @@ public function rules() 'si_col_integer' => [['si_col'], 'integer'], 'si_col_2_integer' => [['si_col_2'], 'integer'], 'mi_integer' => [['mi'], 'integer'], - 'mi_default' => [['mi'], 'default', 'value' => 7], 'bi_integer' => [['bi'], 'integer'], 'int_col_integer' => [['int_col'], 'integer'], 'int_col_2_integer' => [['int_col_2'], 'integer'], @@ -104,14 +111,7 @@ public function rules() 'datetime_col_datetime' => [['datetime_col'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'timestamp_col_string' => [['timestamp_col'], 'string'], 'year_col_string' => [['year_col'], 'string'], - 'json_col_def_default' => [['json_col_def'], 'default', 'value' => []], - 'json_col_def_2_default' => [['json_col_def_2'], 'default', 'value' => []], - 'blob_def_default' => [['blob_def'], 'default', 'value' => 'the blob'], 'text_def_string' => [['text_def'], 'string'], - 'text_def_default' => [['text_def'], 'default', 'value' => 'the text'], - 'json_def_default' => [['json_def'], 'default', 'value' => [ - 'a' => 'b', - ]], 'safe' => [['varbinary_col', 'blob_col', 'json_col', 'json_col_def', 'json_col_def_2', 'blob_def', 'json_def'], 'safe'], ]; } diff --git a/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Editcolumn.php b/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Editcolumn.php index ee4bed5b..acaa29cf 100644 --- a/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Editcolumn.php +++ b/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Editcolumn.php @@ -34,21 +34,21 @@ public function rules() { return [ 'trim' => [['name', 'tag', 'first_name', 'string_col', 'str_col_def', 'json_col'], 'trim'], + 'name_default' => [['name'], 'default', 'value' => 'Horse-2'], + 'dec_col_default' => [['dec_col'], 'default', 'value' => 3.14], + 'json_col_default' => [['json_col'], 'default', 'value' => 'fox jumps over dog'], + 'json_col_2_default' => [['json_col_2'], 'default', 'value' => []], + 'json_col_def_n_default' => [['json_col_def_n'], 'default', 'value' => []], + 'json_col_def_n_2_default' => [['json_col_def_n_2'], 'default', 'value' => []], 'required' => [['name', 'str_col_def', 'json_col', 'json_col_2'], 'required'], 'name_string' => [['name'], 'string', 'max' => 254], - 'name_default' => [['name'], 'default', 'value' => 'Horse-2'], 'tag_string' => [['tag'], 'string'], 'first_name_string' => [['first_name'], 'string', 'max' => 255], 'string_col_string' => [['string_col'], 'string'], 'dec_col_double' => [['dec_col'], 'double'], - 'dec_col_default' => [['dec_col'], 'default', 'value' => 3.14], 'str_col_def_string' => [['str_col_def'], 'string', 'max' => 3], 'json_col_string' => [['json_col'], 'string'], - 'json_col_default' => [['json_col'], 'default', 'value' => 'fox jumps over dog'], - 'json_col_2_default' => [['json_col_2'], 'default', 'value' => []], 'numeric_col_double' => [['numeric_col'], 'double'], - 'json_col_def_n_default' => [['json_col_def_n'], 'default', 'value' => []], - 'json_col_def_n_2_default' => [['json_col_def_n_2'], 'default', 'value' => []], 'safe' => [['json_col_2', 'json_col_def_n', 'json_col_def_n_2'], 'safe'], ]; } diff --git a/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Newcolumn.php b/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Newcolumn.php index b7abc1fb..15e18ee2 100644 --- a/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Newcolumn.php +++ b/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Newcolumn.php @@ -30,13 +30,13 @@ public function rules() { return [ 'trim' => [['name', 'last_name', 'varchar_col'], 'trim'], + 'json_col_def_n_default' => [['json_col_def_n'], 'default', 'value' => []], 'required' => [['name'], 'required'], 'name_string' => [['name'], 'string', 'max' => 255], 'last_name_string' => [['last_name'], 'string'], 'dec_col_double' => [['dec_col'], 'double'], 'varchar_col_string' => [['varchar_col'], 'string', 'max' => 5], 'numeric_col_double' => [['numeric_col'], 'double'], - 'json_col_def_n_default' => [['json_col_def_n'], 'default', 'value' => []], 'safe' => [['json_col', 'json_col_def_n'], 'safe'], ]; } diff --git a/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Pristine.php b/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Pristine.php index dba4f363..fb393cc0 100644 --- a/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Pristine.php +++ b/tests/specs/x_db_type/rules_and_more/maria/app/models/mariamodel/base/Pristine.php @@ -34,11 +34,12 @@ public function rules() { return [ 'trim' => [['name', 'tag', 'new_col', 'col_9', 'col_10', 'col_11'], 'trim'], + 'tag_default' => [['tag'], 'default', 'value' => '4 leg'], + 'price_default' => [['price'], 'default', 'value' => 0], 'required' => [['custom_id_col', 'name'], 'required'], 'custom_id_col_integer' => [['custom_id_col'], 'integer'], 'name_string' => [['name'], 'string'], 'tag_string' => [['tag'], 'string'], - 'tag_default' => [['tag'], 'default', 'value' => '4 leg'], 'new_col_string' => [['new_col'], 'string', 'max' => 17], 'col_5_double' => [['col_5'], 'double'], 'col_6_double' => [['col_6'], 'double'], @@ -47,7 +48,6 @@ public function rules() 'col_10_string' => [['col_10'], 'string', 'max' => 10], 'col_11_string' => [['col_11'], 'string'], 'price_double' => [['price'], 'double'], - 'price_default' => [['price'], 'default', 'value' => 0], 'safe' => [['col_8'], 'safe'], ]; } diff --git a/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Alldbdatatype.php b/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Alldbdatatype.php index 35dd25ef..a9e08518 100644 --- a/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Alldbdatatype.php +++ b/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Alldbdatatype.php @@ -66,6 +66,15 @@ public function rules() { return [ 'trim' => [['string_col', 'varchar_col', 'text_col', 'varchar_4_col', 'char_4_col', 'char_5_col', 'char_6_col', 'char_7_col', 'char_8_col', 'date_col', 'time_col', 'datetime_col', 'timestamp_col', 'year_col', 'text_def'], 'trim'], + 'char_8_col_default' => [['char_8_col'], 'default', 'value' => 'd'], + 'mi_default' => [['mi'], 'default', 'value' => 7], + 'json_col_def_default' => [['json_col_def'], 'default', 'value' => []], + 'json_col_def_2_default' => [['json_col_def_2'], 'default', 'value' => []], + 'blob_def_default' => [['blob_def'], 'default', 'value' => 'the blob'], + 'text_def_default' => [['text_def'], 'default', 'value' => 'the text'], + 'json_def_default' => [['json_def'], 'default', 'value' => [ + 'a' => 'b', + ]], 'required' => [['char_6_col', 'char_7_col'], 'required'], 'string_col_string' => [['string_col'], 'string', 'max' => 255], 'varchar_col_string' => [['varchar_col'], 'string', 'max' => 132], @@ -76,7 +85,6 @@ public function rules() 'char_6_col_string' => [['char_6_col'], 'string'], 'char_7_col_string' => [['char_7_col'], 'string', 'max' => 6], 'char_8_col_string' => [['char_8_col'], 'string'], - 'char_8_col_default' => [['char_8_col'], 'default', 'value' => 'd'], 'decimal_col_double' => [['decimal_col'], 'double'], 'bit_col_integer' => [['bit_col'], 'integer'], 'bit_2_integer' => [['bit_2'], 'integer'], @@ -87,7 +95,6 @@ public function rules() 'si_col_integer' => [['si_col'], 'integer'], 'si_col_2_integer' => [['si_col_2'], 'integer'], 'mi_integer' => [['mi'], 'integer'], - 'mi_default' => [['mi'], 'default', 'value' => 7], 'bi_integer' => [['bi'], 'integer'], 'int_col_integer' => [['int_col'], 'integer'], 'int_col_2_integer' => [['int_col_2'], 'integer'], @@ -104,14 +111,7 @@ public function rules() 'datetime_col_datetime' => [['datetime_col'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], 'timestamp_col_string' => [['timestamp_col'], 'string'], 'year_col_string' => [['year_col'], 'string'], - 'json_col_def_default' => [['json_col_def'], 'default', 'value' => []], - 'json_col_def_2_default' => [['json_col_def_2'], 'default', 'value' => []], - 'blob_def_default' => [['blob_def'], 'default', 'value' => 'the blob'], 'text_def_string' => [['text_def'], 'string'], - 'text_def_default' => [['text_def'], 'default', 'value' => 'the text'], - 'json_def_default' => [['json_def'], 'default', 'value' => [ - 'a' => 'b', - ]], 'safe' => [['varbinary_col', 'blob_col', 'json_col', 'json_col_def', 'json_col_def_2', 'blob_def', 'json_def'], 'safe'], ]; } diff --git a/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Editcolumn.php b/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Editcolumn.php index 242d7ec5..fe2d46c5 100644 --- a/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Editcolumn.php +++ b/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Editcolumn.php @@ -34,21 +34,21 @@ public function rules() { return [ 'trim' => [['name', 'tag', 'first_name', 'string_col', 'str_col_def', 'json_col'], 'trim'], + 'name_default' => [['name'], 'default', 'value' => 'Horse-2'], + 'dec_col_default' => [['dec_col'], 'default', 'value' => 3.14], + 'json_col_default' => [['json_col'], 'default', 'value' => 'fox jumps over dog'], + 'json_col_2_default' => [['json_col_2'], 'default', 'value' => []], + 'json_col_def_n_default' => [['json_col_def_n'], 'default', 'value' => []], + 'json_col_def_n_2_default' => [['json_col_def_n_2'], 'default', 'value' => []], 'required' => [['name', 'str_col_def', 'json_col', 'json_col_2'], 'required'], 'name_string' => [['name'], 'string', 'max' => 254], - 'name_default' => [['name'], 'default', 'value' => 'Horse-2'], 'tag_string' => [['tag'], 'string'], 'first_name_string' => [['first_name'], 'string', 'max' => 255], 'string_col_string' => [['string_col'], 'string'], 'dec_col_double' => [['dec_col'], 'double'], - 'dec_col_default' => [['dec_col'], 'default', 'value' => 3.14], 'str_col_def_string' => [['str_col_def'], 'string', 'max' => 3], 'json_col_string' => [['json_col'], 'string'], - 'json_col_default' => [['json_col'], 'default', 'value' => 'fox jumps over dog'], - 'json_col_2_default' => [['json_col_2'], 'default', 'value' => []], 'numeric_col_double' => [['numeric_col'], 'double'], - 'json_col_def_n_default' => [['json_col_def_n'], 'default', 'value' => []], - 'json_col_def_n_2_default' => [['json_col_def_n_2'], 'default', 'value' => []], 'safe' => [['json_col_2', 'json_col_def_n', 'json_col_def_n_2'], 'safe'], ]; } diff --git a/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Newcolumn.php b/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Newcolumn.php index 444216ba..57669a6e 100644 --- a/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Newcolumn.php +++ b/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Newcolumn.php @@ -30,13 +30,13 @@ public function rules() { return [ 'trim' => [['name', 'last_name', 'varchar_col'], 'trim'], + 'json_col_def_n_default' => [['json_col_def_n'], 'default', 'value' => []], 'required' => [['name'], 'required'], 'name_string' => [['name'], 'string', 'max' => 255], 'last_name_string' => [['last_name'], 'string'], 'dec_col_double' => [['dec_col'], 'double'], 'varchar_col_string' => [['varchar_col'], 'string', 'max' => 5], 'numeric_col_double' => [['numeric_col'], 'double'], - 'json_col_def_n_default' => [['json_col_def_n'], 'default', 'value' => []], 'safe' => [['json_col', 'json_col_def_n'], 'safe'], ]; } diff --git a/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Pristine.php b/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Pristine.php index 1093d1f2..20d17d29 100644 --- a/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Pristine.php +++ b/tests/specs/x_db_type/rules_and_more/mysql/app/models/base/Pristine.php @@ -34,11 +34,12 @@ public function rules() { return [ 'trim' => [['name', 'tag', 'new_col', 'col_9', 'col_10', 'col_11'], 'trim'], + 'tag_default' => [['tag'], 'default', 'value' => '4 leg'], + 'price_default' => [['price'], 'default', 'value' => 0], 'required' => [['custom_id_col', 'name'], 'required'], 'custom_id_col_integer' => [['custom_id_col'], 'integer'], 'name_string' => [['name'], 'string'], 'tag_string' => [['tag'], 'string'], - 'tag_default' => [['tag'], 'default', 'value' => '4 leg'], 'new_col_string' => [['new_col'], 'string', 'max' => 17], 'col_5_double' => [['col_5'], 'double'], 'col_6_double' => [['col_6'], 'double'], @@ -47,7 +48,6 @@ public function rules() 'col_10_string' => [['col_10'], 'string', 'max' => 10], 'col_11_string' => [['col_11'], 'string'], 'price_double' => [['price'], 'double'], - 'price_default' => [['price'], 'default', 'value' => 0], 'safe' => [['col_8'], 'safe'], ]; } diff --git a/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Alldbdatatype.php b/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Alldbdatatype.php index c63f2aa7..c1cdc2f2 100644 --- a/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Alldbdatatype.php +++ b/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Alldbdatatype.php @@ -116,6 +116,17 @@ public function rules() { return [ 'trim' => [['string_col', 'varchar_col', 'text_col', 'varchar_4_col', 'varchar_5_col', 'char_4_col', 'char_5_col', 'char_6_col', 'char_7_col', 'char_8_col', 'date_col', 'time_col', 'time_col_2', 'time_col_3', 'time_col_4', 'timetz_col', 'timetz_col_2', 'timestamp_col', 'timestamp_col_2', 'timestamp_col_3', 'timestamp_col_4', 'timestamptz_col', 'timestamptz_col_2', 'date2', 'timestamp_col_z', 'box_col', 'character_col', 'character_n', 'character_varying', 'character_varying_n', 'text_def', 'cidr_col', 'circle_col', 'date_col_z', 'inet_col', 'interval_col', 'interval_col_2', 'interval_col_3', 'line_col', 'lseg_col', 'macaddr_col', 'money_col', 'path_col', 'point_col', 'polygon_col', 'tsquery_col', 'tsvector_col', 'txid_snapshot_col', 'uuid_col', 'xml_col'], 'trim'], + 'char_8_col_default' => [['char_8_col'], 'default', 'value' => 'd'], + 'json_col_def_default' => [['json_col_def'], 'default', 'value' => []], + 'json_col_def_2_default' => [['json_col_def_2'], 'default', 'value' => []], + 'bytea_def_default' => [['bytea_def'], 'default', 'value' => 'the bytea blob default'], + 'text_def_default' => [['text_def'], 'default', 'value' => 'the text'], + 'json_def_default' => [['json_def'], 'default', 'value' => [ + 'a' => 'b', + ]], + 'jsonb_def_default' => [['jsonb_def'], 'default', 'value' => [ + 'ba' => 'bb', + ]], 'required' => [['char_6_col', 'char_7_col', 'smallserial_col', 'serial2_col', 'bigserial_col', 'bigserial_col_2', 'serial_col', 'serial4_col'], 'required'], 'string_col_string' => [['string_col'], 'string'], 'varchar_col_string' => [['varchar_col'], 'string'], @@ -127,7 +138,6 @@ public function rules() 'char_6_col_string' => [['char_6_col'], 'string'], 'char_7_col_string' => [['char_7_col'], 'string', 'max' => 6], 'char_8_col_string' => [['char_8_col'], 'string'], - 'char_8_col_default' => [['char_8_col'], 'default', 'value' => 'd'], 'decimal_col_double' => [['decimal_col'], 'double'], 'bit_col_integer' => [['bit_col'], 'integer'], 'bit_2_integer' => [['bit_2'], 'integer'], @@ -178,17 +188,7 @@ public function rules() 'character_n_string' => [['character_n'], 'string', 'max' => 12], 'character_varying_string' => [['character_varying'], 'string'], 'character_varying_n_string' => [['character_varying_n'], 'string', 'max' => 12], - 'json_col_def_default' => [['json_col_def'], 'default', 'value' => []], - 'json_col_def_2_default' => [['json_col_def_2'], 'default', 'value' => []], - 'bytea_def_default' => [['bytea_def'], 'default', 'value' => 'the bytea blob default'], 'text_def_string' => [['text_def'], 'string'], - 'text_def_default' => [['text_def'], 'default', 'value' => 'the text'], - 'json_def_default' => [['json_def'], 'default', 'value' => [ - 'a' => 'b', - ]], - 'jsonb_def_default' => [['jsonb_def'], 'default', 'value' => [ - 'ba' => 'bb', - ]], 'cidr_col_string' => [['cidr_col'], 'string'], 'circle_col_string' => [['circle_col'], 'string'], 'date_col_z_date' => [['date_col_z'], 'date', 'format' => 'php:Y-m-d'], diff --git a/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Editcolumn.php b/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Editcolumn.php index 4155fa5f..4cb00fee 100644 --- a/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Editcolumn.php +++ b/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Editcolumn.php @@ -35,21 +35,21 @@ public function rules() { return [ 'trim' => [['name', 'tag', 'first_name', 'string_col', 'str_col_def', 'json_col'], 'trim'], + 'name_default' => [['name'], 'default', 'value' => 'Horse-2'], + 'dec_col_default' => [['dec_col'], 'default', 'value' => 3.14], + 'json_col_default' => [['json_col'], 'default', 'value' => 'fox jumps over dog'], + 'json_col_2_default' => [['json_col_2'], 'default', 'value' => []], + 'json_col_def_n_default' => [['json_col_def_n'], 'default', 'value' => []], + 'json_col_def_n_2_default' => [['json_col_def_n_2'], 'default', 'value' => []], 'required' => [['name', 'str_col_def', 'json_col', 'json_col_2', 'numeric_col'], 'required'], 'name_string' => [['name'], 'string', 'max' => 254], - 'name_default' => [['name'], 'default', 'value' => 'Horse-2'], 'tag_string' => [['tag'], 'string'], 'first_name_string' => [['first_name'], 'string'], 'string_col_string' => [['string_col'], 'string'], 'dec_col_double' => [['dec_col'], 'double'], - 'dec_col_default' => [['dec_col'], 'default', 'value' => 3.14], 'str_col_def_string' => [['str_col_def'], 'string'], 'json_col_string' => [['json_col'], 'string'], - 'json_col_default' => [['json_col'], 'default', 'value' => 'fox jumps over dog'], - 'json_col_2_default' => [['json_col_2'], 'default', 'value' => []], 'numeric_col_double' => [['numeric_col'], 'double'], - 'json_col_def_n_default' => [['json_col_def_n'], 'default', 'value' => []], - 'json_col_def_n_2_default' => [['json_col_def_n_2'], 'default', 'value' => []], 'safe' => [['json_col_2', 'json_col_def_n', 'json_col_def_n_2', 'text_col_array'], 'safe'], ]; } diff --git a/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Newcolumn.php b/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Newcolumn.php index bc06c5bc..d1cf823e 100644 --- a/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Newcolumn.php +++ b/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Newcolumn.php @@ -33,6 +33,8 @@ public function rules() { return [ 'trim' => [['name', 'first_name', 'last_name', 'varchar_col'], 'trim'], + 'json_col_def_n_default' => [['json_col_def_n'], 'default', 'value' => []], + 'json_col_def_n_2_default' => [['json_col_def_n_2'], 'default', 'value' => []], 'required' => [['name'], 'required'], 'name_string' => [['name'], 'string'], 'first_name_string' => [['first_name'], 'string'], @@ -40,8 +42,6 @@ public function rules() 'dec_col_double' => [['dec_col'], 'double'], 'varchar_col_string' => [['varchar_col'], 'string'], 'numeric_col_double' => [['numeric_col'], 'double'], - 'json_col_def_n_default' => [['json_col_def_n'], 'default', 'value' => []], - 'json_col_def_n_2_default' => [['json_col_def_n_2'], 'default', 'value' => []], 'safe' => [['json_col', 'json_col_def_n', 'json_col_def_n_2', 'text_col_array'], 'safe'], ]; } diff --git a/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Pristine.php b/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Pristine.php index 974f5e8d..60cc8b35 100644 --- a/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Pristine.php +++ b/tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Pristine.php @@ -34,11 +34,12 @@ public function rules() { return [ 'trim' => [['name', 'tag', 'new_col', 'col_9', 'col_10', 'col_11'], 'trim'], + 'tag_default' => [['tag'], 'default', 'value' => '4 leg'], + 'price_default' => [['price'], 'default', 'value' => 0], 'required' => [['custom_id_col', 'name'], 'required'], 'custom_id_col_integer' => [['custom_id_col'], 'integer'], 'name_string' => [['name'], 'string'], 'tag_string' => [['tag'], 'string'], - 'tag_default' => [['tag'], 'default', 'value' => '4 leg'], 'new_col_string' => [['new_col'], 'string'], 'col_5_double' => [['col_5'], 'double'], 'col_6_double' => [['col_6'], 'double'], @@ -47,7 +48,6 @@ public function rules() 'col_10_string' => [['col_10'], 'string'], 'col_11_string' => [['col_11'], 'string'], 'price_double' => [['price'], 'double'], - 'price_default' => [['price'], 'default', 'value' => 0], 'safe' => [['col_8'], 'safe'], ]; } diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index c2d8796c..ea27e5d1 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -1001,6 +1001,50 @@ public function test74InvalidSchemaReferenceError() $this->runActualMigrations(); } + // https://github.com/php-openapi/yii2-openapi/issues/22 + public function test22BugRulesRequiredIsGeneratedBeforeDefault() + { + $testFile = Yii::getAlias("@specs/issue_fix/22_bug_rules_required_is_generated_before_default/index.php"); + $this->runGenerator($testFile); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/22_bug_rules_required_is_generated_before_default/mysql"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + } + + // https://github.com/php-openapi/yii2-openapi/issues/23 + public function test23ConsiderOpenapiExtensionXNoRelationAlsoInOtherPertinentPlace() + { + $testFile = Yii::getAlias("@specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/index.php"); + $this->runGenerator($testFile); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place/mysql"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + $this->runActualMigrations(); + } + + // https://github.com/php-openapi/yii2-openapi/issues/87 + public function test87ImplementForJsonInIsrefpointertoschema() + { + $testFile = Yii::getAlias("@specs/issue_fix/87_implement_for_json_in_is_ref_pointer_to_schema/index.php"); + $this->runGenerator($testFile); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/74_invalid_schema_reference_error/mysql"), [ # this is intentional + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + $this->runActualMigrations(); + } + // https://github.com/php-openapi/yii2-openapi/issues/78 public function test78PropertiesThatAreMarkedAsReadonlyAreNotReadOnly() { From 1aa99e2291d797a4bb695990441292729e861452 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Wed, 12 Mar 2025 15:06:11 +0530 Subject: [PATCH 10/12] Fix merge conflict 2 --- tests/unit/IssueFixTest.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index ea27e5d1..08d1a00c 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -1044,18 +1044,4 @@ public function test87ImplementForJsonInIsrefpointertoschema() $this->checkFiles($actualFiles, $expectedFiles); $this->runActualMigrations(); } - - // https://github.com/php-openapi/yii2-openapi/issues/78 - public function test78PropertiesThatAreMarkedAsReadonlyAreNotReadOnly() - { - $testFile = Yii::getAlias("@specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/index.php"); - $this->runGenerator($testFile); - $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ - 'recursive' => true, - ]); - $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql"), [ - 'recursive' => true, - ]); - $this->checkFiles($actualFiles, $expectedFiles); - } } From 709018b7043be97cbb50ce9e7f8a2e66c85cd528 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Wed, 12 Mar 2025 15:06:37 +0530 Subject: [PATCH 11/12] Fix merge conflict 3 --- tests/unit/IssueFixTest.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index 08d1a00c..ea27e5d1 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -1044,4 +1044,18 @@ public function test87ImplementForJsonInIsrefpointertoschema() $this->checkFiles($actualFiles, $expectedFiles); $this->runActualMigrations(); } + + // https://github.com/php-openapi/yii2-openapi/issues/78 + public function test78PropertiesThatAreMarkedAsReadonlyAreNotReadOnly() + { + $testFile = Yii::getAlias("@specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/index.php"); + $this->runGenerator($testFile); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/mysql"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + } } From 4c796094c2400fa9f26eb346c0caad5f35eaac71 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Wed, 12 Mar 2025 15:10:32 +0530 Subject: [PATCH 12/12] Fix conflict --- src/lib/generators/ControllersGenerator.php | 22 ++++++++++-- .../blog_v2/controllers/CommentController.php | 2 ++ .../pgsql/controllers/ContactController.php | 2 ++ .../pgsql/controllers/AccountController.php | 1 + .../index.php | 13 +++++++ .../index.yml | 36 +++++++++++++++++++ .../mysql/controllers/MangoController.php | 27 ++++++++++++++ .../controllers/base/MangoController.php | 34 ++++++++++++++++++ tests/unit/IssueFixTest.php | 14 ++++++++ 9 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.php create mode 100644 tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.yml create mode 100644 tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/MangoController.php create mode 100644 tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/base/MangoController.php diff --git a/src/lib/generators/ControllersGenerator.php b/src/lib/generators/ControllersGenerator.php index bd749c9f..ea0c73c4 100644 --- a/src/lib/generators/ControllersGenerator.php +++ b/src/lib/generators/ControllersGenerator.php @@ -59,7 +59,7 @@ public function generate():CodeFiles $controllerPath = $path; /** * @var RestAction|FractalAction $action - **/ + **/ $action = $actions[0]; if ($action->prefix && !empty($action->prefixSettings)) { $controllerNamespace = trim($action->prefixSettings['namespace'], '\\'); @@ -126,15 +126,31 @@ protected function makeCustomController( ]; $reflection->addMethod('checkAccess', $params, AbstractMemberGenerator::FLAG_PUBLIC, '//TODO implement checkAccess'); foreach ($abstractActions as $action) { + $responseHttpStatusCodes = ''; + foreach ($this->config->getOpenApi()->paths->getPaths()[$action->urlPath]->getOperations() as $verb => $operation) { + $codes = array_keys($operation->responses->getResponses()); + + $only200OrDefault = false; + if ($codes === [200] || $codes === ['default']) { + $only200OrDefault = true; + } + if (in_array('default', $codes) && in_array(200, $codes) && count($codes) === 2) { + $only200OrDefault = true; + } + + if ($verb === strtolower($action->requestMethod) && !$only200OrDefault) { + $responseHttpStatusCodes = implode(', ', $codes); + } + } + $params = array_map(static function ($param) { return ['name' => $param]; }, $action->getParamNames()); - $reflection->addMethod( $action->actionMethodName, $params, AbstractMemberGenerator::FLAG_PUBLIC, - '//TODO implement ' . $action->actionMethodName + '//TODO implement ' . $action->actionMethodName . ($responseHttpStatusCodes ? PHP_EOL . '// In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: ' . $responseHttpStatusCodes : '') ); } $classFileGenerator->setClasses([$reflection]); diff --git a/tests/specs/blog_v2/controllers/CommentController.php b/tests/specs/blog_v2/controllers/CommentController.php index 0448ec72..c46307ed 100644 --- a/tests/specs/blog_v2/controllers/CommentController.php +++ b/tests/specs/blog_v2/controllers/CommentController.php @@ -18,6 +18,7 @@ public function actionListForPost($postId) public function actionCreateForPost($postId) { //TODO implement actionCreateForPost + // In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 201, default } public function actionViewForPost($slug, $id) @@ -28,6 +29,7 @@ public function actionViewForPost($slug, $id) public function actionDeleteForPost($slug, $id) { //TODO implement actionDeleteForPost + // In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 204 } public function actionUpdateForPost($slug, $id) diff --git a/tests/specs/issue_fix/163_generator_crash_when_using_reference_inside_an_object/pgsql/controllers/ContactController.php b/tests/specs/issue_fix/163_generator_crash_when_using_reference_inside_an_object/pgsql/controllers/ContactController.php index 10422b18..5f21cabb 100644 --- a/tests/specs/issue_fix/163_generator_crash_when_using_reference_inside_an_object/pgsql/controllers/ContactController.php +++ b/tests/specs/issue_fix/163_generator_crash_when_using_reference_inside_an_object/pgsql/controllers/ContactController.php @@ -13,11 +13,13 @@ public function checkAccess($action, $model = null, $params = []) public function actionListForAccount($accountId) { //TODO implement actionListForAccount + // In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 200, 403 } public function actionViewForAccount($accountId, $contactId) { //TODO implement actionViewForAccount + // In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 200, 403 } diff --git a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/controllers/AccountController.php b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/controllers/AccountController.php index b4044b8f..cfa4a6d3 100644 --- a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/controllers/AccountController.php +++ b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/controllers/AccountController.php @@ -13,6 +13,7 @@ public function checkAccess($action, $model = null, $params = []) public function actionView($id) { //TODO implement actionView + // In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 200, 404 } diff --git a/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.php b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.php new file mode 100644 index 00000000..cf88e27a --- /dev/null +++ b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.php @@ -0,0 +1,13 @@ + '@specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.yml', + 'generateUrls' => false, + 'generateModels' => false, + 'excludeModels' => [ + 'Error', + ], + 'generateControllers' => true, + 'generateMigrations' => false, + 'generateModelFaker' => false, +]; diff --git a/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.yml b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.yml new file mode 100644 index 00000000..df5b1314 --- /dev/null +++ b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.yml @@ -0,0 +1,36 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: 79_response_status_codes_are_not_the_codes_defined_in_spec +paths: + /mango/cake: + get: + responses: + '200': + description: The information + '403': + description: The information + '404': + description: The information + post: + responses: + '201': + description: The information + '403': + description: The information + '404': + description: The information + '422': + description: The information + +components: + schemas: + Address: + type: object + description: desc + properties: + id: + type: integer + name: + type: string + maxLength: 64 diff --git a/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/MangoController.php b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/MangoController.php new file mode 100644 index 00000000..46c40ad1 --- /dev/null +++ b/tests/specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql/controllers/MangoController.php @@ -0,0 +1,27 @@ + [ + '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 actionCake(); + + abstract public function actionCreateCake(); + +} diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index ea27e5d1..2110a386 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -1058,4 +1058,18 @@ public function test78PropertiesThatAreMarkedAsReadonlyAreNotReadOnly() ]); $this->checkFiles($actualFiles, $expectedFiles); } + + // https://github.com/php-openapi/yii2-openapi/issues/79 + public function test79ResponseStatusCodesAreNotTheCodesDefinedInSpec() + { + $testFile = Yii::getAlias("@specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.php"); + $this->runGenerator($testFile); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/mysql"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + } }