Skip to content

Commit

Permalink
Fix #534: Generating in model ENUM fields value constants, setter and…
Browse files Browse the repository at this point in the history
… getter methods
  • Loading branch information
uldisn authored Feb 1, 2024
1 parent 042aff9 commit c7f7533
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Yii Framework 2 gii extension Change Log
- Bug #532: Return `ExitCode::USAGE` on command input validation error (egmsystems)
- Enh #537: Generating rules for the fields with default values (manky)
- Enh #542: Use the table name to create the relation (thiagotalma)
- Enh #534: Generating in model ENUM fields value constants, setter and getter methods (uldisn)


2.2.6 May 22, 2023
Expand Down
58 changes: 58 additions & 0 deletions src/generators/model/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use yii\base\NotSupportedException;
use yii\db\ActiveQuery;
use yii\db\ActiveRecord;
use yii\db\ColumnSchema;
use yii\db\Connection;
use yii\db\Exception;
use yii\db\Schema;
Expand Down Expand Up @@ -307,6 +308,7 @@ public function generate()
'rules' => $this->generateRules($tableSchema),
'relations' => $tableRelations,
'relationsClassHints' => $this->generateRelationsClassHints($tableRelations, $this->generateQuery),
'enum' => $this->getEnum($tableSchema->columns),
];
$files[] = new CodeFile(
Yii::getAlias('@' . str_replace('\\', '/', $this->ns)) . '/' . $modelClassName . '.php',
Expand Down Expand Up @@ -509,6 +511,11 @@ public function generateRules($table)
$rules[] = "[['" . implode("', '", $columns) . "'], 'string', 'max' => $length]";
}

$columnsEnum = $this->getEnum($table->columns);
foreach ($columnsEnum as $fieldName => $columnEnum) {
$rules['enum-' . $fieldName] = "['" . $fieldName . "', 'in', 'range' => array_keys(self::" . $columnEnum['funcOptsName'] . '())]';
}

$db = $this->getDbConnection();

// Unique indexes rules
Expand Down Expand Up @@ -1188,6 +1195,57 @@ protected function isColumnAutoIncremental($table, $columns)
return false;
}

/**
* Prepares ENUM field values.
*
* @param ColumnSchema[] $columns
*
* @return array
*/
public function getEnum($columns)
{
$enum = [];
foreach ($columns as $column) {
if (!$this->isEnum($column)) {
continue;
}

$columnCamelName = Inflector::id2camel($column->name, '_');
$enum[$column->name]['funcOptsName'] = 'opts' . $columnCamelName;
$enum[$column->name]['isFunctionPrefix'] = 'is' . $columnCamelName;
$enum[$column->name]['setFunctionPrefix'] = 'set' . $columnCamelName . 'To';
$enum[$column->name]['displayFunctionPrefix'] = 'display' . $columnCamelName;
$enum[$column->name]['columnName'] = $column->name;
$enum[$column->name]['values'] = [];

foreach ($column->enumValues as $value) {

$constantName = strtoupper(Inflector::slug($column->name . ' ' . $value, '_'));
$label = Inflector::camel2words($value);

$enum[$column->name]['values'][] = [
'value' => $value,
'constName' => $constantName,
'label' => $label,
'functionSuffix' => Inflector::id2camel(Inflector::slug($value))
];
}
}

return $enum;
}

/**
* Checks if column is of ENUM type.
*
* @param ColumnSchema $column Column instance
* @return bool
*/
protected function isEnum($column)
{
return !empty($column->enumValues) || stripos($column->dbType, 'ENUM') === 0;
}

/**
* Returns the class name resolution
* @param string $class
Expand Down
64 changes: 64 additions & 0 deletions src/generators/model/default/model.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* This is the template for generating the model class of a specified table.
*/

/** @var $enum array list of ENUM fields */
/** @var yii\web\View $this */
/** @var yii\gii\generators\model\Generator $generator */
/** @var string $tableName full table name */
Expand Down Expand Up @@ -36,6 +37,20 @@
*/
class <?= $className ?> extends <?= '\\' . ltrim($generator->baseClass, '\\') . "\n" ?>
{

<?php if (!empty($enum)): ?>
/**
* ENUM field values
*/
<?php
foreach($enum as $columnName => $columnData) {
foreach ($columnData['values'] as $enumValue){
echo ' const ' . $enumValue['constName'] . ' = \'' . $enumValue['value'] . '\';' . PHP_EOL;
}
}
endif
?>

/**
* {@inheritdoc}
*/
Expand Down Expand Up @@ -99,4 +114,53 @@ public static function find()
return new <?= $queryClassFullName ?>(get_called_class());
}
<?php endif; ?>

<?php if ($enum): ?>
<?php foreach ($enum as $columnName => $columnData): ?>

