From 5a5ee39dda80c30b22962291386f24610599a54a Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Fri, 14 Feb 2025 16:20:29 +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 9ff2113221ee5d94cfab930fb5681443f99ffd56 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Wed, 19 Feb 2025 13:37:23 +0530 Subject: [PATCH 02/12] Implement --- README.md | 2 +- src/lib/AttributeResolver.php | 42 +++++++++++-------- .../mysql/models/base/Pet.php | 6 --- .../index.php | 13 ++++++ .../index.yaml | 35 ++++++++++++++++ tests/unit/IssueFixTest.php | 16 +++++++ 6 files changed, 90 insertions(+), 24 deletions(-) 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 diff --git a/README.md b/README.md index 4cc1d72a..f7e1e789 100644 --- a/README.md +++ b/README.md @@ -350,7 +350,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/src/lib/AttributeResolver.php b/src/lib/AttributeResolver.php index cc41a6fb..09fe6b4f 100644 --- a/src/lib/AttributeResolver.php +++ b/src/lib/AttributeResolver.php @@ -278,7 +278,9 @@ protected function resolveProperty( if ($property->isRefPointerToSelf()) { $relation->asSelfReference(); } - $this->relations[$property->getName()] = $relation; + if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { + $this->relations[$property->getName()] = $relation; + } if (!$property->isRefPointerToSelf()) { $this->addInverseRelation($relatedClassName, $attribute, $property, $fkProperty); } @@ -321,21 +323,25 @@ protected function resolveProperty( $fkProperty->getName(), '_id' )) { + if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { + $this->relations[$property->getName()] = + Yii::createObject( + AttributeRelation::class, + [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] + ) + ->asHasMany([$fkProperty->getName() => $fkProperty->getName()])->asSelfReference(); + } + return; + } + $foreignPk = Inflector::camel2id($fkProperty->getName(), '_') . '_id'; + if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { $this->relations[$property->getName()] = Yii::createObject( AttributeRelation::class, [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] ) - ->asHasMany([$fkProperty->getName() => $fkProperty->getName()])->asSelfReference(); - return; + ->asHasMany([$foreignPk => $this->componentSchema->getPkName()]); } - $foreignPk = Inflector::camel2id($fkProperty->getName(), '_') . '_id'; - $this->relations[$property->getName()] = - Yii::createObject( - AttributeRelation::class, - [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] - ) - ->asHasMany([$foreignPk => $this->componentSchema->getPkName()]); return; } $relatedClassName = $property->getRefClassName(); @@ -349,13 +355,15 @@ protected function resolveProperty( return; } $attribute->setPhpType($relatedClassName . '[]'); - $this->relations[$property->getName()] = - Yii::createObject( - AttributeRelation::class, - [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] - ) - ->asHasMany([Inflector::camel2id($this->schemaName, '_') . '_id' => $this->componentSchema->getPkName()]) - ->setInverse(Inflector::variablize($this->schemaName)); + if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { + $this->relations[$property->getName()] = + Yii::createObject( + AttributeRelation::class, + [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] + ) + ->asHasMany([Inflector::camel2id($this->schemaName, '_') . '_id' => $this->componentSchema->getPkName()]) + ->setInverse(Inflector::variablize($this->schemaName)); + } return; } if ($this->componentSchema->isNonDb() && $attribute->isReference()) { 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..25498979 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 @@ -29,7 +29,6 @@ * @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/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/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index 64ca764d..4b03aa08 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -1001,4 +1001,20 @@ public function test74InvalidSchemaReferenceError() $this->runActualMigrations(); } + // https://github.com/php-openapi/yii2-openapi/issues/23 + public function test23ConsiderOpenapiExtensionXNoRelationAlsoInOtherPertinentPlace() + { +// 23-consider-openapi-extension-x-no-relation-also-in-other-pertinent-place +// 23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place + $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(); + } } From 253da362e351238015449de27be3b6631ebf99c6 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Wed, 19 Feb 2025 15:33:19 +0530 Subject: [PATCH 03/12] WIP --- src/lib/openapi/PropertySchema.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/openapi/PropertySchema.php b/src/lib/openapi/PropertySchema.php index eade252e..bc7296f6 100644 --- a/src/lib/openapi/PropertySchema.php +++ b/src/lib/openapi/PropertySchema.php @@ -497,6 +497,7 @@ public function guessDbType($forReference = false):string } return YiiDbSchema::TYPE_TEXT; case 'object': + case 'array': // TODO WIP Resume from here { return YiiDbSchema::TYPE_JSON; } From 618ce3b53f445540c562e0032308f2ab9218d5e6 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Fri, 21 Feb 2025 14:44:21 +0530 Subject: [PATCH 04/12] C --- tests/unit/IssueFixTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index 6d22d403..d0e2b514 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -1031,5 +1031,4 @@ public function test23ConsiderOpenapiExtensionXNoRelationAlsoInOtherPertinentPla // $this->checkFiles($actualFiles, $expectedFiles); // $this->runActualMigrations(); } - } From d9e47b0e33852da88dd07059dd10f2f7560ada84 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Fri, 21 Feb 2025 14:44:36 +0530 Subject: [PATCH 05/12] Format --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index f7e1e789..7d1c4c8a 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). - From f5e5c01e719a2f7f58f480b4525736845bf0f0dc Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Fri, 21 Feb 2025 16:24:50 +0530 Subject: [PATCH 06/12] Implementation in progress --- src/lib/AttributeResolver.php | 24 +++++++++---------- src/lib/openapi/ComponentSchema.php | 6 ++--- src/lib/openapi/PropertySchema.php | 14 +++++++++++ .../index.yaml | 1 + 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/lib/AttributeResolver.php b/src/lib/AttributeResolver.php index 09fe6b4f..e7bf4970 100644 --- a/src/lib/AttributeResolver.php +++ b/src/lib/AttributeResolver.php @@ -278,9 +278,9 @@ protected function resolveProperty( if ($property->isRefPointerToSelf()) { $relation->asSelfReference(); } - if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { - $this->relations[$property->getName()] = $relation; - } +// if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { + $this->relations[$property->getName()] = $relation; +// } if (!$property->isRefPointerToSelf()) { $this->addInverseRelation($relatedClassName, $attribute, $property, $fkProperty); } @@ -323,25 +323,25 @@ protected function resolveProperty( $fkProperty->getName(), '_id' )) { - if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { - $this->relations[$property->getName()] = +// if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { + $this->relations[$property->getName()] = Yii::createObject( AttributeRelation::class, [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] ) ->asHasMany([$fkProperty->getName() => $fkProperty->getName()])->asSelfReference(); - } +// } return; } $foreignPk = Inflector::camel2id($fkProperty->getName(), '_') . '_id'; - if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { - $this->relations[$property->getName()] = +// if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { + $this->relations[$property->getName()] = Yii::createObject( AttributeRelation::class, [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] ) ->asHasMany([$foreignPk => $this->componentSchema->getPkName()]); - } +// } return; } $relatedClassName = $property->getRefClassName(); @@ -355,15 +355,15 @@ protected function resolveProperty( return; } $attribute->setPhpType($relatedClassName . '[]'); - if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { - $this->relations[$property->getName()] = +// if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { + $this->relations[$property->getName()] = Yii::createObject( AttributeRelation::class, [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] ) ->asHasMany([Inflector::camel2id($this->schemaName, '_') . '_id' => $this->componentSchema->getPkName()]) ->setInverse(Inflector::variablize($this->schemaName)); - } +// } return; } if ($this->componentSchema->isNonDb() && $attribute->isReference()) { 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 bc7296f6..52459e11 100644 --- a/src/lib/openapi/PropertySchema.php +++ b/src/lib/openapi/PropertySchema.php @@ -145,6 +145,10 @@ public function __construct(SpecObjectInterface $property, string $name, Compone $property = $this->property; } + if ($this->getAttr(CustomSpecAttr::NO_RELATION)) { + return; + } + if ($property instanceof Reference) { $this->initReference(); } elseif ( @@ -182,6 +186,10 @@ private function initReference():void if ($this->refSchema && $this->refSchema->isNonDb()) { $this->isNonDbReference = true; } + if ($this->getAttr(CustomSpecAttr::NO_RELATION)) { + $this->isReference = false; + $this->isNonDbReference = true; + } } /** @@ -191,6 +199,9 @@ private function initReference():void private function initItemsReference():void { $this->isItemsReference = true; + if ($this->getAttr(CustomSpecAttr::NO_RELATION)) { + $this->isItemsReference = false; + } $items = $this->property->items ?? null; if (!$items) { return; @@ -206,6 +217,9 @@ private function initItemsReference():void if ($this->refSchema && $this->refSchema->isNonDb()) { $this->isNonDbReference = true; } + if ($this->getAttr(CustomSpecAttr::NO_RELATION)) { + $this->isNonDbReference = true; + } } public function setName(string $name):void 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 index 669f6239..b872617b 100644 --- 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 @@ -25,6 +25,7 @@ components: type: array x-no-relation: true items: + # type: string $ref: '#/components/schemas/Sample' Sample: From fe9b00a2d3c4e60eec8766b53a92ce90d48eb342 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Sat, 22 Feb 2025 16:56:52 +0530 Subject: [PATCH 07/12] Change logic --- src/lib/AttributeResolver.php | 8 -------- src/lib/openapi/PropertySchema.php | 13 ++----------- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/lib/AttributeResolver.php b/src/lib/AttributeResolver.php index e7bf4970..421c3f0a 100644 --- a/src/lib/AttributeResolver.php +++ b/src/lib/AttributeResolver.php @@ -278,9 +278,7 @@ protected function resolveProperty( if ($property->isRefPointerToSelf()) { $relation->asSelfReference(); } -// if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { $this->relations[$property->getName()] = $relation; -// } if (!$property->isRefPointerToSelf()) { $this->addInverseRelation($relatedClassName, $attribute, $property, $fkProperty); } @@ -323,25 +321,21 @@ protected function resolveProperty( $fkProperty->getName(), '_id' )) { -// if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { $this->relations[$property->getName()] = Yii::createObject( AttributeRelation::class, [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] ) ->asHasMany([$fkProperty->getName() => $fkProperty->getName()])->asSelfReference(); -// } return; } $foreignPk = Inflector::camel2id($fkProperty->getName(), '_') . '_id'; -// if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { $this->relations[$property->getName()] = Yii::createObject( AttributeRelation::class, [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] ) ->asHasMany([$foreignPk => $this->componentSchema->getPkName()]); -// } return; } $relatedClassName = $property->getRefClassName(); @@ -355,7 +349,6 @@ protected function resolveProperty( return; } $attribute->setPhpType($relatedClassName . '[]'); -// if (empty($property->getAttr(CustomSpecAttr::NO_RELATION))) { $this->relations[$property->getName()] = Yii::createObject( AttributeRelation::class, @@ -363,7 +356,6 @@ protected function resolveProperty( ) ->asHasMany([Inflector::camel2id($this->schemaName, '_') . '_id' => $this->componentSchema->getPkName()]) ->setInverse(Inflector::variablize($this->schemaName)); -// } return; } if ($this->componentSchema->isNonDb() && $attribute->isReference()) { diff --git a/src/lib/openapi/PropertySchema.php b/src/lib/openapi/PropertySchema.php index 52459e11..56d6df7a 100644 --- a/src/lib/openapi/PropertySchema.php +++ b/src/lib/openapi/PropertySchema.php @@ -145,6 +145,7 @@ 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; } @@ -186,10 +187,6 @@ private function initReference():void if ($this->refSchema && $this->refSchema->isNonDb()) { $this->isNonDbReference = true; } - if ($this->getAttr(CustomSpecAttr::NO_RELATION)) { - $this->isReference = false; - $this->isNonDbReference = true; - } } /** @@ -199,9 +196,6 @@ private function initReference():void private function initItemsReference():void { $this->isItemsReference = true; - if ($this->getAttr(CustomSpecAttr::NO_RELATION)) { - $this->isItemsReference = false; - } $items = $this->property->items ?? null; if (!$items) { return; @@ -217,9 +211,6 @@ private function initItemsReference():void if ($this->refSchema && $this->refSchema->isNonDb()) { $this->isNonDbReference = true; } - if ($this->getAttr(CustomSpecAttr::NO_RELATION)) { - $this->isNonDbReference = true; - } } public function setName(string $name):void @@ -511,7 +502,7 @@ public function guessDbType($forReference = false):string } return YiiDbSchema::TYPE_TEXT; case 'object': - case 'array': // TODO WIP Resume from here + case 'array': { return YiiDbSchema::TYPE_JSON; } From 15d588a8e05f6b7c9905c2365e09a3df996499c0 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Sat, 22 Feb 2025 16:58:42 +0530 Subject: [PATCH 08/12] Format --- src/lib/AttributeResolver.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/lib/AttributeResolver.php b/src/lib/AttributeResolver.php index 421c3f0a..c8f11b52 100644 --- a/src/lib/AttributeResolver.php +++ b/src/lib/AttributeResolver.php @@ -322,20 +322,20 @@ protected function resolveProperty( '_id' )) { $this->relations[$property->getName()] = - Yii::createObject( - AttributeRelation::class, - [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] - ) - ->asHasMany([$fkProperty->getName() => $fkProperty->getName()])->asSelfReference(); - return; - } - $foreignPk = Inflector::camel2id($fkProperty->getName(), '_') . '_id'; - $this->relations[$property->getName()] = Yii::createObject( AttributeRelation::class, [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] ) - ->asHasMany([$foreignPk => $this->componentSchema->getPkName()]); + ->asHasMany([$fkProperty->getName() => $fkProperty->getName()])->asSelfReference(); + return; + } + $foreignPk = Inflector::camel2id($fkProperty->getName(), '_') . '_id'; + $this->relations[$property->getName()] = + Yii::createObject( + AttributeRelation::class, + [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] + ) + ->asHasMany([$foreignPk => $this->componentSchema->getPkName()]); return; } $relatedClassName = $property->getRefClassName(); From 73cfcc44b0cfd11e94122e77f256cdcd66c5ae54 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Sat, 22 Feb 2025 16:59:16 +0530 Subject: [PATCH 09/12] Format 2 --- src/lib/AttributeResolver.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib/AttributeResolver.php b/src/lib/AttributeResolver.php index c8f11b52..cc41a6fb 100644 --- a/src/lib/AttributeResolver.php +++ b/src/lib/AttributeResolver.php @@ -350,12 +350,12 @@ protected function resolveProperty( } $attribute->setPhpType($relatedClassName . '[]'); $this->relations[$property->getName()] = - Yii::createObject( - AttributeRelation::class, - [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] - ) - ->asHasMany([Inflector::camel2id($this->schemaName, '_') . '_id' => $this->componentSchema->getPkName()]) - ->setInverse(Inflector::variablize($this->schemaName)); + Yii::createObject( + AttributeRelation::class, + [static::relationName($property->getName(), $property->fkColName), $relatedTableName, $relatedClassName] + ) + ->asHasMany([Inflector::camel2id($this->schemaName, '_') . '_id' => $this->componentSchema->getPkName()]) + ->setInverse(Inflector::variablize($this->schemaName)); return; } if ($this->componentSchema->isNonDb() && $attribute->isReference()) { From 2a36d5d9d05e756620986c1e3fe426ca775e8838 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Sat, 22 Feb 2025 17:25:54 +0530 Subject: [PATCH 10/12] Fix test --- .../m200000_000001_create_table_pets.php | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) 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', ]); } From c19c71e205228e2f8c5cd3f1e600493eccb6a0e7 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Sat, 22 Feb 2025 17:26:23 +0530 Subject: [PATCH 11/12] Fix test 2 --- .../mysql/models/base/Pet.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 25498979..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,7 +23,7 @@ * @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 From 9f10d85a6ec4c9a77b4996025d3981caa32bc03a Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Tue, 25 Feb 2025 14:33:04 +0530 Subject: [PATCH 12/12] Refactor + complete the test --- src/lib/ValidationRulesBuilder.php | 5 +- .../index.yaml | 1 - .../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 ++++ tests/unit/IssueFixTest.php | 18 +-- 12 files changed, 361 insertions(+), 15 deletions(-) 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 diff --git a/src/lib/ValidationRulesBuilder.php b/src/lib/ValidationRulesBuilder.php index 33a89949..33347314 100644 --- a/src/lib/ValidationRulesBuilder.php +++ b/src/lib/ValidationRulesBuilder.php @@ -243,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()) { 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 index b872617b..669f6239 100644 --- 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 @@ -25,7 +25,6 @@ components: type: array x-no-relation: true items: - # type: string $ref: '#/components/schemas/Sample' Sample: 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/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index d0e2b514..9d20ae4d 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -1018,17 +1018,15 @@ public function test22BugRulesRequiredIsGeneratedBeforeDefault() // https://github.com/php-openapi/yii2-openapi/issues/23 public function test23ConsiderOpenapiExtensionXNoRelationAlsoInOtherPertinentPlace() { -// 23-consider-openapi-extension-x-no-relation-also-in-other-pertinent-place -// 23_consider_openapi_extension_x_no_relation_also_in_other_pertinent_place $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(); + $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(); } }