From 50e28c06216bff9185455ec0d1df218997597913 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Tue, 24 Sep 2024 20:00:11 +0530 Subject: [PATCH 1/6] Create PR --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1cd2090b..3bb79307 100644 --- a/README.md +++ b/README.md @@ -568,3 +568,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 5156a737f79af65f637741082c3e3bd5d69f9917 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Wed, 25 Sep 2024 13:14:25 +0530 Subject: [PATCH 2/6] Add failing test --- README.md | 1 - composer.json | 8 +++-- .../51_bug_allof_with_description/index.php | 14 +++++++++ .../51_bug_allof_with_description/index.yml | 29 +++++++++++++++++++ tests/unit/IssueFixTest.php | 14 +++++++++ 5 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 tests/specs/issue_fix/51_bug_allof_with_description/index.php create mode 100644 tests/specs/issue_fix/51_bug_allof_with_description/index.yml diff --git a/README.md b/README.md index 3bb79307..1cd2090b 100644 --- a/README.md +++ b/README.md @@ -568,4 +568,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/composer.json b/composer.json index 735e5f07..cd2f4dc9 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ }, "require": { "php": "^7.4 || ^8.0", - "cebe/php-openapi": "^1.5.0", + "cebe/php-openapi": "dev-165-better-way-to-resolve-allof", "yiisoft/yii2": "~2.0.48", "yiisoft/yii2-gii": "~2.0.0 | ~2.1.0 | ~2.2.0| ~2.3.0", "laminas/laminas-code": ">=3.4 <=4.13", @@ -58,6 +58,10 @@ { "type": "composer", "url": "https://asset-packagist.org" - } + }, + { + "type": "vcs", + "url": "http://github.com/SOHELAHMED7/php-openapi" + } ] } diff --git a/tests/specs/issue_fix/51_bug_allof_with_description/index.php b/tests/specs/issue_fix/51_bug_allof_with_description/index.php new file mode 100644 index 00000000..9c657262 --- /dev/null +++ b/tests/specs/issue_fix/51_bug_allof_with_description/index.php @@ -0,0 +1,14 @@ + '@specs/issue_fix/51_bug_allof_with_description/index.yml', + 'generateUrls' => true, + 'generateModels' => true, + 'excludeModels' => [ + 'Error', + ], + 'generateControllers' => true, + 'generateMigrations' => true, + 'generateModelFaker' => true, // `generateModels` must be `true` in order to use `generateModelFaker` as `true` +]; + diff --git a/tests/specs/issue_fix/51_bug_allof_with_description/index.yml b/tests/specs/issue_fix/51_bug_allof_with_description/index.yml new file mode 100644 index 00000000..c7d6fb55 --- /dev/null +++ b/tests/specs/issue_fix/51_bug_allof_with_description/index.yml @@ -0,0 +1,29 @@ +openapi: 3.0.3 + +info: + title: 'Bug: allOf with description #51' + version: 1.0.0 + +components: + schemas: + Invoice: + title: Invoice + x-table: invoices + type: object + properties: + id: + type: integer + description: The PK + reference_invoice: + allOf: + - $ref: '#/components/schemas/Invoice' + - x-faker: false + - description: This field is only set on invoices of type "cancellation_invoice" + + +paths: + '/': + get: + responses: + '200': + description: OK diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index b6c7abdb..1ad0feb1 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/51 + public function test51BugAllofWithDescription() + { + $testFile = Yii::getAlias("@specs/issue_fix/51_bug_allof_with_description/index.php"); + $this->runGenerator($testFile); + // $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + // 'recursive' => true, + // ]); + // $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/51_bug_allof_with_description/mysql"), [ + // 'recursive' => true, + // ]); + // $this->checkFiles($actualFiles, $expectedFiles); + } } From d8165e1f86ef8cda56579c49a13ec4deaf6176d6 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Wed, 25 Sep 2024 18:47:05 +0530 Subject: [PATCH 3/6] Implementation --- src/generator/ApiGenerator.php | 5 +++-- src/lib/AttributeResolver.php | 37 +++++++++++++++++++++++++--------- src/lib/Config.php | 2 ++ src/lib/SchemaToDatabase.php | 3 ++- 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/generator/ApiGenerator.php b/src/generator/ApiGenerator.php index a7eff510..2f11197c 100644 --- a/src/generator/ApiGenerator.php +++ b/src/generator/ApiGenerator.php @@ -456,6 +456,7 @@ public function makeConfig():Config unset($props[$key]); } $this->config = new Config($props); + $this->config->resolvedOpenApi = $this->getOpenApiWithoutReferences(); $this->config->setFileRenderer(function ($template, $params) { return $this->render($template, $params); }); @@ -511,9 +512,9 @@ protected function getOpenApiWithoutReferences():OpenApi if ($this->_openApiWithoutRef === null) { $file = Yii::getAlias($this->openApiPath); if (StringHelper::endsWith($this->openApiPath, '.json', false)) { - $this->_openApiWithoutRef = Reader::readFromJsonFile($file, OpenApi::class, true); + $this->_openApiWithoutRef = Reader::readFromJsonFile($file, OpenApi::class, true, true); } else { - $this->_openApiWithoutRef = Reader::readFromYamlFile($file, OpenApi::class, true); + $this->_openApiWithoutRef = Reader::readFromYamlFile($file, OpenApi::class, true, true); } } return $this->_openApiWithoutRef; diff --git a/src/lib/AttributeResolver.php b/src/lib/AttributeResolver.php index 906226d4..5e1ceb0b 100644 --- a/src/lib/AttributeResolver.php +++ b/src/lib/AttributeResolver.php @@ -76,10 +76,19 @@ class AttributeResolver /** @var Config */ private $config; - public function __construct(string $schemaName, ComponentSchema $schema, JunctionSchemas $junctions, ?Config $config = null) + public $resolvedComponentSchema; + + public function __construct( + string $schemaName, + ComponentSchema $schema, + JunctionSchemas $junctions, + ?Config $config = null, + $resolvedComponentSchema = null + ) { $this->schemaName = $schemaName; $this->componentSchema = $schema; + $this->resolvedComponentSchema = $resolvedComponentSchema; $this->tableName = $schema->resolveTableName($schemaName); $this->junctions = $junctions; $this->isJunctionSchema = $junctions->isJunctionSchema($schemaName); @@ -94,9 +103,18 @@ public function __construct(string $schemaName, ComponentSchema $schema, Junctio */ public function resolve():DbModel { - foreach ($this->componentSchema->getProperties() as $property) { + foreach ($this->componentSchema->getProperties() as $key => $property) { /** @var $property \cebe\yii2openapi\lib\openapi\PropertySchema */ + $resolvedProperty = null; + if ($this->resolvedComponentSchema) { + foreach ($this->resolvedComponentSchema->getProperties() as $key2 => $prop) { + if ($key === $key2) { + $resolvedProperty = $prop; + } + } + } + $isRequired = $this->componentSchema->isRequiredProperty($property->getName()); $nullableValue = $property->getProperty()->getSerializableData()->nullable ?? null; if ($nullableValue === false) { // see docs in README regarding NOT NULL, required and nullable @@ -106,9 +124,9 @@ public function resolve():DbModel if ($this->isJunctionSchema) { $this->resolveJunctionTableProperty($property, $isRequired); } elseif ($this->hasMany2Many) { - $this->resolveHasMany2ManyTableProperty($property, $isRequired); + $this->resolveHasMany2ManyTableProperty($property, $isRequired, $resolvedProperty); } else { - $this->resolveProperty($property, $isRequired, $nullableValue); + $this->resolveProperty($property, $isRequired, $nullableValue, $resolvedProperty); } } return Yii::createObject(DbModel::class, [ @@ -169,7 +187,7 @@ protected function resolveJunctionTableProperty(PropertySchema $property, bool $ * @throws \cebe\yii2openapi\lib\exceptions\InvalidDefinitionException * @throws \yii\base\InvalidConfigException */ - protected function resolveHasMany2ManyTableProperty(PropertySchema $property, bool $isRequired):void + protected function resolveHasMany2ManyTableProperty(PropertySchema $property, bool $isRequired, $resolvedProperty = null):void { if ($this->junctions->isManyToManyProperty($this->schemaName, $property->getName())) { return; @@ -203,7 +221,7 @@ protected function resolveHasMany2ManyTableProperty(PropertySchema $property, bo return; } - $this->resolveProperty($property, $isRequired); + $this->resolveProperty($property, $isRequired, $resolvedProperty); } /** @@ -216,14 +234,15 @@ protected function resolveHasMany2ManyTableProperty(PropertySchema $property, bo protected function resolveProperty( PropertySchema $property, bool $isRequired, - $nullableValue = 'ARG_ABSENT' + $nullableValue = 'ARG_ABSENT', + $resolvedProperty = null ):void { if ($nullableValue === 'ARG_ABSENT') { $nullableValue = $property->getProperty()->getSerializableData()->nullable ?? null; } $attribute = Yii::createObject(Attribute::class, [$property->getName()]); $attribute->setRequired($isRequired) - ->setDescription($property->getAttr('description', '')) + ->setDescription($resolvedProperty ? $resolvedProperty->getAttr('description', '') : $property->getAttr('description', '')) ->setReadOnly($property->isReadonly()) ->setDefault($property->guessDefault()) ->setXDbType($property->getAttr(CustomSpecAttr::DB_TYPE)) @@ -262,7 +281,7 @@ protected function resolveProperty( $attribute->setPhpType($fkProperty->guessPhpType()) ->setDbType($fkProperty->guessDbType(true)) ->setSize($fkProperty->getMaxLength()) - ->setDescription($property->getRefSchema()->getDescription()) + ->setDescription($resolvedProperty ? $resolvedProperty->getAttr('description', '') : $property->getRefSchema()->getDescription()) ->setDefault($fkProperty->guessDefault()) ->setLimits($min, $max, $fkProperty->getMinLength()); diff --git a/src/lib/Config.php b/src/lib/Config.php index bd4934a0..7b8ebbf2 100644 --- a/src/lib/Config.php +++ b/src/lib/Config.php @@ -164,6 +164,8 @@ class Config extends BaseObject */ private $openApi; + public $resolvedOpenApi; + /** * @return \cebe\openapi\spec\OpenApi * @throws \cebe\openapi\exceptions\IOException diff --git a/src/lib/SchemaToDatabase.php b/src/lib/SchemaToDatabase.php index 0e93ff29..5aa2445a 100644 --- a/src/lib/SchemaToDatabase.php +++ b/src/lib/SchemaToDatabase.php @@ -81,6 +81,7 @@ public function prepareModels():array $junctions = $this->findJunctionSchemas(); foreach ($openApi->components->schemas as $schemaName => $openApiSchema) { $schema = Yii::createObject(ComponentSchema::class, [$openApiSchema, $schemaName]); + $resolvedComponentSchema = Yii::createObject(ComponentSchema::class, [$this->config->resolvedOpenApi->components->schemas[$schemaName], $schemaName]); if (!$this->canGenerateModel($schemaName, $schema)) { continue; @@ -89,7 +90,7 @@ public function prepareModels():array $schemaName = $junctions->trimPrefix($schemaName); } /**@var \cebe\yii2openapi\lib\AttributeResolver $resolver */ - $resolver = Yii::createObject(AttributeResolver::class, [$schemaName, $schema, $junctions, $this->config]); + $resolver = Yii::createObject(AttributeResolver::class, [$schemaName, $schema, $junctions, $this->config, $resolvedComponentSchema]); $models[$schemaName] = $resolver->resolve(); } foreach ($models as $model) { From 14984de8d7a2082361a905d098e927cef5ac0567 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Wed, 25 Sep 2024 18:47:59 +0530 Subject: [PATCH 4/6] Fix failing test --- tests/specs/blog_jsonapi.yaml | 8 ++++---- tests/unit/SchemaToDatabaseTest.php | 10 +++++++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/tests/specs/blog_jsonapi.yaml b/tests/specs/blog_jsonapi.yaml index bd6581df..5d1b1464 100644 --- a/tests/specs/blog_jsonapi.yaml +++ b/tests/specs/blog_jsonapi.yaml @@ -690,8 +690,8 @@ components: included: type: array items: - allOf: - - $ref: '#/components/schemas/_PostResource' +# allOf: # TODO undo + $ref: '#/components/schemas/_PostResource' CategoryCreatedResponse: description: Single category info headers: @@ -806,8 +806,8 @@ components: included: type: array items: - allOf: - - $ref: '#/components/schemas/_PostResource' +# allOf: # TODO undo + $ref: '#/components/schemas/_PostResource' PostListResponse: description: List posts with pagination content: diff --git a/tests/unit/SchemaToDatabaseTest.php b/tests/unit/SchemaToDatabaseTest.php index e18a5c0b..8da4d54f 100644 --- a/tests/unit/SchemaToDatabaseTest.php +++ b/tests/unit/SchemaToDatabaseTest.php @@ -10,6 +10,7 @@ use cebe\yii2openapi\lib\SchemaToDatabase; use tests\TestCase; use Yii; +use yii\helpers\StringHelper; use yii\helpers\VarDumper; use function array_keys; @@ -72,7 +73,14 @@ public function testFindJunctionSchemas() public function testGenerateModels() { $schemaFile = Yii::getAlias("@specs/many2many.yaml"); - $converter = new SchemaToDatabase(new Config(['openApiPath' => $schemaFile])); + + if (StringHelper::endsWith($schemaFile, '.json', false)) { + $openapi = Reader::readFromJsonFile($schemaFile, OpenApi::class, true, true); + } else { + $openapi = Reader::readFromYamlFile($schemaFile, OpenApi::class, true, true); + } + + $converter = new SchemaToDatabase(new Config(['openApiPath' => $schemaFile, 'resolvedOpenApi' => $openapi])); $result = $converter->prepareModels(); self::assertNotEmpty($result); self::assertArrayHasKey('Post', $result); From 7bcf57d587c590e260fdbc7d50c1c34c1849b956 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Wed, 25 Sep 2024 18:50:00 +0530 Subject: [PATCH 5/6] Fix style --- composer.json | 8 ++++---- src/generator/default/dbmodel.php | 8 ++++---- src/lib/AttributeResolver.php | 3 +-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index cd2f4dc9..c957e974 100644 --- a/composer.json +++ b/composer.json @@ -59,9 +59,9 @@ "type": "composer", "url": "https://asset-packagist.org" }, - { - "type": "vcs", - "url": "http://github.com/SOHELAHMED7/php-openapi" - } + { + "type": "vcs", + "url": "http://github.com/SOHELAHMED7/php-openapi" + } ] } diff --git a/src/generator/default/dbmodel.php b/src/generator/default/dbmodel.php index 17fa4a84..a3d269b6 100644 --- a/src/generator/default/dbmodel.php +++ b/src/generator/default/dbmodel.php @@ -49,8 +49,8 @@ */ abstract class getClassName() ?> extends \yii\db\ActiveRecord { -getScenarios()): -foreach($scenarios as $scenario): ?> +getScenarios()): +foreach ($scenarios as $scenario): ?> /** * @@ -76,7 +76,7 @@ public static function tableName() { return getTableAlias()) ?>; } - + /** * Automatically generated scenarios from the model 'x-scenarios'. @@ -92,7 +92,7 @@ public function scenarios() $default = parent::scenarios()[self::SCENARIO_DEFAULT]; return [ - + self:: => $default, /** diff --git a/src/lib/AttributeResolver.php b/src/lib/AttributeResolver.php index 5e1ceb0b..966872c1 100644 --- a/src/lib/AttributeResolver.php +++ b/src/lib/AttributeResolver.php @@ -84,8 +84,7 @@ public function __construct( JunctionSchemas $junctions, ?Config $config = null, $resolvedComponentSchema = null - ) - { + ) { $this->schemaName = $schemaName; $this->componentSchema = $schema; $this->resolvedComponentSchema = $resolvedComponentSchema; From 338273268cc3d377332a9a6cccdbe0c0609aa798 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Wed, 25 Sep 2024 18:54:22 +0530 Subject: [PATCH 6/6] Complete the test --- .../mysql/config/urls.rest.php | 10 ++ .../mysql/controllers/DefaultController.php | 20 +++ .../controllers/base/DefaultController.php | 32 ++++ .../m200000_000000_create_table_invoices.php | 22 +++ .../mysql/models/BaseModelFaker.php | 144 ++++++++++++++++++ .../mysql/models/Invoice.php | 10 ++ .../mysql/models/InvoiceFaker.php | 49 ++++++ .../mysql/models/base/Invoice.php | 36 +++++ tests/unit/IssueFixTest.php | 14 +- 9 files changed, 330 insertions(+), 7 deletions(-) create mode 100644 tests/specs/issue_fix/51_bug_allof_with_description/mysql/config/urls.rest.php create mode 100644 tests/specs/issue_fix/51_bug_allof_with_description/mysql/controllers/DefaultController.php create mode 100644 tests/specs/issue_fix/51_bug_allof_with_description/mysql/controllers/base/DefaultController.php create mode 100644 tests/specs/issue_fix/51_bug_allof_with_description/mysql/migrations_mysql_db/m200000_000000_create_table_invoices.php create mode 100644 tests/specs/issue_fix/51_bug_allof_with_description/mysql/models/BaseModelFaker.php create mode 100644 tests/specs/issue_fix/51_bug_allof_with_description/mysql/models/Invoice.php create mode 100644 tests/specs/issue_fix/51_bug_allof_with_description/mysql/models/InvoiceFaker.php create mode 100644 tests/specs/issue_fix/51_bug_allof_with_description/mysql/models/base/Invoice.php diff --git a/tests/specs/issue_fix/51_bug_allof_with_description/mysql/config/urls.rest.php b/tests/specs/issue_fix/51_bug_allof_with_description/mysql/config/urls.rest.php new file mode 100644 index 00000000..fc946717 --- /dev/null +++ b/tests/specs/issue_fix/51_bug_allof_with_description/mysql/config/urls.rest.php @@ -0,0 +1,10 @@ + 'default/', + '' => 'default/options', +]; diff --git a/tests/specs/issue_fix/51_bug_allof_with_description/mysql/controllers/DefaultController.php b/tests/specs/issue_fix/51_bug_allof_with_description/mysql/controllers/DefaultController.php new file mode 100644 index 00000000..484d28ff --- /dev/null +++ b/tests/specs/issue_fix/51_bug_allof_with_description/mysql/controllers/DefaultController.php @@ -0,0 +1,20 @@ + [ + 'class' => \yii\rest\OptionsAction::class, + ], + ]; + } + + /** + * Checks the privilege of the current user. + * + * This method checks whether the current user has the privilege + * to run the specified action against the specified data model. + * If the user does not have access, a [[ForbiddenHttpException]] should be thrown. + * + * @param string $action the ID of the action to be executed + * @param object $model the model to be accessed. If null, it means no specific model is being accessed. + * @param array $params additional parameters + * @throws \yii\web\ForbiddenHttpException if the user does not have access + */ + abstract public function checkAccess($action, $model = null, $params = []); + + abstract public function action(); + +} diff --git a/tests/specs/issue_fix/51_bug_allof_with_description/mysql/migrations_mysql_db/m200000_000000_create_table_invoices.php b/tests/specs/issue_fix/51_bug_allof_with_description/mysql/migrations_mysql_db/m200000_000000_create_table_invoices.php new file mode 100644 index 00000000..67c48300 --- /dev/null +++ b/tests/specs/issue_fix/51_bug_allof_with_description/mysql/migrations_mysql_db/m200000_000000_create_table_invoices.php @@ -0,0 +1,22 @@ +createTable('{{%invoices}}', [ + 'id' => $this->primaryKey(), + 'reference_invoice_id' => $this->integer()->null()->defaultValue(null), + ]); + $this->addForeignKey('fk_invoices_reference_invoice_id_invoices_id', '{{%invoices}}', 'reference_invoice_id', '{{%invoices}}', 'id'); + } + + public function down() + { + $this->dropForeignKey('fk_invoices_reference_invoice_id_invoices_id', '{{%invoices}}'); + $this->dropTable('{{%invoices}}'); + } +} diff --git a/tests/specs/issue_fix/51_bug_allof_with_description/mysql/models/BaseModelFaker.php b/tests/specs/issue_fix/51_bug_allof_with_description/mysql/models/BaseModelFaker.php new file mode 100644 index 00000000..c367fbb4 --- /dev/null +++ b/tests/specs/issue_fix/51_bug_allof_with_description/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/51_bug_allof_with_description/mysql/models/Invoice.php b/tests/specs/issue_fix/51_bug_allof_with_description/mysql/models/Invoice.php new file mode 100644 index 00000000..43e37fd3 --- /dev/null +++ b/tests/specs/issue_fix/51_bug_allof_with_description/mysql/models/Invoice.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 Invoice(); + //$model->id = $uniqueFaker->numberBetween(0, 1000000); + 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 + 'Invoice', + + ]; + } +} diff --git a/tests/specs/issue_fix/51_bug_allof_with_description/mysql/models/base/Invoice.php b/tests/specs/issue_fix/51_bug_allof_with_description/mysql/models/base/Invoice.php new file mode 100644 index 00000000..6194afb0 --- /dev/null +++ b/tests/specs/issue_fix/51_bug_allof_with_description/mysql/models/base/Invoice.php @@ -0,0 +1,36 @@ + [['reference_invoice_id'], 'integer'], + 'reference_invoice_id_exist' => [['reference_invoice_id'], 'exist', 'targetRelation' => 'ReferenceInvoice'], + ]; + } + + public function getReferenceInvoice() + { + return $this->hasOne(\app\models\Invoice::class, ['id' => 'reference_invoice_id']); + } +} diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index 1ad0feb1..b69bfbef 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -366,12 +366,12 @@ public function test51BugAllofWithDescription() { $testFile = Yii::getAlias("@specs/issue_fix/51_bug_allof_with_description/index.php"); $this->runGenerator($testFile); - // $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ - // 'recursive' => true, - // ]); - // $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/51_bug_allof_with_description/mysql"), [ - // 'recursive' => true, - // ]); - // $this->checkFiles($actualFiles, $expectedFiles); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/51_bug_allof_with_description/mysql"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); } }