/**
* column <?= $columnName ?> ENUM value labels
* @return string[]
*/
public static function <?= $columnData['funcOptsName'] ?>()
{
return [
<?php foreach ($columnData['values'] as $k => $value): ?>
<?php
if ($generator->enableI18N) {
echo ' self::' . $value['constName'] . ' => Yii::t(\'' . $generator->messageCategory . '\', \'' . $value['value'] . "'),\n";
} else {
echo ' self::' . $value['constName'] . ' => \'' . $value['value'] . "',\n";
}
?>
<?php endforeach; ?>
];
}
<?php endforeach; ?>
<?php foreach ($enum as $columnName => $columnData): ?>

/**
* @return string
*/
public function <?= $columnData['displayFunctionPrefix'] ?>()
{
return self::<?= $columnData['funcOptsName'] ?>()[$this-><?=$columnName?>];
}
<?php foreach ($columnData['values'] as $enumValue): ?>

/**
* @return bool
*/
public function <?= $columnData['isFunctionPrefix'] . $enumValue['functionSuffix'] ?>()
{
return $this-><?= $columnName ?> === self::<?= $enumValue['constName'] ?>;
}

public function <?= $columnData['setFunctionPrefix'] . $enumValue['functionSuffix'] ?>()
{
$this-><?= $columnName ?> = self::<?= $enumValue['constName'] ?>;
}
<?php endforeach; ?>
<?php endforeach; ?>
<?php endif; ?>
}
109 changes: 109 additions & 0 deletions tests/generators/ModelGeneratorTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?php
namespace yiiunit\gii\generators;

use yii\db\mysql\ColumnSchema;
use yii\db\TableSchema;
use yii\gii\generators\model\Generator as ModelGenerator;
use yiiunit\gii\GiiTestCase;

Expand Down Expand Up @@ -484,4 +486,111 @@ public function testGenerateProperties($tableName, $columns)
}

}

public function testEnum()
{
$generator = new ModelGenerator();
$generator->template = 'default';
$generator->tableName = 'category_photo';

$tableSchema = $this->createEnumTableSchema();
$params = [
'tableName' => $tableSchema->name,
'className' => 'TestEnumModel',
'queryClassName' => false,
'tableSchema' => $tableSchema,
'properties' => [],
'labels' => $generator->generateLabels($tableSchema),
'rules' => $generator->generateRules($tableSchema),
'relations' => [],
'relationsClassHints' => [],
'enum' => $generator->getEnum($tableSchema->columns),
];
$codeFile = $generator->render('model.php', $params);

/**
* Fix class code for eval - remove ?php, namespace and use Yii
*/
$classCode = str_replace('<?php', '', $codeFile);
$classCode = str_replace('namespace app\models;', '', $classCode);
$classCode = str_replace('use Yii;', '', $classCode);

/**
* Add method getTableSchema for setting test schema
*/
$classCode = substr($classCode, 0, strrpos($classCode, "\n"));
$classCode = substr($classCode, 0, strrpos($classCode, "\n"));
$classCode .= '
public static $testTableSchema;
public static function getTableSchema(){
return self::$testTableSchema;
}
}
';
if (!class_exists('TestEnumModel')) {
eval($classCode);
}

$testEnumModel = new \TestEnumModel();
$testEnumModel::$testTableSchema = $this->createEnumTableSchema();

/** test assigning and method is... */
$testEnumModel->type = \TestEnumModel::TYPE_CLIENT;
$this->assertTrue($testEnumModel->isTypeClient());
$this->assertFalse($testEnumModel->isTypeConsignees());

$testEnumModel->type = \TestEnumModel::TYPE_CONSIGNEES;
$this->assertFalse($testEnumModel->isTypeClient());
$this->assertTrue($testEnumModel->isTypeConsignees());
$this->assertEquals(\TestEnumModel::TYPE_CONSIGNEES,$testEnumModel->displayType());

/** test validate */
$this->assertTrue($testEnumModel->validate());
$testEnumModel->type = '11111';
$this->assertFalse($testEnumModel->validate());

}

public function createEnumTableSchema()
{
$schema = new TableSchema();
$schema->name = 'company_type';
$schema->fullName = 'company_type';
$schema->primaryKey = ['id'];
$schema->columns = [
'id' => new ColumnSchema([
'name' => 'id',
'allowNull' => false,
'type' => 'smallint',
'phpType' => 'integer',
'dbType' => 'smallint(5) unsigned',
'size' => 5,
'precision' => 5,
'isPrimaryKey' => true,
'autoIncrement' => true,
'unsigned' => true,
'comment' => ''
]),
'type' => new ColumnSchema([
'name' => 'type',
'allowNull' => true,
'type' => 'string',
'phpType' => 'string',
'dbType' => 'enum(\'Client\',\'Consignees\',\'Car cleaner\')',
'enumValues' => [
0 => 'Client',
1 => 'Consignees',
2 => 'Car cleaner',
],
'size' => null,
'precision' => null,
'isPrimaryKey' => false,
'autoIncrement' => false,
'unsigned' => false,
'comment' => ''
]),
];

return $schema;
}
}

0 comments on commit c7f7533

Please sign in to comment.