diff --git a/src/lib/AttributeResolver.php b/src/lib/AttributeResolver.php index 0063d8df..e8f936cb 100644 --- a/src/lib/AttributeResolver.php +++ b/src/lib/AttributeResolver.php @@ -7,8 +7,6 @@ namespace cebe\yii2openapi\lib; -use cebe\yii2openapi\lib\Config; -use cebe\yii2openapi\lib\CustomSpecAttr; use cebe\yii2openapi\lib\exceptions\InvalidDefinitionException; use cebe\yii2openapi\lib\items\Attribute; use cebe\yii2openapi\lib\items\AttributeRelation; @@ -22,7 +20,6 @@ use Yii; use yii\helpers\Inflector; use yii\helpers\StringHelper; -use yii\helpers\VarDumper; use function explode; use function strpos; use function strtolower; @@ -266,7 +263,7 @@ protected function resolveProperty( $relation = Yii::createObject( AttributeRelation::class, - [$property->getName(), $relatedTableName, $relatedClassName] + [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] ) ->asHasOne([$fkProperty->getName() => $attribute->columnName]); $relation->onUpdateFkConstraint = $property->onUpdateFkConstraint; @@ -317,7 +314,7 @@ protected function resolveProperty( $this->relations[$property->getName()] = Yii::createObject( AttributeRelation::class, - [$property->getName(), $relatedTableName, $relatedClassName] + [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] ) ->asHasMany([$fkProperty->getName() => $fkProperty->getName()])->asSelfReference(); return; @@ -326,7 +323,7 @@ protected function resolveProperty( $this->relations[$property->getName()] = Yii::createObject( AttributeRelation::class, - [$property->getName(), $relatedTableName, $relatedClassName] + [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] ) ->asHasMany([$foreignPk => $this->schema->getPkName()]); return; @@ -345,7 +342,7 @@ protected function resolveProperty( $this->relations[$property->getName()] = Yii::createObject( AttributeRelation::class, - [$property->getName(), $relatedTableName, $relatedClassName] + [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] ) ->asHasMany([Inflector::camel2id($this->schemaName, '_') . '_id' => $this->schema->getPkName()]); return; @@ -492,4 +489,14 @@ protected function resolvePropertyRef(PropertySchema $property, Attribute $attri $this->attributes[$property->getName()] = $attribute->setFakerStub($this->guessFakerStub($attribute, $fkProperty)); } + + public static function relationName(string $propertyName, ?string $fkColumnName): string + { + $fkColumnName = (string) $fkColumnName; + $relationName = $propertyName; + if (!str_contains($fkColumnName, '_')) { + $relationName = strtolower($fkColumnName) === strtolower($relationName) ? $relationName . 'Rel' : $relationName; + } + return $relationName; + } } diff --git a/src/lib/ValidationRulesBuilder.php b/src/lib/ValidationRulesBuilder.php index 3f3c1398..0c5403f2 100644 --- a/src/lib/ValidationRulesBuilder.php +++ b/src/lib/ValidationRulesBuilder.php @@ -10,8 +10,7 @@ use cebe\yii2openapi\lib\items\Attribute; use cebe\yii2openapi\lib\items\DbModel; use cebe\yii2openapi\lib\items\ValidationRule; -use yii\helpers\VarDumper; -use yii\validators\DateValidator; +use yii\helpers\Inflector; use function count; use function implode; use function in_array; @@ -162,10 +161,12 @@ private function addExistRules(array $relations):void } elseif ($attribute->phpType === 'string') { $this->addStringRule($attribute); } + + $targetRelation = AttributeResolver::relationName(Inflector::variablize($attribute->camelName()), $attribute->fkColName); $this->rules[$attribute->columnName . '_exist'] = new ValidationRule( [$attribute->columnName], 'exist', - ['targetRelation' => $attribute->camelName()] + ['targetRelation' => $targetRelation] ); } } diff --git a/tests/specs/blog/models/base/Comment.php b/tests/specs/blog/models/base/Comment.php index 44cd42fc..1cf49178 100644 --- a/tests/specs/blog/models/base/Comment.php +++ b/tests/specs/blog/models/base/Comment.php @@ -28,9 +28,9 @@ public function rules() 'trim' => [['post_id'], 'trim'], 'required' => [['post_id', 'author_id', 'message', 'created_at'], 'required'], 'post_id_string' => [['post_id'], 'string', 'max' => 128], - 'post_id_exist' => [['post_id'], 'exist', 'targetRelation' => 'Post'], + 'post_id_exist' => [['post_id'], 'exist', 'targetRelation' => 'post'], 'author_id_integer' => [['author_id'], 'integer'], - 'author_id_exist' => [['author_id'], 'exist', 'targetRelation' => 'Author'], + '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'], diff --git a/tests/specs/blog/models/base/Post.php b/tests/specs/blog/models/base/Post.php index 457978b5..d1949af2 100644 --- a/tests/specs/blog/models/base/Post.php +++ b/tests/specs/blog/models/base/Post.php @@ -30,9 +30,9 @@ public function rules() 'trim' => [['title', 'slug', 'created_at'], 'trim'], 'required' => [['title', 'category_id', 'active'], 'required'], 'category_id_integer' => [['category_id'], 'integer'], - 'category_id_exist' => [['category_id'], 'exist', 'targetRelation' => 'Category'], + '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'], + 'created_by_id_exist' => [['created_by_id'], 'exist', 'targetRelation' => 'createdBy'], 'title_unique' => [['title'], 'unique'], 'slug_unique' => [['slug'], 'unique'], 'title_string' => [['title'], 'string', 'max' => 255], diff --git a/tests/specs/blog_v2/models/base/Comment.php b/tests/specs/blog_v2/models/base/Comment.php index a732c5c0..0f9fc288 100644 --- a/tests/specs/blog_v2/models/base/Comment.php +++ b/tests/specs/blog_v2/models/base/Comment.php @@ -28,9 +28,9 @@ public function rules() 'trim' => [['message', 'meta_data', 'created_at'], 'trim'], 'required' => [['post_id', 'message', 'created_at'], 'required'], 'post_id_integer' => [['post_id'], 'integer'], - 'post_id_exist' => [['post_id'], 'exist', 'targetRelation' => 'Post'], + 'post_id_exist' => [['post_id'], 'exist', 'targetRelation' => 'post'], 'user_id_integer' => [['user_id'], 'integer'], - 'user_id_exist' => [['user_id'], 'exist', 'targetRelation' => 'User'], + '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' => ''], diff --git a/tests/specs/blog_v2/models/base/Post.php b/tests/specs/blog_v2/models/base/Post.php index 44fe4275..333167e6 100644 --- a/tests/specs/blog_v2/models/base/Post.php +++ b/tests/specs/blog_v2/models/base/Post.php @@ -32,9 +32,9 @@ public function rules() 'trim' => [['title', 'slug', 'created_at'], 'trim'], 'required' => [['title', 'category_id', 'active'], 'required'], 'category_id_integer' => [['category_id'], 'integer'], - 'category_id_exist' => [['category_id'], 'exist', 'targetRelation' => 'Category'], + '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'], + '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], 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 8746e8f0..6b1d0b44 100644 --- a/tests/specs/fk_col_name/app/models/base/Webhook.php +++ b/tests/specs/fk_col_name/app/models/base/Webhook.php @@ -25,9 +25,9 @@ public function rules() return [ 'trim' => [['name'], 'trim'], 'user_id_integer' => [['user_id'], 'integer'], - 'user_id_exist' => [['user_id'], 'exist', 'targetRelation' => 'User'], + 'user_id_exist' => [['user_id'], 'exist', 'targetRelation' => 'user'], 'redelivery_of_integer' => [['redelivery_of'], 'integer'], - 'redelivery_of_exist' => [['redelivery_of'], 'exist', 'targetRelation' => 'RedeliveryOf'], + '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 29a40568..7adabbcc 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 @@ -27,11 +27,11 @@ public function rules() return [ 'trim' => [['name'], 'trim'], 'user_id_integer' => [['user_id'], 'integer'], - 'user_id_exist' => [['user_id'], 'exist', 'targetRelation' => 'User'], + 'user_id_exist' => [['user_id'], 'exist', 'targetRelation' => 'user'], 'redelivery_of_integer' => [['redelivery_of'], 'integer'], - 'redelivery_of_exist' => [['redelivery_of'], 'exist', 'targetRelation' => 'RedeliveryOf'], + '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'], + 'rd_abc_2_exist' => [['rd_abc_2'], 'exist', 'targetRelation' => 'rd2'], 'user_id_name_unique' => [['user_id', 'name'], 'unique', 'targetAttribute' => [ 'user_id', 'name', 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 efbd8b32..f77b3725 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 @@ -25,7 +25,7 @@ public function rules() 'trim' => [['nickname'], 'trim'], 'required' => [['mailing_id'], 'required'], 'mailing_id_integer' => [['mailing_id'], 'integer'], - 'mailing_id_exist' => [['mailing_id'], 'exist', 'targetRelation' => 'Mailing'], + 'mailing_id_exist' => [['mailing_id'], 'exist', 'targetRelation' => 'mailing'], 'active_boolean' => [['active'], 'boolean'], 'active_default' => [['active'], 'default', 'value' => false], 'nickname_string' => [['nickname'], 'string'], 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 74472cd5..89d5b559 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 @@ -24,7 +24,7 @@ public function rules() return [ 'trim' => [['name', 'name2'], 'trim'], 'invoice_id_integer' => [['invoice_id'], 'integer'], - 'invoice_id_exist' => [['invoice_id'], 'exist', 'targetRelation' => 'Invoice'], + 'invoice_id_exist' => [['invoice_id'], 'exist', 'targetRelation' => 'invoice'], 'name_string' => [['name'], 'string'], 'name2_string' => [['name2'], 'string'], ]; 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 21a2e7f1..ec235266 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 @@ -25,7 +25,7 @@ public function rules() 'trim' => [['nickname'], 'trim'], 'required' => [['account_id'], 'required'], 'account_id_integer' => [['account_id'], 'integer'], - 'account_id_exist' => [['account_id'], 'exist', 'targetRelation' => 'Account'], + 'account_id_exist' => [['account_id'], 'exist', 'targetRelation' => 'account'], 'active_boolean' => [['active'], 'boolean'], 'active_default' => [['active'], 'default', 'value' => false], 'nickname_string' => [['nickname'], 'string'], diff --git a/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/index.php b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/index.php new file mode 100644 index 00000000..f818842e --- /dev/null +++ b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/index.php @@ -0,0 +1,13 @@ + '@specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/index.yaml', + 'generateUrls' => false, + 'generateModels' => true, + 'excludeModels' => [ + 'Error', + ], + 'generateControllers' => false, + 'generateMigrations' => true, + 'generateModelFaker' => true, +]; diff --git a/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/index.yaml b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/index.yaml new file mode 100644 index 00000000..6a872595 --- /dev/null +++ b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/index.yaml @@ -0,0 +1,33 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Extension FK COLUMN NAME cause error in case of column name without underscore \#29 +paths: + /: + get: + summary: List + operationId: list + responses: + '200': + description: The information + +components: + schemas: + User: + type: object + properties: + id: + type: integer + name: + type: string + Post: + type: object + properties: + id: + type: integer + content: + type: string + user: + allOf: + - $ref: '#/components/schemas/User' + - x-fk-column-name: user diff --git a/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/migrations_mysql_db/m200000_000000_create_table_users.php b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/migrations_mysql_db/m200000_000000_create_table_users.php new file mode 100644 index 00000000..9ab60f3e --- /dev/null +++ b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/migrations_mysql_db/m200000_000000_create_table_users.php @@ -0,0 +1,20 @@ +createTable('{{%users}}', [ + 'id' => $this->primaryKey(), + 'name' => $this->text()->null(), + ]); + } + + public function down() + { + $this->dropTable('{{%users}}'); + } +} diff --git a/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/migrations_mysql_db/m200000_000001_create_table_posts.php b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/migrations_mysql_db/m200000_000001_create_table_posts.php new file mode 100644 index 00000000..ebb98b8e --- /dev/null +++ b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/migrations_mysql_db/m200000_000001_create_table_posts.php @@ -0,0 +1,23 @@ +createTable('{{%posts}}', [ + 'id' => $this->primaryKey(), + 'content' => $this->text()->null(), + 'user' => $this->integer()->null()->defaultValue(null), + ]); + $this->addForeignKey('fk_posts_user_users_id', '{{%posts}}', 'user', '{{%users}}', 'id'); + } + + public function down() + { + $this->dropForeignKey('fk_posts_user_users_id', '{{%posts}}'); + $this->dropTable('{{%posts}}'); + } +} diff --git a/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/BaseModelFaker.php b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/BaseModelFaker.php new file mode 100644 index 00000000..c367fbb4 --- /dev/null +++ b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/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/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/Post.php b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/Post.php new file mode 100644 index 00000000..2825fe31 --- /dev/null +++ b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/Post.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 Post(); + //$model->id = $uniqueFaker->numberBetween(0, 1000000); + $model->content = $faker->paragraphs(6, true); + $model->user = $faker->randomElement(\app\models\User::find()->select("id")->column()); + if (!is_callable($attributes)) { + $model->setAttributes($attributes, false); + } else { + $model = $attributes($model, $faker, $uniqueFaker); + } + return $model; + } + + public static function dependentOn() + { + return [ + // just model class names + 'User', + + ]; + } +} diff --git a/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/User.php b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/User.php new file mode 100644 index 00000000..9b837d6e --- /dev/null +++ b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/User.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 User(); + //$model->id = $uniqueFaker->numberBetween(0, 1000000); + $model->name = $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/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 new file mode 100644 index 00000000..c8ba9f96 --- /dev/null +++ b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/base/Post.php @@ -0,0 +1,35 @@ + [['content'], 'trim'], + 'user_integer' => [['user'], 'integer'], + 'user_exist' => [['user'], 'exist', 'targetRelation' => 'userRel'], + 'content_string' => [['content'], 'string'], + ]; + } + + public function getUserRel() + { + return $this->hasOne(\app\models\User::class, ['id' => 'user']); + } +} diff --git a/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/base/User.php b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/base/User.php new file mode 100644 index 00000000..08e59880 --- /dev/null +++ b/tests/specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql/models/base/User.php @@ -0,0 +1,26 @@ + [['name'], 'trim'], + 'name_string' => [['name'], 'string'], + ]; + } +} 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 cbec768a..ac4dce54 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 @@ -27,11 +27,11 @@ public function rules() return [ 'trim' => [['name'], 'trim'], 'account_id_integer' => [['account_id'], 'integer'], - 'account_id_exist' => [['account_id'], 'exist', 'targetRelation' => 'Account'], + '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_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'], + 'account_3_id_exist' => [['account_3_id'], 'exist', 'targetRelation' => 'account3'], 'name_string' => [['name'], 'string'], ]; } diff --git a/tests/specs/many2many/models/base/Photos2Posts.php b/tests/specs/many2many/models/base/Photos2Posts.php index 523ecada..80ef4f97 100644 --- a/tests/specs/many2many/models/base/Photos2Posts.php +++ b/tests/specs/many2many/models/base/Photos2Posts.php @@ -23,9 +23,9 @@ public function rules() { return [ 'photo_id_integer' => [['photo_id'], 'integer'], - 'photo_id_exist' => [['photo_id'], 'exist', 'targetRelation' => 'Photo'], + 'photo_id_exist' => [['photo_id'], 'exist', 'targetRelation' => 'photo'], 'post_id_integer' => [['post_id'], 'integer'], - 'post_id_exist' => [['post_id'], 'exist', 'targetRelation' => 'Post'], + 'post_id_exist' => [['post_id'], 'exist', 'targetRelation' => 'post'], ]; } diff --git a/tests/specs/many2many/models/base/PostsAttaches.php b/tests/specs/many2many/models/base/PostsAttaches.php index 54b8adda..8b30ab15 100644 --- a/tests/specs/many2many/models/base/PostsAttaches.php +++ b/tests/specs/many2many/models/base/PostsAttaches.php @@ -23,9 +23,9 @@ public function rules() { return [ 'attach_id_integer' => [['attach_id'], 'integer'], - 'attach_id_exist' => [['attach_id'], 'exist', 'targetRelation' => 'Attach'], + 'attach_id_exist' => [['attach_id'], 'exist', 'targetRelation' => 'attach'], 'target_id_integer' => [['target_id'], 'integer'], - 'target_id_exist' => [['target_id'], 'exist', 'targetRelation' => 'Target'], + 'target_id_exist' => [['target_id'], 'exist', 'targetRelation' => 'target'], ]; } diff --git a/tests/specs/many2many/models/base/PostsGallery.php b/tests/specs/many2many/models/base/PostsGallery.php index 61cfd67f..0adea949 100644 --- a/tests/specs/many2many/models/base/PostsGallery.php +++ b/tests/specs/many2many/models/base/PostsGallery.php @@ -23,9 +23,9 @@ public function rules() { return [ 'image_id_integer' => [['image_id'], 'integer'], - 'image_id_exist' => [['image_id'], 'exist', 'targetRelation' => 'Image'], + 'image_id_exist' => [['image_id'], 'exist', 'targetRelation' => 'image'], 'article_id_integer' => [['article_id'], 'integer'], - 'article_id_exist' => [['article_id'], 'exist', 'targetRelation' => 'Article'], + '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 582d952d..a92755f6 100644 --- a/tests/specs/menu/models/base/Menu.php +++ b/tests/specs/menu/models/base/Menu.php @@ -27,7 +27,7 @@ public function rules() 'trim' => [['name'], 'trim'], 'required' => [['name'], 'required'], 'parent_id_integer' => [['parent_id'], 'integer'], - 'parent_id_exist' => [['parent_id'], 'exist', 'targetRelation' => 'Parent'], + 'parent_id_exist' => [['parent_id'], 'exist', 'targetRelation' => 'parent'], 'name_string' => [['name'], 'string', 'min' => 3, 'max' => 100], 'args_default' => [['args'], 'default', 'value' => [ 'foo', diff --git a/tests/specs/petstore/models/base/Pet.php b/tests/specs/petstore/models/base/Pet.php index 039764d2..62f78428 100644 --- a/tests/specs/petstore/models/base/Pet.php +++ b/tests/specs/petstore/models/base/Pet.php @@ -25,7 +25,7 @@ public function rules() 'trim' => [['name', 'tag'], 'trim'], 'required' => [['name'], 'required'], 'store_id_integer' => [['store_id'], 'integer'], - 'store_id_exist' => [['store_id'], 'exist', 'targetRelation' => 'Store'], + 'store_id_exist' => [['store_id'], 'exist', 'targetRelation' => 'store'], 'name_string' => [['name'], 'string'], 'tag_string' => [['tag'], 'string'], ]; diff --git a/tests/specs/petstore_jsonapi/models/base/PetStatistic.php b/tests/specs/petstore_jsonapi/models/base/PetStatistic.php index ba8af41d..adc6e8fd 100644 --- a/tests/specs/petstore_jsonapi/models/base/PetStatistic.php +++ b/tests/specs/petstore_jsonapi/models/base/PetStatistic.php @@ -54,7 +54,7 @@ public function rules() return [ 'trim' => [['title', 'summary'], 'trim'], 'parentPet_id_integer' => [['parentPet_id'], 'integer'], - 'parentPet_id_exist' => [['parentPet_id'], 'exist', 'targetRelation' => 'ParentPet'], + 'parentPet_id_exist' => [['parentPet_id'], 'exist', 'targetRelation' => 'parentPet'], 'title_string' => [['title'], 'string'], 'dogsCount_integer' => [['dogsCount'], 'integer'], 'catsCount_integer' => [['catsCount'], 'integer'], diff --git a/tests/specs/petstore_namespace/mymodels/base/Pet.php b/tests/specs/petstore_namespace/mymodels/base/Pet.php index 58750645..cb549e8f 100644 --- a/tests/specs/petstore_namespace/mymodels/base/Pet.php +++ b/tests/specs/petstore_namespace/mymodels/base/Pet.php @@ -25,7 +25,7 @@ public function rules() 'trim' => [['name', 'tag'], 'trim'], 'required' => [['name'], 'required'], 'store_id_integer' => [['store_id'], 'integer'], - 'store_id_exist' => [['store_id'], 'exist', 'targetRelation' => 'Store'], + 'store_id_exist' => [['store_id'], 'exist', 'targetRelation' => 'store'], 'name_string' => [['name'], 'string'], 'tag_string' => [['tag'], 'string'], ]; 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 9836dc3b..6aaf6df5 100644 --- a/tests/specs/relations_in_faker/app/models/base/A123.php +++ b/tests/specs/relations_in_faker/app/models/base/A123.php @@ -23,7 +23,7 @@ public function rules() return [ 'trim' => [['name'], 'trim'], 'b123_id_integer' => [['b123_id'], 'integer'], - 'b123_id_exist' => [['b123_id'], 'exist', 'targetRelation' => 'B123'], + '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 f05fe320..8e5caa5a 100644 --- a/tests/specs/relations_in_faker/app/models/base/B123.php +++ b/tests/specs/relations_in_faker/app/models/base/B123.php @@ -23,7 +23,7 @@ public function rules() return [ 'trim' => [['name'], 'trim'], 'c123_id_integer' => [['c123_id'], 'integer'], - 'c123_id_exist' => [['c123_id'], 'exist', 'targetRelation' => 'C123'], + '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 3f861f9e..d378bbe3 100644 --- a/tests/specs/relations_in_faker/app/models/base/Domain.php +++ b/tests/specs/relations_in_faker/app/models/base/Domain.php @@ -26,7 +26,7 @@ public function rules() 'trim' => [['name'], 'trim'], 'required' => [['name', 'account_id'], 'required'], 'account_id_integer' => [['account_id'], 'integer'], - 'account_id_exist' => [['account_id'], 'exist', 'targetRelation' => 'Account'], + '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 6eb43814..c1a85c27 100644 --- a/tests/specs/relations_in_faker/app/models/base/E123.php +++ b/tests/specs/relations_in_faker/app/models/base/E123.php @@ -23,7 +23,7 @@ public function rules() return [ 'trim' => [['name'], 'trim'], 'b123_id_integer' => [['b123_id'], 'integer'], - 'b123_id_exist' => [['b123_id'], 'exist', 'targetRelation' => 'B123'], + '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 71a31b81..40e707e6 100644 --- a/tests/specs/relations_in_faker/app/models/base/Routing.php +++ b/tests/specs/relations_in_faker/app/models/base/Routing.php @@ -32,11 +32,11 @@ public function rules() 'trim' => [['path', 'service'], 'trim'], 'required' => [['domain_id'], 'required'], 'domain_id_integer' => [['domain_id'], 'integer'], - 'domain_id_exist' => [['domain_id'], 'exist', 'targetRelation' => 'Domain'], + 'domain_id_exist' => [['domain_id'], 'exist', 'targetRelation' => 'domain'], 'd123_id_integer' => [['d123_id'], 'integer'], - 'd123_id_exist' => [['d123_id'], 'exist', 'targetRelation' => 'D123'], + 'd123_id_exist' => [['d123_id'], 'exist', 'targetRelation' => 'd123'], 'a123_id_integer' => [['a123_id'], 'integer'], - 'a123_id_exist' => [['a123_id'], 'exist', 'targetRelation' => 'A123'], + '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'], diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index b6c7abdb..ea9d2182 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -360,4 +360,18 @@ public function test158BugGiiapiGeneratedRulesEnumWithTrim() ]); $this->checkFiles($actualFiles, $expectedFiles); } + + // https://github.com/php-openapi/yii2-openapi/issues/29 + public function test29ExtensionFkColumnNameCauseErrorInCaseOfColumnNameWithoutUnderscore() + { + $testFile = Yii::getAlias("@specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/index.php"); + $this->runGenerator($testFile); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/29_extension_fk_column_name_cause_error_in_case_of_column_name_without_underscore/mysql"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + } } diff --git a/tests/unit/ValidatorRulesBuilderTest.php b/tests/unit/ValidatorRulesBuilderTest.php index 43343df6..af018565 100644 --- a/tests/unit/ValidatorRulesBuilderTest.php +++ b/tests/unit/ValidatorRulesBuilderTest.php @@ -48,7 +48,7 @@ public function testBuild() ], 'trim'), 'required' => new ValidationRule(['title', 'category_id', 'required_with_def'], 'required'), 'category_id_integer' => new ValidationRule(['category_id'], 'integer'), - 'category_id_exist' => new ValidationRule(['category_id'], 'exist', ['targetRelation' => 'Category']), + 'category_id_exist' => new ValidationRule(['category_id'], 'exist', ['targetRelation' => 'category']), 'title_active_unique' => new ValidationRule(['title', 'active'], 'unique', [ 'targetAttribute' => ['title', 'active'],