'FooBar'
*/
public $tableNameMap = [];
protected $classNames2;
public $classnameTarget;
/**
* @var array for new rules
*/
public $newRules = [];
/**
* @var array per relazioni aggiuntive
*/
public $otherRelations = [];
public $workflow;
/**
*
* @var array per le colonne rappresentative
*/
public $representingColumn;
/**
*
*/
public $pluginName;
/**
*
* @var string $generatedClassName
*/
public $generatedClassName;
/**
* @inheritdoc
*/
public function getName()
{
return 'Amos Model';
}
/**
* @inheritdoc
*/
public function getDescription()
{
return 'This generator generates an ActiveRecord class and base class for the specified database table.';
}
/**
* @inheritdoc
*/
public function rules()
{
return array_merge(
parent::rules(),
[
[['generateModelClass'], 'boolean'],
[['tablePrefix'], 'safe'],
]
);
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return array_merge(
parent::attributeLabels(), [
'generateModelClass' => 'Generate Model Class',
]
);
}
/**
* @inheritdoc
*/
public function hints()
{
return array_merge(
parent::hints(),
[
'generateModelClass' => 'This indicates whether the generator should generate the model class, this should usually be done only once. The model-base class is always generated.',
'tablePrefix' => 'Custom table prefix, eg app_
.
Note! overrides yii\db\Connection
prefix!',
]
);
}
/**
* @inheritdoc
*/
public function requiredTemplates()
{
return ['model.php'];
}
/**
* @inheritdoc
*/
public function generate()
{
try {
$files = [];
$relations = $this->generateRelations();
$db = $this->getDbConnection();
foreach ($this->getTableNames() as $tableName) {
$className = $this->generateClassName($tableName);
$relations = $this->createRelations($relations, $tableName, $className);
$tableSchema = $db->getTableSchema($tableName);
$params = [
'tableName' => $tableName,
'className' => $className,
'tableSchema' => $tableSchema,
'labels' => $this->generateLabels($tableSchema),
'rules' => $this->generateRules($tableSchema),
'relations' => isset($relations[$tableName]) ? $relations[$tableName] : [],
'otherRelations' => $this->otherRelations,
'classnameTarget' => $this->classnameTarget,
'newRules' => $this->newRules,
'ns' => $this->ns,
'representingColumn' => $this->representingColumn,
'pluginName' => $this->pluginName
];
$files[] = new CodeFile(
Yii::getAlias('@'.str_replace('\\', '/', $this->ns)).'/'.$className.'.php',
$this->render('model.php', $params)
);
}
return $files;
} catch (\Exception $e) {
pr($e->getMessage());
die;
return null;
}
}
protected function createRelations($relation, $tableName, $modelClass)
{
$ret = [];
$len = strlen($modelClass);
$modelClass = substr($modelClass, 0, ($len - 11));
if (isset($relation[$tableName][$modelClass][0])) {
$posA = strpos($relation[$tableName][$modelClass][0], 'Translation::');
$posB = $posA + 11;
$pre = substr($relation[$tableName][$modelClass][0], 0, $posA);
$post = substr($relation[$tableName][$modelClass][0], $posB);
$relation[$tableName][$modelClass][0] = $pre.$post;
$ret = $relation;
}
return $ret;
}
/**
* Generates a class name from the specified table name.
*
* @param string $tableName the table name (which may contain schema prefix)
*
* @return string the generated class name
*/
protected function generateClassName($tableName, $useSchemaName = null)
{
#Yii::trace("Generating class name for '{$tableName}'...", __METHOD__);
if (isset($this->classNames2[$tableName])) {
#Yii::trace("Using '{$this->classNames2[$tableName]}' for '{$tableName}' from classNames2.", __METHOD__);
return $this->classNames2[$tableName];
}
if (isset($this->tableNameMap[$tableName])) {
Yii::trace("Converted '{$tableName}' from tableNameMap.", __METHOD__);
return $this->classNames2[$tableName] = $this->tableNameMap[$tableName];
}
if (($pos = strrpos($tableName, '.')) !== false) {
$tableName = substr($tableName, $pos + 1);
}
$db = $this->getDbConnection();
$patterns = [];
$patterns[] = "/^{$this->tablePrefix}(.*?)$/";
$patterns[] = "/^(.*?){$this->tablePrefix}$/";
$patterns[] = "/^{$db->tablePrefix}(.*?)$/";
$patterns[] = "/^(.*?){$db->tablePrefix}$/";
if (strpos($this->tableName, '*') !== false) {
$pattern = $this->tableName;
if (($pos = strrpos($pattern, '.')) !== false) {
$pattern = substr($pattern, $pos + 1);
}
$patterns[] = '/^'.str_replace('*', '(\w+)', $pattern).'$/';
}
$className = $tableName;
foreach ($patterns as $pattern) {
if (preg_match($pattern, $tableName, $matches)) {
$className = $matches[1];
Yii::trace("Mapping '{$tableName}' to '{$className}' from pattern '{$pattern}'.", __METHOD__);
break;
}
}
$returnName = Inflector::id2camel($className, '_');
Yii::trace("Converted '{$tableName}' to '{$returnName}'.", __METHOD__);
if (empty($this->generatedClassName)) {
return $this->classNames2[$tableName] = $returnName;
} else {
return $this->classNames2[$tableName] = $this->generatedClassName;
}
}
protected function generateRelations()
{
try {
$relations = parent::generateRelations();
// inject namespace
$ns = "\\{$this->classnameTarget}";
foreach ($relations AS $model => $relInfo) {
foreach ($relInfo AS $relName => $relData) {
$relations[$model][$relName][0] = preg_replace(
'/(has[A-Za-z0-9]+\()([a-zA-Z0-9]+::)/', '$1__NS__$2', $relations[$model][$relName][0]
);
$relations[$model][$relName][0] = str_replace('__NS__', $ns, $relations[$model][$relName][0]);
}
}
return $relations;
} catch (\Exception $e) {
return null;
}
}
/**
* Generates validation rules for the specified table.
* @param \yii\db\TableSchema $table the table schema
* @return array the generated validation rules
*/
public function generateRules($table)
{
$types = [];
$lengths = [];
foreach ($table->columns as $column) {
if ($column->autoIncrement) {
continue;
}
if (!$column->allowNull && $column->defaultValue === null) {
$types['required'][] = $column->name;
}
switch ($column->type) {
case Schema::TYPE_SMALLINT:
case Schema::TYPE_INTEGER:
case Schema::TYPE_BIGINT:
$types['integer'][] = $column->name;
break;
case Schema::TYPE_BOOLEAN:
$types['boolean'][] = $column->name;
break;
case Schema::TYPE_FLOAT:
case 'double': // Schema::TYPE_DOUBLE, which is available since Yii 2.0.3
case Schema::TYPE_DECIMAL:
case Schema::TYPE_MONEY:
$types['number'][] = $column->name;
break;
case Schema::TYPE_DATE:
case Schema::TYPE_TIME:
case Schema::TYPE_DATETIME:
case Schema::TYPE_TIMESTAMP:
$types['safe'][] = $column->name;
break;
default: // strings
if ($column->size > 0) {
$lengths[$column->size][] = $column->name;
} else {
$types['string'][] = $column->name;
}
}
}
$rules = [];
foreach ($types as $type => $columns) {
$rules[] = "[['".implode("', '", $columns)."'], '$type']";
}
foreach ($lengths as $length => $columns) {
$rules[] = "[['".implode("', '", $columns)."'], 'string', 'max' => $length]";
}
$db = $this->getDbConnection();
// Unique indexes rules
try {
$uniqueIndexes = $db->getSchema()->findUniqueIndexes($table);
foreach ($uniqueIndexes as $uniqueColumns) {
// Avoid validating auto incremental columns
if (!$this->isColumnAutoIncremental($table, $uniqueColumns)) {
$attributesCount = count($uniqueColumns);
if ($attributesCount === 1) {
$rules[] = "[['".$uniqueColumns[0]."'], 'unique']";
} elseif ($attributesCount > 1) {
$labels = array_intersect_key($this->generateLabels($table), array_flip($uniqueColumns));
$lastLabel = array_pop($labels);
$columnsList = implode("', '", $uniqueColumns);
$rules[] = "[['$columnsList'], 'unique', 'targetAttribute' => ['$columnsList'], 'message' => 'The combination of ".implode(', ',
$labels)." and $lastLabel has already been taken.']";
}
}
}
} catch (NotSupportedException $e) {
// doesn't support unique indexes information...do nothing
}
// Exist rules for foreign keys
foreach ($table->foreignKeys as $refs) {
$refTable = $refs[0];
$refTableSchema = $db->getTableSchema($refTable);
if ($refTableSchema === null) {
// Foreign key could point to non-existing table: https://github.com/yiisoft/yii2-gii/issues/34
continue;
}
$refClassName = $this->generateClassName($refTable);
$pos = strlen($refClassName) - 11;
$refClassName = substr($refClassName, 0, $pos);
unset($refs[0]);
$attributes = implode("', '", array_keys($refs));
$targetAttributes = [];
foreach ($refs as $key => $value) {
$targetAttributes[] = "'$key' => '$value'";
}
$targetAttributes = implode(', ', $targetAttributes);
$rules[] = "[['$attributes'], 'exist', 'skipOnError' => true, 'targetClass' => ".(isset($this->classnameTarget)
? "\\".$this->classnameTarget : "")."$refClassName::className(), 'targetAttribute' => [$targetAttributes]]";
}
return $rules;
}
}