diff --git a/README.md b/README.md index aae945c5..f68df469 100644 --- a/README.md +++ b/README.md @@ -465,6 +465,60 @@ Generated URL rules config for above is (in `urls.rest.php` or pertinent file): ``` `x-route` does not support [Yii Modules](https://www.yiiframework.com/doc/guide/2.0/en/structure-modules). +### `x-description-is-comment` + + boolean; default: false + +When a new database table is created from new OpenAPI component schema, description of a property will be used as +comment of column (of database table). + +This extension is used when a description is edited for existing property, and you want to generate migration for its +corresponding column comment changes. + +This extension can be used at 3 place: + +**1. root level (highest priority)** + +```yaml +openapi: 3.0.3 +x-description-is-comment: true +info: + title: Description +``` + +This will create migration of any changed description of component schema property present throughout the spec. + +**2. component schema level** + +```yaml +components: + schemas: + Fruit: + type: object + x-description-is-comment: true +``` + +This will create migration of changed description of only properties of component schema which have this extension. + +**3. property level (lowest priority)** + +```yaml +components: + schemas: + Fruit: + type: object + properties: + id: + type: integer + name: + type: string + nullable: false + x-description-is-comment: true + description: Hi there +``` + +Migrations will be only generated for changed description of properties having this extension. + ## Many-to-Many relation definition There are two ways for define many-to-many relations: diff --git a/src/lib/AttributeResolver.php b/src/lib/AttributeResolver.php index 92014c6e..a43aa8ba 100644 --- a/src/lib/AttributeResolver.php +++ b/src/lib/AttributeResolver.php @@ -117,6 +117,7 @@ public function resolve(): DbModel //For valid primary keys for junction tables 'junctionCols' => $this->isJunctionSchema ? $this->junctions->junctionCols($this->schemaName) : [], 'isNotDb' => $this->componentSchema->isNonDb(), + 'descriptionIsComment' => !empty(($this->componentSchema->getSchema()->{CustomSpecAttr::DESC_IS_COMMENT})) ], ]); } @@ -225,6 +226,7 @@ protected function resolveProperty( ->setDefault($property->guessDefault()) ->setXDbType($property->getAttr(CustomSpecAttr::DB_TYPE)) ->setXDbDefaultExpression($property->getAttr(CustomSpecAttr::DB_DEFAULT_EXPRESSION)) + ->setXDescriptionIsComment($property->getAttr(CustomSpecAttr::DESC_IS_COMMENT)) ->setNullable($nullableValue) ->setIsPrimary($property->isPrimaryKey()) ->setForeignKeyColumnName($property->fkColName) diff --git a/src/lib/ColumnToCode.php b/src/lib/ColumnToCode.php index fdbdfc72..f4da8079 100644 --- a/src/lib/ColumnToCode.php +++ b/src/lib/ColumnToCode.php @@ -84,9 +84,9 @@ class ColumnToCode */ private $isPk = false; - private $rawParts = ['type' => null, 'nullable' => null, 'default' => null, 'position' => null]; + private $rawParts = ['type' => null, 'nullable' => null, 'default' => null, 'position' => null, 'comment' => null]; - private $fluentParts = ['type' => null, 'nullable' => null, 'default' => null, 'position' => null]; + private $fluentParts = ['type' => null, 'nullable' => null, 'default' => null, 'position' => null, 'comment' => null]; /** * @var bool @@ -150,6 +150,60 @@ public function __construct( $this->resolve(); } + private function resolve():void + { + $dbType = $this->typeWithoutSize(strtolower($this->column->dbType)); + $type = $this->column->type; + $this->resolvePosition(); + //Primary Keys + if (array_key_exists($type, self::PK_TYPE_MAP)) { + $this->rawParts['type'] = $type; + $this->fluentParts['type'] = self::PK_TYPE_MAP[$type]; + $this->isPk = true; + return; + } + if (array_key_exists($dbType, self::PK_TYPE_MAP)) { + $this->rawParts['type'] = $dbType; + $this->fluentParts['type'] = self::PK_TYPE_MAP[$dbType]; + $this->isPk = true; + return; + } + + if ($dbType === 'varchar') { + $type = $dbType = 'string'; + } + $fluentSize = $this->column->size ? '(' . $this->column->size . ')' : '()'; + $rawSize = $this->column->size ? '(' . $this->column->size . ')' : ''; + $this->rawParts['nullable'] = $this->column->allowNull ? 'NULL' : 'NOT NULL'; + $this->fluentParts['nullable'] = $this->column->allowNull === true ? 'null()' : 'notNull()'; + + $this->fluentParts['comment'] = $this->column->comment ? 'comment('.var_export($this->column->comment, true).')' : $this->fluentParts['comment']; + $this->rawParts['comment'] = $this->column->comment ? 'COMMENT '.var_export($this->column->comment, true) : $this->rawParts['comment']; + + if (array_key_exists($dbType, self::INT_TYPE_MAP)) { + $this->fluentParts['type'] = self::INT_TYPE_MAP[$dbType] . $fluentSize; + $this->rawParts['type'] = + $this->column->dbType . (strpos($this->column->dbType, '(') !== false ? '' : $rawSize); + } elseif (array_key_exists($type, self::INT_TYPE_MAP)) { + $this->fluentParts['type'] = self::INT_TYPE_MAP[$type] . $fluentSize; + $this->rawParts['type'] = + $this->column->dbType . (strpos($this->column->dbType, '(') !== false ? '' : $rawSize); + } elseif ($this->isEnum()) { + $this->resolveEnumType(); + } elseif ($this->isDecimal()) { + $this->fluentParts['type'] = $this->column->dbType; + $this->rawParts['type'] = $this->column->dbType; + } else { + $this->fluentParts['type'] = $type . $fluentSize; + $this->rawParts['type'] = + $this->column->dbType . (strpos($this->column->dbType, '(') !== false ? '' : $rawSize); + } + + $this->isBuiltinType = $this->raw ? false : $this->getIsBuiltinType($type, $dbType); + + $this->resolveDefaultValue(); + } + public function getCode(bool $quoted = false):string { if ($this->isPk) { @@ -160,7 +214,8 @@ public function getCode(bool $quoted = false):string $this->fluentParts['type'], $this->fluentParts['nullable'], $this->fluentParts['default'], - $this->fluentParts['position'] + $this->fluentParts['position'], + $this->fluentParts['comment'], ]); array_unshift($parts, '$this'); return implode('->', array_filter(array_map('trim', $parts))); @@ -175,9 +230,12 @@ public function getCode(bool $quoted = false):string } $code = $this->rawParts['type'] . ' ' . $this->rawParts['nullable'] . $default; - if ((ApiGenerator::isMysql() || ApiGenerator::isMariaDb()) && $this->rawParts['position']) { - $code .= ' ' . $this->rawParts['position']; + + if ((ApiGenerator::isMysql() || ApiGenerator::isMariaDb())) { + $code .= $this->rawParts['position'] ? ' ' . $this->rawParts['position'] : ''; + $code .= $this->rawParts['comment'] ? ' '.$this->rawParts['comment'] : ''; } + if (ApiGenerator::isPostgres() && $this->alterByXDbType) { return $quoted ? VarDumper::export($this->rawParts['type']) : $this->rawParts['type']; } @@ -320,56 +378,6 @@ private function defaultValueArray(array $value):string return "'{" . trim(Json::encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_QUOT), '[]') . "}'"; } - private function resolve():void - { - $dbType = $this->typeWithoutSize(strtolower($this->column->dbType)); - $type = $this->column->type; - $this->resolvePosition(); - //Primary Keys - if (array_key_exists($type, self::PK_TYPE_MAP)) { - $this->rawParts['type'] = $type; - $this->fluentParts['type'] = self::PK_TYPE_MAP[$type]; - $this->isPk = true; - return; - } - if (array_key_exists($dbType, self::PK_TYPE_MAP)) { - $this->rawParts['type'] = $dbType; - $this->fluentParts['type'] = self::PK_TYPE_MAP[$dbType]; - $this->isPk = true; - return; - } - - if ($dbType === 'varchar') { - $type = $dbType = 'string'; - } - $fluentSize = $this->column->size ? '(' . $this->column->size . ')' : '()'; - $rawSize = $this->column->size ? '(' . $this->column->size . ')' : ''; - $this->rawParts['nullable'] = $this->column->allowNull ? 'NULL' : 'NOT NULL'; - $this->fluentParts['nullable'] = $this->column->allowNull === true ? 'null()' : 'notNull()'; - if (array_key_exists($dbType, self::INT_TYPE_MAP)) { - $this->fluentParts['type'] = self::INT_TYPE_MAP[$dbType] . $fluentSize; - $this->rawParts['type'] = - $this->column->dbType . (strpos($this->column->dbType, '(') !== false ? '' : $rawSize); - } elseif (array_key_exists($type, self::INT_TYPE_MAP)) { - $this->fluentParts['type'] = self::INT_TYPE_MAP[$type] . $fluentSize; - $this->rawParts['type'] = - $this->column->dbType . (strpos($this->column->dbType, '(') !== false ? '' : $rawSize); - } elseif ($this->isEnum()) { - $this->resolveEnumType(); - } elseif ($this->isDecimal()) { - $this->fluentParts['type'] = $this->column->dbType; - $this->rawParts['type'] = $this->column->dbType; - } else { - $this->fluentParts['type'] = $type . $fluentSize; - $this->rawParts['type'] = - $this->column->dbType . (strpos($this->column->dbType, '(') !== false ? '' : $rawSize); - } - - $this->isBuiltinType = $this->raw ? false : $this->getIsBuiltinType($type, $dbType); - - $this->resolveDefaultValue(); - } - /** * @param $type * @param $dbType diff --git a/src/lib/CustomSpecAttr.php b/src/lib/CustomSpecAttr.php index e4638746..6234f7a9 100644 --- a/src/lib/CustomSpecAttr.php +++ b/src/lib/CustomSpecAttr.php @@ -56,4 +56,10 @@ class CustomSpecAttr * Custom route (controller ID/action ID) instead of auto-generated. See README for usage docs. https://github.com/cebe/yii2-openapi/issues/144 */ public const ROUTE = 'x-route'; + + + /** + * Generate migrations for changed description of property. More docs is present in README.md file + */ + public const DESC_IS_COMMENT = 'x-description-is-comment'; } diff --git a/src/lib/generators/MigrationsGenerator.php b/src/lib/generators/MigrationsGenerator.php index 1c0dfb51..211e4639 100644 --- a/src/lib/generators/MigrationsGenerator.php +++ b/src/lib/generators/MigrationsGenerator.php @@ -12,7 +12,6 @@ use cebe\yii2openapi\lib\items\DbModel; use cebe\yii2openapi\lib\items\MigrationModel; use cebe\yii2openapi\lib\migrations\BaseMigrationBuilder; -use cebe\yii2openapi\lib\migrations\MigrationRecordBuilder; use cebe\yii2openapi\lib\migrations\MysqlMigrationBuilder; use cebe\yii2openapi\lib\migrations\PostgresMigrationBuilder; use Exception; @@ -139,10 +138,11 @@ public function buildMigrations():array */ protected function createBuilder(DbModel $model):BaseMigrationBuilder { + $params = [$this->db, $model, $this->config]; if ($this->db->getDriverName() === 'pgsql') { - return Yii::createObject(PostgresMigrationBuilder::class, [$this->db, $model]); + return Yii::createObject(PostgresMigrationBuilder::class, $params); } - return Yii::createObject(MysqlMigrationBuilder::class, [$this->db, $model]); + return Yii::createObject(MysqlMigrationBuilder::class, $params); } /** diff --git a/src/lib/items/Attribute.php b/src/lib/items/Attribute.php index 8b0306c9..c079d06b 100644 --- a/src/lib/items/Attribute.php +++ b/src/lib/items/Attribute.php @@ -61,13 +61,6 @@ class Attribute extends BaseObject */ public $dbType = 'string'; - /** - * Custom db type - * string | null | false - * if `false` then this attribute is virtual - */ - public $xDbType; - /** * nullable * bool | null @@ -128,6 +121,18 @@ class Attribute extends BaseObject **/ public $isVirtual = false; + /** + * Custom db type + * string | null | false + * if `false` then this attribute is virtual + */ + public $xDbType; + + /** + * @see \cebe\yii2openapi\lib\CustomSpecAttr::DESC_IS_COMMENT + */ + public ?bool $xDescriptionIsComment = false; + public function __construct(string $propertyName, array $config = []) { $this->propertyName = $propertyName; @@ -322,6 +327,7 @@ public function toColumnSchema(): ColumnSchema 'allowNull' => $this->allowNull(), 'size' => $this->size > 0 ? $this->size : null, 'xDbType' => $this->xDbType, + 'comment' => $this->description, ]); $column->isPrimaryKey = $this->primary; $column->autoIncrement = $this->primary && $this->phpType === 'int'; @@ -396,4 +402,10 @@ public function handleDecimal(ColumnSchema $columnSchema): void $columnSchema->dbType = $decimalAttributes['dbType']; } } + + public function setXDescriptionIsComment($xDescriptionIsComment): Attribute + { + $this->xDescriptionIsComment = $xDescriptionIsComment; + return $this; + } } diff --git a/src/lib/items/DbModel.php b/src/lib/items/DbModel.php index 1deb9fbc..08135d71 100644 --- a/src/lib/items/DbModel.php +++ b/src/lib/items/DbModel.php @@ -88,6 +88,8 @@ class DbModel extends BaseObject */ public $scenarioDefaultDescription = "Scenario {scenarioName}"; + public bool $descriptionIsComment = false; + /** * @var array Automatically generated scenarios from the model 'x-scenarios'. */ diff --git a/src/lib/migrations/BaseMigrationBuilder.php b/src/lib/migrations/BaseMigrationBuilder.php index 831f6f3d..2cf1702a 100644 --- a/src/lib/migrations/BaseMigrationBuilder.php +++ b/src/lib/migrations/BaseMigrationBuilder.php @@ -9,6 +9,8 @@ use cebe\yii2openapi\generator\ApiGenerator; use cebe\yii2openapi\lib\ColumnToCode; +use cebe\yii2openapi\lib\Config; +use cebe\yii2openapi\lib\CustomSpecAttr; use cebe\yii2openapi\lib\items\DbModel; use cebe\yii2openapi\lib\items\ManyToManyRelation; use cebe\yii2openapi\lib\items\MigrationModel; @@ -53,6 +55,8 @@ abstract class BaseMigrationBuilder */ protected $recordBuilder; + protected ?Config $config = null; + /** * MigrationBuilder constructor. * @param \yii\db\Connection $db @@ -60,12 +64,13 @@ abstract class BaseMigrationBuilder * @throws \yii\base\InvalidConfigException * @throws \yii\base\NotSupportedException */ - public function __construct(Connection $db, DbModel $model) + public function __construct(Connection $db, DbModel $model, ?Config $config = null) { $this->db = $db; $this->model = $model; $this->tableSchema = $db->getTableSchema($model->getTableAlias(), true); $this->recordBuilder = Yii::createObject(MigrationRecordBuilder::class, [$db->getSchema()]); + $this->config = $config; } /** @@ -162,6 +167,8 @@ public function buildFresh():MigrationModel } } + $this->handleCommentsMigration(); + return $this->migration; } @@ -294,6 +301,8 @@ abstract public static function getColumnSchemaBuilderClass(): string; */ abstract protected function findTableIndexes():array; + abstract public function handleCommentsMigration(); + protected function buildIndexChanges():void { $haveIndexes = $this->findTableIndexes(); @@ -467,7 +476,7 @@ public function tmpSaveNewCol(string $tableAlias, \cebe\yii2openapi\db\ColumnSch if (ApiGenerator::isPostgres() && static::isEnum($columnSchema)) { $allEnumValues = $columnSchema->enumValues; $allEnumValues = array_map(function ($aValue) { - return "'$aValue'"; + return $this->db->quoteValue($aValue); }, $allEnumValues); Yii::$app->db->createCommand( 'CREATE TYPE '.$tmpEnumName($columnSchema->name).' AS ENUM('.implode(', ', $allEnumValues).')' @@ -475,6 +484,9 @@ public function tmpSaveNewCol(string $tableAlias, \cebe\yii2openapi\db\ColumnSch } Yii::$app->db->createCommand()->createTable($tmpTableName, $column)->execute(); + if (ApiGenerator::isPostgres() && $columnSchema->comment) { + Yii::$app->db->createCommand("COMMENT ON COLUMN $tmpTableName.$columnSchema->name IS {$this->db->quoteValue($columnSchema->comment)}")->execute(); + } $table = Yii::$app->db->getTableSchema($tmpTableName); @@ -496,7 +508,8 @@ public function tmpSaveNewCol(string $tableAlias, \cebe\yii2openapi\db\ColumnSch public function newColStr(string $tableAlias, \cebe\yii2openapi\db\ColumnSchema $columnSchema): string { $ctc = new ColumnToCode(\Yii::$app->db->schema, $tableAlias, $columnSchema, false, false, true); - return ColumnToCode::undoEscapeQuotes($ctc->getCode()); +// return ColumnToCode::undoEscapeQuotes($ctc->getCode()); + return $ctc->getCode(); } public static function isEnum(\yii\db\ColumnSchema $columnSchema): bool @@ -585,4 +598,20 @@ public function buildTablesDrop(): void abstract public function findPosition(ColumnSchema $column, bool $forDrop = false, bool $forAlter = false): ?string; abstract public function setColumnsPositions(); + + protected function shouldCompareComment(ColumnSchema $desired): bool + { + $comment = false; + if (isset($this->model->attributes[$desired->name]) && $this->model->attributes[$desired->name]->xDescriptionIsComment) { + $comment = true; + } + if ($this->model->descriptionIsComment) { + $comment = true; + } + if ($this->config !== null && + !empty($this->config->getOpenApi()->{CustomSpecAttr::DESC_IS_COMMENT})) { + $comment = true; + } + return $comment; + } } diff --git a/src/lib/migrations/MigrationRecordBuilder.php b/src/lib/migrations/MigrationRecordBuilder.php index 0648589f..700cbe4e 100644 --- a/src/lib/migrations/MigrationRecordBuilder.php +++ b/src/lib/migrations/MigrationRecordBuilder.php @@ -46,6 +46,10 @@ final class MigrationRecordBuilder public const ALTER_COLUMN_RAW_PGSQL = MigrationRecordBuilder::INDENT . "\$this->db->createCommand('ALTER TABLE %s ALTER COLUMN \"%s\" SET DATA TYPE %s')->execute();"; + public const ADD_COMMENT_ON_COLUMN = MigrationRecordBuilder::INDENT . "\$this->addCommentOnColumn('%s', '%s', %s);"; + + public const DROP_COMMENT_FROM_COLUMN = MigrationRecordBuilder::INDENT . "\$this->dropCommentFromColumn('%s', '%s');"; + /** * @var \yii\db\Schema */ @@ -373,4 +377,14 @@ public static function makeString(array $codeColumns): string $codeColumns = '['.PHP_EOL.self::INDENT.' '.$codeColumns.PHP_EOL . self::INDENT.']'; return $codeColumns; } + + public function addCommentOnColumn($table, string $column, string $comment): string + { + return sprintf(self::ADD_COMMENT_ON_COLUMN, $table, $column, var_export($comment, true)); + } + + public function dropCommentFromColumn($table, string $column): string + { + return sprintf(self::DROP_COMMENT_FROM_COLUMN, $table, $column); + } } diff --git a/src/lib/migrations/MysqlMigrationBuilder.php b/src/lib/migrations/MysqlMigrationBuilder.php index 2a3f9642..da3d967d 100644 --- a/src/lib/migrations/MysqlMigrationBuilder.php +++ b/src/lib/migrations/MysqlMigrationBuilder.php @@ -59,10 +59,14 @@ protected function compareColumns(ColumnSchema $current, ColumnSchema $desired): $this->modifyDesiredInContextOfCurrent($current, $desiredFromDb); $this->modifyDesiredFromDbInContextOfDesired($desired, $desiredFromDb); - foreach (['type', 'size', 'allowNull', 'defaultValue', 'enumValues' - , 'dbType', 'phpType' - , 'precision', 'scale', 'unsigned' - ] as $attr) { + $properties = ['type', 'size', 'allowNull', 'defaultValue', 'enumValues' + , 'dbType', 'phpType' + , 'precision', 'scale', 'unsigned' + ]; + if ($this->shouldCompareComment($desired)) { + $properties[] = 'comment'; + } + foreach ($properties as $attr) { if ($attr === 'defaultValue') { if ($this->isDefaultValueChanged($current, $desiredFromDb)) { $changedAttributes[] = $attr; @@ -306,4 +310,10 @@ public function setColumnsPositions() } } } + + public function handleCommentsMigration() + { + // nothing to do here as comments can be defined in same statement as of alter/add column in MySQL + // this method is only for PgSQL + } } diff --git a/src/lib/migrations/PostgresMigrationBuilder.php b/src/lib/migrations/PostgresMigrationBuilder.php index 8281ca3e..4f2379cf 100644 --- a/src/lib/migrations/PostgresMigrationBuilder.php +++ b/src/lib/migrations/PostgresMigrationBuilder.php @@ -66,7 +66,7 @@ protected function buildColumnChanges(ColumnSchema $current, ColumnSchema $desir $forUp = $forDown = false; if (!empty(array_intersect(['type', 'size' , 'dbType', 'phpType' - , 'precision', 'scale', 'unsigned' + , 'precision', 'scale', 'unsigned' ], $changed))) { $addUsing = $this->isNeedUsingExpression($current->dbType, $desired->dbType); $this->migration->addUpCode($this->recordBuilder->alterColumnType($tableName, $desired, $addUsing)); @@ -99,6 +99,17 @@ protected function buildColumnChanges(ColumnSchema $current, ColumnSchema $desir $this->migration->addUpCode($upCode)->addDownCode($downCode, true); } } + + if (in_array('comment', $changed, true)) { + if ($desired->comment) { + $this->migration->addUpCode($this->recordBuilder->addCommentOnColumn($tableName, $desired->name, $desired->comment)); + $this->migration->addDownCode($this->recordBuilder->dropCommentFromColumn($tableName, $desired->name)); + } else { + $this->migration->addUpCode($this->recordBuilder->dropCommentFromColumn($tableName, $desired->name)); + $this->migration->addDownCode($this->recordBuilder->addCommentOnColumn($tableName, $desired->name, $current->comment)); + } + } + if ($isChangeToEnum) { $this->migration->addUpCode($this->recordBuilder->createEnum($tableName, $desired->name, $desired->enumValues), true); } @@ -130,10 +141,15 @@ protected function compareColumns(ColumnSchema $current, ColumnSchema $desired): $this->modifyDesiredInContextOfCurrent($current, $desiredFromDb); $this->modifyDesiredFromDbInContextOfDesired($desired, $desiredFromDb); - foreach (['type', 'size', 'allowNull', 'defaultValue', 'enumValues' + $properties = ['type', 'size', 'allowNull', 'defaultValue', 'enumValues' , 'dbType', 'phpType' - , 'precision', 'scale', 'unsigned' - ] as $attr) { + , 'precision', 'scale', 'unsigned' + ]; + if ($this->shouldCompareComment($desired)) { + $properties[] = 'comment'; + } + + foreach ($properties as $attr) { if ($attr === 'defaultValue') { if ($this->isDefaultValueChanged($current, $desiredFromDb)) { $changedAttributes[] = $attr; @@ -265,4 +281,15 @@ public function findPosition(ColumnSchema $column, bool $forDrop = false, bool $ public function setColumnsPositions() { } + + public function handleCommentsMigration() + { + $tableAlias = $this->model->getTableAlias(); + foreach ($this->newColumns as $column) { + if ($column->comment) { + $this->migration + ->addUpCode($this->recordBuilder->addCommentOnColumn($tableAlias, $column->name, $column->comment)); + } + } + } } diff --git a/tests/specs/blog/migrations/m200000_000002_create_table_blog_posts.php b/tests/specs/blog/migrations/m200000_000002_create_table_blog_posts.php index b0b8e371..c7cc90fb 100644 --- a/tests/specs/blog/migrations/m200000_000002_create_table_blog_posts.php +++ b/tests/specs/blog/migrations/m200000_000002_create_table_blog_posts.php @@ -11,10 +11,10 @@ public function up() 0 => 'uid varchar(128) NOT NULL', 'title' => $this->string(255)->notNull(), 'slug' => $this->string(200)->null()->defaultValue(null), - 'category_id' => $this->integer()->notNull(), + 'category_id' => $this->integer()->notNull()->comment('Category of posts'), 'active' => $this->boolean()->notNull()->defaultValue(false), 'created_at' => $this->date()->null()->defaultValue(null), - 'created_by_id' => $this->integer()->null()->defaultValue(null), + 'created_by_id' => $this->integer()->null()->defaultValue(null)->comment('The User'), ]); $this->addPrimaryKey('pk_blog_posts_uid', '{{%blog_posts}}', 'uid'); $this->createIndex('blog_posts_title_key', '{{%blog_posts}}', 'title', true); diff --git a/tests/specs/blog/migrations/m200000_000004_create_table_post_comments.php b/tests/specs/blog/migrations/m200000_000004_create_table_post_comments.php index c16766da..175a32b7 100644 --- a/tests/specs/blog/migrations/m200000_000004_create_table_post_comments.php +++ b/tests/specs/blog/migrations/m200000_000004_create_table_post_comments.php @@ -9,8 +9,8 @@ public function up() { $this->createTable('{{%post_comments}}', [ 'id' => $this->bigPrimaryKey(), - 'post_id' => $this->string(128)->notNull(), - 'author_id' => $this->integer()->notNull(), + 'post_id' => $this->string(128)->notNull()->comment('A blog post (uid used as pk for test purposes)'), + 'author_id' => $this->integer()->notNull()->comment('The User'), 0 => 'message json NOT NULL', 1 => 'meta_data json NOT NULL', 'created_at' => $this->integer()->notNull(), diff --git a/tests/specs/blog/migrations_maria_db/m200000_000002_create_table_blog_posts.php b/tests/specs/blog/migrations_maria_db/m200000_000002_create_table_blog_posts.php index b0b8e371..c7cc90fb 100644 --- a/tests/specs/blog/migrations_maria_db/m200000_000002_create_table_blog_posts.php +++ b/tests/specs/blog/migrations_maria_db/m200000_000002_create_table_blog_posts.php @@ -11,10 +11,10 @@ public function up() 0 => 'uid varchar(128) NOT NULL', 'title' => $this->string(255)->notNull(), 'slug' => $this->string(200)->null()->defaultValue(null), - 'category_id' => $this->integer()->notNull(), + 'category_id' => $this->integer()->notNull()->comment('Category of posts'), 'active' => $this->boolean()->notNull()->defaultValue(false), 'created_at' => $this->date()->null()->defaultValue(null), - 'created_by_id' => $this->integer()->null()->defaultValue(null), + 'created_by_id' => $this->integer()->null()->defaultValue(null)->comment('The User'), ]); $this->addPrimaryKey('pk_blog_posts_uid', '{{%blog_posts}}', 'uid'); $this->createIndex('blog_posts_title_key', '{{%blog_posts}}', 'title', true); diff --git a/tests/specs/blog/migrations_maria_db/m200000_000004_create_table_post_comments.php b/tests/specs/blog/migrations_maria_db/m200000_000004_create_table_post_comments.php index d4971f43..5883fa5b 100644 --- a/tests/specs/blog/migrations_maria_db/m200000_000004_create_table_post_comments.php +++ b/tests/specs/blog/migrations_maria_db/m200000_000004_create_table_post_comments.php @@ -9,8 +9,8 @@ public function up() { $this->createTable('{{%post_comments}}', [ 'id' => $this->bigPrimaryKey(), - 'post_id' => $this->string(128)->notNull(), - 'author_id' => $this->integer()->notNull(), + 'post_id' => $this->string(128)->notNull()->comment('A blog post (uid used as pk for test purposes)'), + 'author_id' => $this->integer()->notNull()->comment('The User'), 0 => 'message json NOT NULL DEFAULT \'[]\'', 1 => 'meta_data json NOT NULL DEFAULT \'[]\'', 'created_at' => $this->integer()->notNull(), diff --git a/tests/specs/blog/migrations_mysql_db/m200000_000002_create_table_blog_posts.php b/tests/specs/blog/migrations_mysql_db/m200000_000002_create_table_blog_posts.php index b0b8e371..c7cc90fb 100644 --- a/tests/specs/blog/migrations_mysql_db/m200000_000002_create_table_blog_posts.php +++ b/tests/specs/blog/migrations_mysql_db/m200000_000002_create_table_blog_posts.php @@ -11,10 +11,10 @@ public function up() 0 => 'uid varchar(128) NOT NULL', 'title' => $this->string(255)->notNull(), 'slug' => $this->string(200)->null()->defaultValue(null), - 'category_id' => $this->integer()->notNull(), + 'category_id' => $this->integer()->notNull()->comment('Category of posts'), 'active' => $this->boolean()->notNull()->defaultValue(false), 'created_at' => $this->date()->null()->defaultValue(null), - 'created_by_id' => $this->integer()->null()->defaultValue(null), + 'created_by_id' => $this->integer()->null()->defaultValue(null)->comment('The User'), ]); $this->addPrimaryKey('pk_blog_posts_uid', '{{%blog_posts}}', 'uid'); $this->createIndex('blog_posts_title_key', '{{%blog_posts}}', 'title', true); diff --git a/tests/specs/blog/migrations_mysql_db/m200000_000004_create_table_post_comments.php b/tests/specs/blog/migrations_mysql_db/m200000_000004_create_table_post_comments.php index c16766da..175a32b7 100644 --- a/tests/specs/blog/migrations_mysql_db/m200000_000004_create_table_post_comments.php +++ b/tests/specs/blog/migrations_mysql_db/m200000_000004_create_table_post_comments.php @@ -9,8 +9,8 @@ public function up() { $this->createTable('{{%post_comments}}', [ 'id' => $this->bigPrimaryKey(), - 'post_id' => $this->string(128)->notNull(), - 'author_id' => $this->integer()->notNull(), + 'post_id' => $this->string(128)->notNull()->comment('A blog post (uid used as pk for test purposes)'), + 'author_id' => $this->integer()->notNull()->comment('The User'), 0 => 'message json NOT NULL', 1 => 'meta_data json NOT NULL', 'created_at' => $this->integer()->notNull(), diff --git a/tests/specs/blog/migrations_pgsql_db/m200000_000002_create_table_blog_posts.php b/tests/specs/blog/migrations_pgsql_db/m200000_000002_create_table_blog_posts.php index 8639040d..9dbe55cf 100644 --- a/tests/specs/blog/migrations_pgsql_db/m200000_000002_create_table_blog_posts.php +++ b/tests/specs/blog/migrations_pgsql_db/m200000_000002_create_table_blog_posts.php @@ -11,16 +11,18 @@ public function safeUp() 0 => '"uid" varchar(128) NOT NULL', 'title' => $this->string(255)->notNull(), 'slug' => $this->string(200)->null()->defaultValue(null), - 'category_id' => $this->integer()->notNull(), + 'category_id' => $this->integer()->notNull()->comment('Category of posts'), 'active' => $this->boolean()->notNull()->defaultValue(false), 'created_at' => $this->date()->null()->defaultValue(null), - 'created_by_id' => $this->integer()->null()->defaultValue(null), + 'created_by_id' => $this->integer()->null()->defaultValue(null)->comment('The User'), ]); $this->addPrimaryKey('pk_blog_posts_uid', '{{%blog_posts}}', 'uid'); $this->createIndex('blog_posts_title_key', '{{%blog_posts}}', 'title', true); $this->createIndex('blog_posts_slug_key', '{{%blog_posts}}', 'slug', true); $this->addForeignKey('fk_blog_posts_category_id_categories_id', '{{%blog_posts}}', 'category_id', '{{%categories}}', 'id'); $this->addForeignKey('fk_blog_posts_created_by_id_users_id', '{{%blog_posts}}', 'created_by_id', '{{%users}}', 'id'); + $this->addCommentOnColumn('{{%blog_posts}}', 'category_id', 'Category of posts'); + $this->addCommentOnColumn('{{%blog_posts}}', 'created_by_id', 'The User'); } public function safeDown() diff --git a/tests/specs/blog/migrations_pgsql_db/m200000_000004_create_table_post_comments.php b/tests/specs/blog/migrations_pgsql_db/m200000_000004_create_table_post_comments.php index 2aa48549..2d924e52 100644 --- a/tests/specs/blog/migrations_pgsql_db/m200000_000004_create_table_post_comments.php +++ b/tests/specs/blog/migrations_pgsql_db/m200000_000004_create_table_post_comments.php @@ -9,14 +9,16 @@ public function safeUp() { $this->createTable('{{%post_comments}}', [ 'id' => $this->bigPrimaryKey(), - 'post_id' => $this->string(128)->notNull(), - 'author_id' => $this->integer()->notNull(), + 'post_id' => $this->string(128)->notNull()->comment('A blog post (uid used as pk for test purposes)'), + 'author_id' => $this->integer()->notNull()->comment('The User'), 0 => '"message" json NOT NULL DEFAULT \'[]\'', 1 => '"meta_data" json NOT NULL DEFAULT \'[]\'', 'created_at' => $this->integer()->notNull(), ]); $this->addForeignKey('fk_post_comments_post_id_blog_posts_uid', '{{%post_comments}}', 'post_id', '{{%blog_posts}}', 'uid'); $this->addForeignKey('fk_post_comments_author_id_users_id', '{{%post_comments}}', 'author_id', '{{%users}}', 'id'); + $this->addCommentOnColumn('{{%post_comments}}', 'post_id', 'A blog post (uid used as pk for test purposes)'); + $this->addCommentOnColumn('{{%post_comments}}', 'author_id', 'The User'); } public function safeDown() diff --git a/tests/specs/blog_v2/migrations_maria_db/m200000_000005_change_table_v2_comments.php b/tests/specs/blog_v2/migrations_maria_db/m200000_000005_change_table_v2_comments.php index 8b655559..b34a7810 100644 --- a/tests/specs/blog_v2/migrations_maria_db/m200000_000005_change_table_v2_comments.php +++ b/tests/specs/blog_v2/migrations_maria_db/m200000_000005_change_table_v2_comments.php @@ -9,7 +9,7 @@ public function up() { $this->dropForeignKey('fk_v2_comments_post_id_v2_posts_uid', '{{%v2_comments}}'); $this->dropForeignKey('fk_v2_comments_author_id_v2_users_id', '{{%v2_comments}}'); - $this->addColumn('{{%v2_comments}}', 'user_id', $this->bigInteger()->null()->defaultValue(null)->after('post_id')); + $this->addColumn('{{%v2_comments}}', 'user_id', $this->bigInteger()->null()->defaultValue(null)->after('post_id')->comment('The User')); $this->dropColumn('{{%v2_comments}}', 'author_id'); $this->alterColumn('{{%v2_comments}}', 'message', $this->text()->notNull()); $this->alterColumn('{{%v2_comments}}', 'meta_data', $this->string(300)->null()->defaultValue('')); diff --git a/tests/specs/blog_v2/migrations_mysql_db/m200000_000005_change_table_v2_comments.php b/tests/specs/blog_v2/migrations_mysql_db/m200000_000005_change_table_v2_comments.php index 0051469e..8ac91b71 100644 --- a/tests/specs/blog_v2/migrations_mysql_db/m200000_000005_change_table_v2_comments.php +++ b/tests/specs/blog_v2/migrations_mysql_db/m200000_000005_change_table_v2_comments.php @@ -9,7 +9,7 @@ public function up() { $this->dropForeignKey('fk_v2_comments_post_id_v2_posts_uid', '{{%v2_comments}}'); $this->dropForeignKey('fk_v2_comments_author_id_v2_users_id', '{{%v2_comments}}'); - $this->addColumn('{{%v2_comments}}', 'user_id', $this->bigInteger()->null()->defaultValue(null)->after('post_id')); + $this->addColumn('{{%v2_comments}}', 'user_id', $this->bigInteger()->null()->defaultValue(null)->after('post_id')->comment('The User')); $this->dropColumn('{{%v2_comments}}', 'author_id'); $this->alterColumn('{{%v2_comments}}', 'message', $this->text()->notNull()); $this->alterColumn('{{%v2_comments}}', 'meta_data', $this->string(300)->null()->defaultValue('')); diff --git a/tests/specs/blog_v2/migrations_pgsql_db/m200000_000005_change_table_v2_comments.php b/tests/specs/blog_v2/migrations_pgsql_db/m200000_000005_change_table_v2_comments.php index efbb21be..e9ad9ff5 100644 --- a/tests/specs/blog_v2/migrations_pgsql_db/m200000_000005_change_table_v2_comments.php +++ b/tests/specs/blog_v2/migrations_pgsql_db/m200000_000005_change_table_v2_comments.php @@ -9,7 +9,7 @@ public function safeUp() { $this->dropForeignKey('fk_v2_comments_author_id_v2_users_id', '{{%v2_comments}}'); $this->dropForeignKey('fk_v2_comments_post_id_v2_posts_uid', '{{%v2_comments}}'); - $this->addColumn('{{%v2_comments}}', 'user_id', $this->bigInteger()->null()->defaultValue(null)); + $this->addColumn('{{%v2_comments}}', 'user_id', $this->bigInteger()->null()->defaultValue(null)->comment('The User')); $this->dropColumn('{{%v2_comments}}', 'author_id'); $this->alterColumn('{{%v2_comments}}', 'message', 'text NOT NULL USING "message"::text'); $this->alterColumn('{{%v2_comments}}', 'message', "DROP DEFAULT"); diff --git a/tests/specs/fk_col_name/app/migrations_mysql_db/m200000_000002_create_table_webhooks.php b/tests/specs/fk_col_name/app/migrations_mysql_db/m200000_000002_create_table_webhooks.php index bb6aa050..5d3abaf3 100644 --- a/tests/specs/fk_col_name/app/migrations_mysql_db/m200000_000002_create_table_webhooks.php +++ b/tests/specs/fk_col_name/app/migrations_mysql_db/m200000_000002_create_table_webhooks.php @@ -10,7 +10,7 @@ public function up() $this->createTable('{{%webhooks}}', [ 'id' => $this->primaryKey(), 'name' => $this->text()->null(), - 'user_id' => $this->integer()->null()->defaultValue(null), + 'user_id' => $this->integer()->null()->defaultValue(null)->comment('Test model for model code generation that should not contain id column in rules'), 'redelivery_of' => $this->integer()->null()->defaultValue(null), ]); $this->addForeignKey('fk_webhooks_user_id_users_id', '{{%webhooks}}', 'user_id', '{{%users}}', 'id'); diff --git a/tests/specs/fk_col_name_index/app/migrations_mysql_db/m200000_000002_create_table_webhooks.php b/tests/specs/fk_col_name_index/app/migrations_mysql_db/m200000_000002_create_table_webhooks.php index 783d58b0..591905a0 100644 --- a/tests/specs/fk_col_name_index/app/migrations_mysql_db/m200000_000002_create_table_webhooks.php +++ b/tests/specs/fk_col_name_index/app/migrations_mysql_db/m200000_000002_create_table_webhooks.php @@ -10,7 +10,7 @@ public function up() $this->createTable('{{%webhooks}}', [ 'id' => $this->primaryKey(), 'name' => $this->string(255)->null()->defaultValue(null), - 'user_id' => $this->integer()->null()->defaultValue(null), + 'user_id' => $this->integer()->null()->defaultValue(null)->comment('Test model for model code generation that should not contain id column in rules'), 'redelivery_of' => $this->integer()->null()->defaultValue(null), 'rd_abc_2' => $this->integer()->null()->defaultValue(null), ]); diff --git a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/migrations_pgsql_db/m200000_000000_create_table_accounts.php b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/migrations_pgsql_db/m200000_000000_create_table_accounts.php index 1606f2fc..ce7db4f9 100644 --- a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/migrations_pgsql_db/m200000_000000_create_table_accounts.php +++ b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/migrations_pgsql_db/m200000_000000_create_table_accounts.php @@ -9,7 +9,7 @@ public function up() { $this->createTable('{{%accounts}}', [ 'id' => $this->primaryKey(), - 'name' => $this->string(128)->notNull(), + 'name' => $this->string(128)->notNull()->comment('account name'), 'paymentMethodName' => $this->text()->null(), ]); } diff --git a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/migrations_pgsql_db/m200000_000001_create_table_contacts.php b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/migrations_pgsql_db/m200000_000001_create_table_contacts.php index 5fcda9dc..a706a626 100644 --- a/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/migrations_pgsql_db/m200000_000001_create_table_contacts.php +++ b/tests/specs/issue_fix/175_bug_allof_with_multiple_dollarrefs/pgsql/migrations_pgsql_db/m200000_000001_create_table_contacts.php @@ -9,7 +9,7 @@ public function up() { $this->createTable('{{%contacts}}', [ 'id' => $this->primaryKey(), - 'account_id' => $this->integer()->notNull(), + 'account_id' => $this->integer()->notNull()->comment('Account'), 'active' => $this->boolean()->null()->defaultValue(false), 'nickname' => $this->text()->null(), ]); diff --git a/tests/specs/issue_fix/25_generate_inverse_relations/mysql/migrations_mysql_db/m200000_000001_create_table_accounts.php b/tests/specs/issue_fix/25_generate_inverse_relations/mysql/migrations_mysql_db/m200000_000001_create_table_accounts.php index f2bc7b90..1bc93a24 100644 --- a/tests/specs/issue_fix/25_generate_inverse_relations/mysql/migrations_mysql_db/m200000_000001_create_table_accounts.php +++ b/tests/specs/issue_fix/25_generate_inverse_relations/mysql/migrations_mysql_db/m200000_000001_create_table_accounts.php @@ -9,7 +9,7 @@ public function up() { $this->createTable('{{%accounts}}', [ 'id' => $this->primaryKey(), - 'name' => $this->string(128)->notNull(), + 'name' => $this->string(128)->notNull()->comment('account name'), 'paymentMethodName' => $this->text()->null(), 'user_id' => $this->integer()->null()->defaultValue(null), 'user2_id' => $this->integer()->null()->defaultValue(null), diff --git a/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/index.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/index.php new file mode 100644 index 00000000..5642a696 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/index.php @@ -0,0 +1,13 @@ + '@specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/index.yml', + '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/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/index.yml b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/index.yml new file mode 100644 index 00000000..bafe0cf8 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/index.yml @@ -0,0 +1,49 @@ +openapi: 3.0.3 +x-description-is-comment: true +info: + title: 'Description of a property in spec must correspond to DB TABLE COLUMN COMMENT #60' + version: 1.0.0 + +components: + schemas: + Fruit: + type: object + properties: + id: + type: integer + name: + type: string + description: desc with ' quote + description: + type: number + x-db-type: double precision + description: desc ' 2 + Animal: + type: object + properties: + id: + type: integer + name: + type: integer + g: + type: string + description: desc for g + g2: + type: string + description: changed comment on g2 col + g3: + type: string + description: the comment on g3 col remains same + g4: + type: integer + description: data type changes but comment remains same + new_col: + type: string + description: new col added + +paths: + '/': + get: + responses: + '200': + description: OK diff --git a/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/migrations_mysql_db/m200000_000000_change_table_animals.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/migrations_mysql_db/m200000_000000_change_table_animals.php new file mode 100644 index 00000000..bff6c78d --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/migrations_mysql_db/m200000_000000_change_table_animals.php @@ -0,0 +1,27 @@ +addColumn('{{%animals}}', 'new_col', $this->text()->null()->comment('new col added')); + $this->dropColumn('{{%animals}}', 'drop_col'); + $this->alterColumn('{{%animals}}', 'name', $this->integer()->null()->defaultValue(null)); + $this->alterColumn('{{%animals}}', 'g', $this->text()->null()->comment('desc for g')); + $this->alterColumn('{{%animals}}', 'g2', $this->text()->null()->comment('changed comment on g2 col')); + $this->alterColumn('{{%animals}}', 'g4', $this->integer()->null()->defaultValue(null)->comment('data type changes but comment remains same')); + } + + public function down() + { + $this->alterColumn('{{%animals}}', 'g4', $this->text()->null()->comment('data type changes but comment remains same')); + $this->alterColumn('{{%animals}}', 'g2', $this->text()->null()->comment('the comment on g2 col')); + $this->alterColumn('{{%animals}}', 'g', $this->text()->null()); + $this->alterColumn('{{%animals}}', 'name', $this->text()->null()->comment('the comment on name col')); + $this->addColumn('{{%animals}}', 'drop_col', $this->text()->null()); + $this->dropColumn('{{%animals}}', 'new_col'); + } +} diff --git a/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/migrations_mysql_db/m200000_000001_create_table_fruits.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/migrations_mysql_db/m200000_000001_create_table_fruits.php new file mode 100644 index 00000000..c4271f02 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/migrations_mysql_db/m200000_000001_create_table_fruits.php @@ -0,0 +1,21 @@ +createTable('{{%fruits}}', [ + 'id' => $this->primaryKey(), + 'name' => $this->text()->null()->comment('desc with \' quote'), + 0 => 'description double precision NULL DEFAULT NULL COMMENT \'desc \\\' 2\'', + ]); + } + + public function down() + { + $this->dropTable('{{%fruits}}'); + } +} diff --git a/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/Animal.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/Animal.php new file mode 100644 index 00000000..92caf2f3 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/Animal.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 Animal(); + //$model->id = $uniqueFaker->numberBetween(0, 1000000); + $model->name = $faker->numberBetween(0, 1000000); + $model->g = $faker->sentence; + $model->g2 = $faker->sentence; + $model->g3 = $faker->sentence; + $model->g4 = $faker->numberBetween(0, 1000000); + $model->new_col = $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/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/BaseModelFaker.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/BaseModelFaker.php new file mode 100644 index 00000000..c367fbb4 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/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/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/Fruit.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/Fruit.php new file mode 100644 index 00000000..c74c53d9 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/Fruit.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 Fruit(); + //$model->id = $uniqueFaker->numberBetween(0, 1000000); + $model->name = $faker->sentence; + $model->description = $faker->randomFloat(); + if (!is_callable($attributes)) { + $model->setAttributes($attributes, false); + } else { + $model = $attributes($model, $faker, $uniqueFaker); + } + return $model; + } +} diff --git a/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/base/Animal.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/base/Animal.php new file mode 100644 index 00000000..5fd077a3 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/base/Animal.php @@ -0,0 +1,40 @@ + [['g', 'g2', 'g3', 'new_col'], 'trim'], + 'name_integer' => [['name'], 'integer'], + 'g_string' => [['g'], 'string'], + 'g2_string' => [['g2'], 'string'], + 'g3_string' => [['g3'], 'string'], + 'g4_integer' => [['g4'], 'integer'], + 'new_col_string' => [['new_col'], 'string'], + ]; + } +} diff --git a/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/base/Fruit.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/base/Fruit.php new file mode 100644 index 00000000..177133f5 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql/models/base/Fruit.php @@ -0,0 +1,32 @@ + [['name'], 'trim'], + 'name_string' => [['name'], 'string'], + 'description_double' => [['description'], 'double'], + ]; + } +} diff --git a/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/migrations_pgsql_db/m200000_000000_change_table_animals.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/migrations_pgsql_db/m200000_000000_change_table_animals.php new file mode 100644 index 00000000..ede74a69 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/migrations_pgsql_db/m200000_000000_change_table_animals.php @@ -0,0 +1,29 @@ +addColumn('{{%animals}}', 'new_col', $this->text()->null()->defaultValue(null)->comment('new col added')); + $this->dropColumn('{{%animals}}', 'drop_col'); + $this->alterColumn('{{%animals}}', 'name', 'int4 NULL USING "name"::int4'); + $this->dropCommentFromColumn('{{%animals}}', 'name'); + $this->addCommentOnColumn('{{%animals}}', 'g', 'desc for g'); + $this->addCommentOnColumn('{{%animals}}', 'g2', 'changed comment on g2 col'); + $this->alterColumn('{{%animals}}', 'g4', 'int4 NULL USING "g4"::int4'); + } + + public function safeDown() + { + $this->alterColumn('{{%animals}}', 'g4', 'text NULL USING "g4"::text'); + $this->dropCommentFromColumn('{{%animals}}', 'g2'); + $this->dropCommentFromColumn('{{%animals}}', 'g'); + $this->addCommentOnColumn('{{%animals}}', 'name', 'the comment on name col'); + $this->alterColumn('{{%animals}}', 'name', 'text NULL USING "name"::text'); + $this->addColumn('{{%animals}}', 'drop_col', $this->text()->null()->defaultValue(null)); + $this->dropColumn('{{%animals}}', 'new_col'); + } +} diff --git a/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/migrations_pgsql_db/m200000_000001_create_table_fruits.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/migrations_pgsql_db/m200000_000001_create_table_fruits.php new file mode 100644 index 00000000..21467feb --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/migrations_pgsql_db/m200000_000001_create_table_fruits.php @@ -0,0 +1,23 @@ +createTable('{{%fruits}}', [ + 'id' => $this->primaryKey(), + 'name' => $this->text()->null()->defaultValue(null)->comment('desc with \' quote'), + 0 => '"description" double precision NULL DEFAULT NULL', + ]); + $this->addCommentOnColumn('{{%fruits}}', 'name', 'desc with \' quote'); + $this->addCommentOnColumn('{{%fruits}}', 'description', 'desc \' 2'); + } + + public function safeDown() + { + $this->dropTable('{{%fruits}}'); + } +} diff --git a/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/Animal.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/Animal.php new file mode 100644 index 00000000..92caf2f3 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/Animal.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 Animal(); + //$model->id = $uniqueFaker->numberBetween(0, 1000000); + $model->name = $faker->numberBetween(0, 1000000); + $model->g = $faker->sentence; + $model->g2 = $faker->sentence; + $model->g3 = $faker->sentence; + $model->g4 = $faker->numberBetween(0, 1000000); + $model->new_col = $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/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/BaseModelFaker.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/BaseModelFaker.php new file mode 100644 index 00000000..c367fbb4 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/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/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/Fruit.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/Fruit.php new file mode 100644 index 00000000..c74c53d9 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/Fruit.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 Fruit(); + //$model->id = $uniqueFaker->numberBetween(0, 1000000); + $model->name = $faker->sentence; + $model->description = $faker->randomFloat(); + if (!is_callable($attributes)) { + $model->setAttributes($attributes, false); + } else { + $model = $attributes($model, $faker, $uniqueFaker); + } + return $model; + } +} diff --git a/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/base/Animal.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/base/Animal.php new file mode 100644 index 00000000..5fd077a3 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/base/Animal.php @@ -0,0 +1,40 @@ + [['g', 'g2', 'g3', 'new_col'], 'trim'], + 'name_integer' => [['name'], 'integer'], + 'g_string' => [['g'], 'string'], + 'g2_string' => [['g2'], 'string'], + 'g3_string' => [['g3'], 'string'], + 'g4_integer' => [['g4'], 'integer'], + 'new_col_string' => [['new_col'], 'string'], + ]; + } +} diff --git a/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/base/Fruit.php b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/base/Fruit.php new file mode 100644 index 00000000..177133f5 --- /dev/null +++ b/tests/specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql/models/base/Fruit.php @@ -0,0 +1,32 @@ + [['name'], 'trim'], + 'name_string' => [['name'], 'string'], + 'description_double' => [['description'], 'double'], + ]; + } +} diff --git a/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000001_create_table_b123s.php b/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000001_create_table_b123s.php index 908bd998..688d4e58 100644 --- a/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000001_create_table_b123s.php +++ b/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000001_create_table_b123s.php @@ -10,9 +10,10 @@ public function safeUp() $this->createTable('{{%b123s}}', [ 'id' => $this->primaryKey(), 'name' => $this->text()->null()->defaultValue(null), - 'c123_id' => $this->integer()->null()->defaultValue(null), + 'c123_id' => $this->integer()->null()->defaultValue(null)->comment('desc'), ]); $this->addForeignKey('fk_b123s_c123_id_c123s_id', '{{%b123s}}', 'c123_id', '{{%c123s}}', 'id'); + $this->addCommentOnColumn('{{%b123s}}', 'c123_id', 'desc'); } public function safeDown() diff --git a/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000002_create_table_a123s.php b/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000002_create_table_a123s.php index 73c70ae2..f93343c6 100644 --- a/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000002_create_table_a123s.php +++ b/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000002_create_table_a123s.php @@ -10,9 +10,10 @@ public function safeUp() $this->createTable('{{%a123s}}', [ 'id' => $this->primaryKey(), 'name' => $this->text()->null()->defaultValue(null), - 'b123_id' => $this->integer()->null()->defaultValue(null), + 'b123_id' => $this->integer()->null()->defaultValue(null)->comment('desc'), ]); $this->addForeignKey('fk_a123s_b123_id_b123s_id', '{{%a123s}}', 'b123_id', '{{%b123s}}', 'id'); + $this->addCommentOnColumn('{{%a123s}}', 'b123_id', 'desc'); } public function safeDown() diff --git a/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000003_create_table_accounts.php b/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000003_create_table_accounts.php index 8eba95b2..271f8a7b 100644 --- a/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000003_create_table_accounts.php +++ b/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000003_create_table_accounts.php @@ -9,8 +9,9 @@ public function safeUp() { $this->createTable('{{%accounts}}', [ 'id' => $this->primaryKey(), - 'name' => $this->string(40)->notNull(), + 'name' => $this->string(40)->notNull()->comment('account name'), ]); + $this->addCommentOnColumn('{{%accounts}}', 'name', 'account name'); } public function safeDown() diff --git a/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000005_create_table_domains.php b/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000005_create_table_domains.php index c830fe7e..c5a0e7f2 100644 --- a/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000005_create_table_domains.php +++ b/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000005_create_table_domains.php @@ -9,11 +9,13 @@ public function safeUp() { $this->createTable('{{%domains}}', [ 'id' => $this->primaryKey(), - 'name' => $this->string(128)->notNull(), - 'account_id' => $this->integer()->notNull(), + 'name' => $this->string(128)->notNull()->comment('domain or sub-domain name, in DNS syntax, IDN are converted'), + 'account_id' => $this->integer()->notNull()->comment('user account'), 0 => '"created_at" timestamp NOT NULL', ]); $this->addForeignKey('fk_domains_account_id_accounts_id', '{{%domains}}', 'account_id', '{{%accounts}}', 'id'); + $this->addCommentOnColumn('{{%domains}}', 'name', 'domain or sub-domain name, in DNS syntax, IDN are converted'); + $this->addCommentOnColumn('{{%domains}}', 'account_id', 'user account'); } public function safeDown() diff --git a/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000006_create_table_e123s.php b/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000006_create_table_e123s.php index f8d58a41..55cb62af 100644 --- a/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000006_create_table_e123s.php +++ b/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000006_create_table_e123s.php @@ -10,9 +10,10 @@ public function safeUp() $this->createTable('{{%e123s}}', [ 'id' => $this->primaryKey(), 'name' => $this->text()->null()->defaultValue(null), - 'b123_id' => $this->integer()->null()->defaultValue(null), + 'b123_id' => $this->integer()->null()->defaultValue(null)->comment('desc'), ]); $this->addForeignKey('fk_e123s_b123_id_b123s_id', '{{%e123s}}', 'b123_id', '{{%b123s}}', 'id'); + $this->addCommentOnColumn('{{%e123s}}', 'b123_id', 'desc'); } public function safeDown() diff --git a/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000007_create_table_routings.php b/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000007_create_table_routings.php index 98ac2ad9..bd09ae48 100644 --- a/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000007_create_table_routings.php +++ b/tests/specs/relations_in_faker/app/migrations_pgsql_db/m200000_000007_create_table_routings.php @@ -9,18 +9,21 @@ public function safeUp() { $this->createTable('{{%routings}}', [ 'id' => $this->primaryKey(), - 'domain_id' => $this->integer()->notNull(), + 'domain_id' => $this->integer()->notNull()->comment('domain'), 'path' => $this->string(255)->null()->defaultValue(null), 'ssl' => $this->boolean()->null()->defaultValue(null), 'redirect_to_ssl' => $this->boolean()->null()->defaultValue(null), 'service' => $this->string(255)->null()->defaultValue(null), 0 => '"created_at" timestamp NULL DEFAULT NULL', - 'd123_id' => $this->integer()->null()->defaultValue(null), - 'a123_id' => $this->integer()->null()->defaultValue(null), + 'd123_id' => $this->integer()->null()->defaultValue(null)->comment('desc'), + 'a123_id' => $this->integer()->null()->defaultValue(null)->comment('desc'), ]); $this->addForeignKey('fk_routings_domain_id_domains_id', '{{%routings}}', 'domain_id', '{{%domains}}', 'id'); $this->addForeignKey('fk_routings_d123_id_d123s_id', '{{%routings}}', 'd123_id', '{{%d123s}}', 'id'); $this->addForeignKey('fk_routings_a123_id_a123s_id', '{{%routings}}', 'a123_id', '{{%a123s}}', 'id'); + $this->addCommentOnColumn('{{%routings}}', 'domain_id', 'domain'); + $this->addCommentOnColumn('{{%routings}}', 'd123_id', 'desc'); + $this->addCommentOnColumn('{{%routings}}', 'a123_id', 'desc'); } public function safeDown() diff --git a/tests/specs/x_db_type/edit_column/maria/app/migrations_maria_db/m200000_000003_create_table_pristines.php b/tests/specs/x_db_type/edit_column/maria/app/migrations_maria_db/m200000_000003_create_table_pristines.php index 1e27d8d6..7c0b936f 100644 --- a/tests/specs/x_db_type/edit_column/maria/app/migrations_maria_db/m200000_000003_create_table_pristines.php +++ b/tests/specs/x_db_type/edit_column/maria/app/migrations_maria_db/m200000_000003_create_table_pristines.php @@ -19,7 +19,7 @@ public function up() 7 => 'col_9 varchar(9) NULL DEFAULT NULL', 8 => 'col_10 varchar(10) NULL DEFAULT NULL', 9 => 'col_11 text NULL DEFAULT NULL', - 10 => 'price decimal(10,2) NULL DEFAULT 0', + 10 => 'price decimal(10,2) NULL DEFAULT 0 COMMENT \'price in EUR\'', ]); } diff --git a/tests/specs/x_db_type/edit_column/mysql/app/migrations_mysql_db/m200000_000003_create_table_pristines.php b/tests/specs/x_db_type/edit_column/mysql/app/migrations_mysql_db/m200000_000003_create_table_pristines.php index 3e9e8e02..50881e9d 100644 --- a/tests/specs/x_db_type/edit_column/mysql/app/migrations_mysql_db/m200000_000003_create_table_pristines.php +++ b/tests/specs/x_db_type/edit_column/mysql/app/migrations_mysql_db/m200000_000003_create_table_pristines.php @@ -19,7 +19,7 @@ public function up() 7 => 'col_9 varchar(9) NULL DEFAULT NULL', 8 => 'col_10 varchar(10) NULL DEFAULT NULL', 9 => 'col_11 text NULL', - 10 => 'price decimal(10,2) NULL DEFAULT 0', + 10 => 'price decimal(10,2) NULL DEFAULT 0 COMMENT \'price in EUR\'', ]); } diff --git a/tests/specs/x_db_type/edit_column/pgsql/app/migrations_pgsql_db/m200000_000003_create_table_pristines.php b/tests/specs/x_db_type/edit_column/pgsql/app/migrations_pgsql_db/m200000_000003_create_table_pristines.php index aab6bb88..7fa8a01f 100644 --- a/tests/specs/x_db_type/edit_column/pgsql/app/migrations_pgsql_db/m200000_000003_create_table_pristines.php +++ b/tests/specs/x_db_type/edit_column/pgsql/app/migrations_pgsql_db/m200000_000003_create_table_pristines.php @@ -21,6 +21,7 @@ public function safeUp() 9 => '"col_11" text NULL DEFAULT NULL', 10 => '"price" decimal(10,2) NULL DEFAULT 0', ]); + $this->addCommentOnColumn('{{%pristines}}', 'price', 'price in EUR'); } public function safeDown() diff --git a/tests/specs/x_db_type/fresh/maria/app/migrations_maria_db/m200000_000003_create_table_pristines.php b/tests/specs/x_db_type/fresh/maria/app/migrations_maria_db/m200000_000003_create_table_pristines.php index 1e27d8d6..7c0b936f 100644 --- a/tests/specs/x_db_type/fresh/maria/app/migrations_maria_db/m200000_000003_create_table_pristines.php +++ b/tests/specs/x_db_type/fresh/maria/app/migrations_maria_db/m200000_000003_create_table_pristines.php @@ -19,7 +19,7 @@ public function up() 7 => 'col_9 varchar(9) NULL DEFAULT NULL', 8 => 'col_10 varchar(10) NULL DEFAULT NULL', 9 => 'col_11 text NULL DEFAULT NULL', - 10 => 'price decimal(10,2) NULL DEFAULT 0', + 10 => 'price decimal(10,2) NULL DEFAULT 0 COMMENT \'price in EUR\'', ]); } diff --git a/tests/specs/x_db_type/fresh/mysql/app/migrations_mysql_db/m200000_000003_create_table_pristines.php b/tests/specs/x_db_type/fresh/mysql/app/migrations_mysql_db/m200000_000003_create_table_pristines.php index 3e9e8e02..50881e9d 100644 --- a/tests/specs/x_db_type/fresh/mysql/app/migrations_mysql_db/m200000_000003_create_table_pristines.php +++ b/tests/specs/x_db_type/fresh/mysql/app/migrations_mysql_db/m200000_000003_create_table_pristines.php @@ -19,7 +19,7 @@ public function up() 7 => 'col_9 varchar(9) NULL DEFAULT NULL', 8 => 'col_10 varchar(10) NULL DEFAULT NULL', 9 => 'col_11 text NULL', - 10 => 'price decimal(10,2) NULL DEFAULT 0', + 10 => 'price decimal(10,2) NULL DEFAULT 0 COMMENT \'price in EUR\'', ]); } diff --git a/tests/specs/x_db_type/fresh/pgsql/app/migrations_pgsql_db/m200000_000003_create_table_pristines.php b/tests/specs/x_db_type/fresh/pgsql/app/migrations_pgsql_db/m200000_000003_create_table_pristines.php index aab6bb88..7fa8a01f 100644 --- a/tests/specs/x_db_type/fresh/pgsql/app/migrations_pgsql_db/m200000_000003_create_table_pristines.php +++ b/tests/specs/x_db_type/fresh/pgsql/app/migrations_pgsql_db/m200000_000003_create_table_pristines.php @@ -21,6 +21,7 @@ public function safeUp() 9 => '"col_11" text NULL DEFAULT NULL', 10 => '"price" decimal(10,2) NULL DEFAULT 0', ]); + $this->addCommentOnColumn('{{%pristines}}', 'price', 'price in EUR'); } public function safeDown() diff --git a/tests/specs/x_db_type/new_column/maria/app/migrations_maria_db/m200000_000003_create_table_pristines.php b/tests/specs/x_db_type/new_column/maria/app/migrations_maria_db/m200000_000003_create_table_pristines.php index 1e27d8d6..7c0b936f 100644 --- a/tests/specs/x_db_type/new_column/maria/app/migrations_maria_db/m200000_000003_create_table_pristines.php +++ b/tests/specs/x_db_type/new_column/maria/app/migrations_maria_db/m200000_000003_create_table_pristines.php @@ -19,7 +19,7 @@ public function up() 7 => 'col_9 varchar(9) NULL DEFAULT NULL', 8 => 'col_10 varchar(10) NULL DEFAULT NULL', 9 => 'col_11 text NULL DEFAULT NULL', - 10 => 'price decimal(10,2) NULL DEFAULT 0', + 10 => 'price decimal(10,2) NULL DEFAULT 0 COMMENT \'price in EUR\'', ]); } diff --git a/tests/specs/x_db_type/new_column/mysql/app/migrations_mysql_db/m200000_000003_create_table_pristines.php b/tests/specs/x_db_type/new_column/mysql/app/migrations_mysql_db/m200000_000003_create_table_pristines.php index 3e9e8e02..50881e9d 100644 --- a/tests/specs/x_db_type/new_column/mysql/app/migrations_mysql_db/m200000_000003_create_table_pristines.php +++ b/tests/specs/x_db_type/new_column/mysql/app/migrations_mysql_db/m200000_000003_create_table_pristines.php @@ -19,7 +19,7 @@ public function up() 7 => 'col_9 varchar(9) NULL DEFAULT NULL', 8 => 'col_10 varchar(10) NULL DEFAULT NULL', 9 => 'col_11 text NULL', - 10 => 'price decimal(10,2) NULL DEFAULT 0', + 10 => 'price decimal(10,2) NULL DEFAULT 0 COMMENT \'price in EUR\'', ]); } diff --git a/tests/specs/x_db_type/new_column/pgsql/app/migrations_pgsql_db/m200000_000003_create_table_pristines.php b/tests/specs/x_db_type/new_column/pgsql/app/migrations_pgsql_db/m200000_000003_create_table_pristines.php index aab6bb88..7fa8a01f 100644 --- a/tests/specs/x_db_type/new_column/pgsql/app/migrations_pgsql_db/m200000_000003_create_table_pristines.php +++ b/tests/specs/x_db_type/new_column/pgsql/app/migrations_pgsql_db/m200000_000003_create_table_pristines.php @@ -21,6 +21,7 @@ public function safeUp() 9 => '"col_11" text NULL DEFAULT NULL', 10 => '"price" decimal(10,2) NULL DEFAULT 0', ]); + $this->addCommentOnColumn('{{%pristines}}', 'price', 'price in EUR'); } public function safeDown() diff --git a/tests/specs/x_on_x_fk_constraint/app/migrations_pgsql_db/m200000_000001_create_table_postxes.php b/tests/specs/x_on_x_fk_constraint/app/migrations_pgsql_db/m200000_000001_create_table_postxes.php index f0e8adc8..5593db95 100644 --- a/tests/specs/x_on_x_fk_constraint/app/migrations_pgsql_db/m200000_000001_create_table_postxes.php +++ b/tests/specs/x_on_x_fk_constraint/app/migrations_pgsql_db/m200000_000001_create_table_postxes.php @@ -10,15 +10,19 @@ public function safeUp() $this->createTable('{{%postxes}}', [ 'id' => $this->primaryKey(), 'title' => $this->text()->null()->defaultValue(null), - 'user_id' => $this->integer()->null()->defaultValue(null), - 'user_2_id' => $this->integer()->null()->defaultValue(null), - 'user_3_id' => $this->integer()->null()->defaultValue(null), - 'user_4_id' => $this->integer()->null()->defaultValue(null), + 'user_id' => $this->integer()->null()->defaultValue(null)->comment('x on-x (update|delete) foreign key constraint'), + 'user_2_id' => $this->integer()->null()->defaultValue(null)->comment('x on-x (update|delete) foreign key constraint'), + 'user_3_id' => $this->integer()->null()->defaultValue(null)->comment('x on-x (update|delete) foreign key constraint'), + 'user_4_id' => $this->integer()->null()->defaultValue(null)->comment('x on-x (update|delete) foreign key constraint'), ]); $this->addForeignKey('fk_postxes_user_id_userxes_id', '{{%postxes}}', 'user_id', '{{%userxes}}', 'id', null, 'CASCADE'); $this->addForeignKey('fk_postxes_user_2_id_userxes_id', '{{%postxes}}', 'user_2_id', '{{%userxes}}', 'id', 'SET NULL', 'CASCADE'); $this->addForeignKey('fk_postxes_user_3_id_userxes_id', '{{%postxes}}', 'user_3_id', '{{%userxes}}', 'id', 'SET NULL'); $this->addForeignKey('fk_postxes_user_4_id_userxes_id', '{{%postxes}}', 'user_4_id', '{{%userxes}}', 'id'); + $this->addCommentOnColumn('{{%postxes}}', 'user_id', 'x on-x (update|delete) foreign key constraint'); + $this->addCommentOnColumn('{{%postxes}}', 'user_2_id', 'x on-x (update|delete) foreign key constraint'); + $this->addCommentOnColumn('{{%postxes}}', 'user_3_id', 'x on-x (update|delete) foreign key constraint'); + $this->addCommentOnColumn('{{%postxes}}', 'user_4_id', 'x on-x (update|delete) foreign key constraint'); } public function safeDown() diff --git a/tests/unit/IssueFixTest.php b/tests/unit/IssueFixTest.php index 91a17357..86a41d4c 100644 --- a/tests/unit/IssueFixTest.php +++ b/tests/unit/IssueFixTest.php @@ -544,6 +544,197 @@ public function test158BugGiiapiGeneratedRulesEnumWithTrim() $this->checkFiles($actualFiles, $expectedFiles); } + // https://github.com/php-openapi/yii2-openapi/issues/60 + public function test60DescriptionOfAPropertyInSpecMustCorrespondToDbTableColumnComment() + { + // MySQL + $this->deleteTableFor60DescriptionOfAProperty(); + $this->createTableFor60DescriptionOfAProperty(); + $testFile = Yii::getAlias("@specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/index.php"); + $this->runGenerator($testFile); + $this->runActualMigrations(); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/mysql"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + $this->deleteTableFor60DescriptionOfAProperty(); + + + // PgSQL + $this->changeDbToPgsql(); + $this->deleteTableFor60DescriptionOfAProperty(); + $this->createTableFor60DescriptionOfAProperty(); + $this->runGenerator($testFile, 'pgsql'); + $this->runActualMigrations('pgsql'); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + 'except' => ['migrations_mysql_db'] + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/issue_fix/60_description_of_a_property_in_spec_must_correspond_to_db_table_column_comment/pgsql"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + $this->deleteTableFor60DescriptionOfAProperty(); + } + + // https://github.com/php-openapi/yii2-openapi/issues/60 + public function test60ComponentSchemaLevelExtension() + { + + + $schema = <<alterColumn('{{%fruits}}', 'name', $this->text()->notNull()->comment('Hi there')); + } + + public function down() + { + $this->alterColumn('{{%fruits}}', 'name', $this->text()->null()); + } +} + +PHP; + + $this->for60($schema, $expected); + } + + // https://github.com/php-openapi/yii2-openapi/issues/60 + public function test60PropertyLevelExtension() + { + $schema = <<alterColumn('{{%fruits}}', 'name', $this->text()->notNull()->comment('Hi there')); + } + + public function down() + { + $this->alterColumn('{{%fruits}}', 'name', $this->text()->null()); + } +} + +PHP; + + $this->for60($schema, $expected); + } + + private function for60($spec, $expected) + { + Yii::$app->db->createCommand('DROP TABLE IF EXISTS {{%fruits}}')->execute(); + Yii::$app->db->createCommand()->createTable('{{%fruits}}', [ + 'id' => 'pk', + 'name' => 'text', + ])->execute(); + $config = [ + 'openApiPath' => 'data://text/plain;base64,' . base64_encode($spec), + 'generateUrls' => false, + 'generateModels' => false, + 'generateControllers' => false, + 'generateMigrations' => true, + 'generateModelFaker' => false, + ]; + $tmpConfigFile = Yii::getAlias("@runtime") . "/tmp-config.php"; + file_put_contents($tmpConfigFile, 'runGenerator($tmpConfigFile); + $actual = file_get_contents(Yii::getAlias('@app') . '/migrations_mysql_db/m200000_000000_change_table_fruits.php'); + $this->assertSame($expected, $actual); + $this->runActualMigrations('mysql', 1); + Yii::$app->db->createCommand('DROP TABLE IF EXISTS {{%fruits}}')->execute(); + } + + private function createTableFor60DescriptionOfAProperty() + { + Yii::$app->db->createCommand()->createTable('{{%animals}}', [ + 'id' => 'pk', + 'name' => 'text ', # comment "the name" + 'g' => 'text', + 'g2' => 'text', + 'g3' => 'text', + 'g4' => 'text', + 'drop_col' => 'text', + ])->execute(); + + Yii::$app->db->createCommand()->addCommentOnColumn('{{%animals}}', 'name', 'the comment on name col')->execute(); + Yii::$app->db->createCommand()->addCommentOnColumn('{{%animals}}', 'g2', 'the comment on g2 col')->execute(); + Yii::$app->db->createCommand()->addCommentOnColumn('{{%animals}}', 'g3', 'the comment on g3 col remains same')->execute(); + Yii::$app->db->createCommand()->addCommentOnColumn('{{%animals}}', 'g4', 'data type changes but comment remains same')->execute(); + } + + private function deleteTableFor60DescriptionOfAProperty() + { + Yii::$app->db->createCommand('DROP TABLE IF EXISTS {{%animals}}')->execute(); + } + // https://github.com/php-openapi/yii2-openapi/issues/3 public function test3BugAddRemovePropertyAndAtTheSameTimeChangeItAtXIndexes() {