|
|
|
@ -8,6 +8,7 @@
|
|
|
|
|
namespace yii\gii\generators\model; |
|
|
|
|
|
|
|
|
|
use Yii; |
|
|
|
|
use yii\db\ActiveRecord; |
|
|
|
|
use yii\db\Connection; |
|
|
|
|
use yii\gii\CodeFile; |
|
|
|
|
use yii\helpers\Inflector; |
|
|
|
@ -50,7 +51,7 @@ class Generator extends \yii\gii\Generator
|
|
|
|
|
array('ns', 'validateNamespace'), |
|
|
|
|
array('tableName', 'validateTableName'), |
|
|
|
|
array('modelClass', 'validateModelClass'), |
|
|
|
|
array('baseClass', 'validateBaseClass'), |
|
|
|
|
array('baseClass', 'validateClass', 'params' => array('extends' => ActiveRecord::className())), |
|
|
|
|
array('generateRelations, generateLabelsFromComments', 'boolean'), |
|
|
|
|
)); |
|
|
|
|
} |
|
|
|
@ -83,7 +84,7 @@ class Generator extends \yii\gii\Generator
|
|
|
|
|
'baseClass' => 'This is the base class of the new ActiveRecord class. It should be a fully qualified namespaced class name.', |
|
|
|
|
'generateRelations' => 'This indicates whether the generator should generate relations based on |
|
|
|
|
foreign key constraints it detects in the database. Note that if your database contains too many tables, |
|
|
|
|
you may want to uncheck this option to accelerate the code generation process.', |
|
|
|
|
you may want to uncheck this option to accelerate the code generation proc ess.', |
|
|
|
|
'generateLabelsFromComments' => 'This indicates whether the generator should generate attribute labels |
|
|
|
|
by using the comments of the corresponding DB columns.', |
|
|
|
|
); |
|
|
|
@ -101,6 +102,9 @@ class Generator extends \yii\gii\Generator
|
|
|
|
|
return array('ns', 'db', 'baseClass', 'generateRelations', 'generateLabelsFromComments'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @return Connection |
|
|
|
|
*/ |
|
|
|
|
public function getDbConnection() |
|
|
|
|
{ |
|
|
|
|
return Yii::$app->{$this->db}; |
|
|
|
@ -108,33 +112,18 @@ class Generator extends \yii\gii\Generator
|
|
|
|
|
|
|
|
|
|
public function generate() |
|
|
|
|
{ |
|
|
|
|
$db = $this->getDbConnection(); |
|
|
|
|
|
|
|
|
|
if (($pos = strrpos($this->tableName, '.')) !== false) { |
|
|
|
|
$schema = substr($this->tableName, 0, $pos); |
|
|
|
|
$tableName = substr($this->tableName, $pos + 1); |
|
|
|
|
} else { |
|
|
|
|
$schema = ''; |
|
|
|
|
$tableName = $this->tableName; |
|
|
|
|
} |
|
|
|
|
if (strpos($tableName, '*') !== false) { |
|
|
|
|
$tables = $db->getSchema()->getTableNames($schema); |
|
|
|
|
} else { |
|
|
|
|
$tables = array($db->getTableSchema($this->tableName, true)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$files = array(); |
|
|
|
|
|
|
|
|
|
foreach ($tables as $table) { |
|
|
|
|
$className = $this->generateClassName($table->name); |
|
|
|
|
foreach ($this->getTableNames() as $tableName) { |
|
|
|
|
$className = $this->generateClassName($tableName); |
|
|
|
|
$tableSchema = $this->getTableSchema($tableName); |
|
|
|
|
$params = array( |
|
|
|
|
'tableName' => $schema === '' ? $tableName : $schema . '.' . $tableName, |
|
|
|
|
'tableName' => $tableName, |
|
|
|
|
'className' => $className, |
|
|
|
|
'columns' => $table->columns, |
|
|
|
|
'labels' => $this->generateLabels($table), |
|
|
|
|
'tableSchema' => $tableSchema, |
|
|
|
|
'labels' => $this->generateLabels($tableSchema), |
|
|
|
|
); |
|
|
|
|
$files[] = new CodeFile( |
|
|
|
|
Yii::getAlias($this->modelPath) . '/' . $className . '.php', |
|
|
|
|
Yii::getAlias('@' . $this->ns) . '/' . $className . '.php', |
|
|
|
|
$this->render('model.php', $params) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
@ -142,25 +131,9 @@ class Generator extends \yii\gii\Generator
|
|
|
|
|
return $files; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
* Check that all database field names conform to PHP variable naming rules |
|
|
|
|
* For example mysql allows field name like "2011aa", but PHP does not allow variable like "$model->2011aa" |
|
|
|
|
* @param CDbTableSchema $table the table schema object |
|
|
|
|
* @return string the invalid table column name. Null if no error. |
|
|
|
|
*/ |
|
|
|
|
public function checkColumns($table) |
|
|
|
|
{ |
|
|
|
|
foreach ($table->columns as $column) { |
|
|
|
|
if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $column->name)) { |
|
|
|
|
return $table->name . '.' . $column->name; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function getTableSchema($tableName) |
|
|
|
|
{ |
|
|
|
|
$db = $this->getDbConnection(); |
|
|
|
|
return $db->getSchema()->getTable($tableName, true); |
|
|
|
|
return $this->getDbConnection()->getTableSchema($tableName, true); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function generateLabels($table) |
|
|
|
@ -403,18 +376,22 @@ class Generator extends \yii\gii\Generator
|
|
|
|
|
public function validateDb() |
|
|
|
|
{ |
|
|
|
|
if (Yii::$app->hasComponent($this->db) === false || !(Yii::$app->getComponent($this->db) instanceof Connection)) { |
|
|
|
|
$this->addError('db', 'A valid database connection is required to run this generator.'); |
|
|
|
|
$this->addError('db', 'Database Connection ID must refer to a valid application component.'); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function validateNamespace() |
|
|
|
|
{ |
|
|
|
|
$path = Yii::getAlias('@' . ltrim($this->ns, '\\'), false); |
|
|
|
|
if ($path === false) { |
|
|
|
|
$this->addError('ns', 'Namespace must be associated with an existing directory.'); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function validateModelClass() |
|
|
|
|
{ |
|
|
|
|
if ($this->isReservedKeyword($this->modelClass)) { |
|
|
|
|
$this->addError('modelClass', 'The name is a reserved PHP keyword.'); |
|
|
|
|
$this->addError('modelClass', 'Class name cannot be a reserved PHP keyword.'); |
|
|
|
|
} |
|
|
|
|
if (strpos($this->tableName, '*') === false && $this->modelClass == '') { |
|
|
|
|
$this->addError('modelClass', 'Model Class cannot be blank.'); |
|
|
|
@ -423,56 +400,41 @@ class Generator extends \yii\gii\Generator
|
|
|
|
|
|
|
|
|
|
public function validateTableName() |
|
|
|
|
{ |
|
|
|
|
$invalidTables = array(); |
|
|
|
|
$invalidColumns = array(); |
|
|
|
|
$tables = $this->getTableNames(); |
|
|
|
|
if (empty($tables)) { |
|
|
|
|
$this->addError('tableName', "Table '{$this->tableName}' does not exist.'"); |
|
|
|
|
} else { |
|
|
|
|
foreach ($tables as $table) { |
|
|
|
|
$class = $this->generateClassName($table); |
|
|
|
|
if ($this->isReservedKeyword($class)) { |
|
|
|
|
$this->addError('tableName', "Table '$table' would generate a class which is a reserved PHP keyword."); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected function getTableNames() |
|
|
|
|
{ |
|
|
|
|
$db = $this->getDbConnection(); |
|
|
|
|
$tableNames = array(); |
|
|
|
|
if ($this->tableName[strlen($this->tableName) - 1] === '*') { |
|
|
|
|
if (($pos = strrpos($this->tableName, '.')) !== false) { |
|
|
|
|
$schema = substr($this->tableName, 0, $pos); |
|
|
|
|
$pattern = '/' . str_replace('*', '\w+', substr($this->tableName, $pos + 1)) . '/'; |
|
|
|
|
} else { |
|
|
|
|
$schema = ''; |
|
|
|
|
$pattern = '/' . str_replace('*', '\w+', $this->tableName) . '/'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$this->modelClass = ''; |
|
|
|
|
$tables = $this->getDbConnection()->schema->getTables($schema); |
|
|
|
|
foreach ($tables as $table) { |
|
|
|
|
if ($this->tablePrefix == '' || strpos($table->name, $this->tablePrefix) === 0) { |
|
|
|
|
if (in_array(strtolower($table->name), self::$keywords)) { |
|
|
|
|
$invalidTables[] = $table->name; |
|
|
|
|
} |
|
|
|
|
if (($invalidColumn = $this->checkColumns($table)) !== null) { |
|
|
|
|
$invalidColumns[] = $invalidColumn; |
|
|
|
|
} |
|
|
|
|
foreach ($db->schema->getTableNames($schema) as $table) { |
|
|
|
|
if (preg_match($pattern, $table)) { |
|
|
|
|
$tableNames[] = $schema === '' ? $table : ($schema . '.' . $table); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if (($table = $this->getTableSchema($this->tableName)) === null) { |
|
|
|
|
$this->addError('tableName', "Table '{$this->tableName}' does not exist."); |
|
|
|
|
} |
|
|
|
|
if ($this->modelClass === '') { |
|
|
|
|
$this->addError('modelClass', 'Model Class cannot be blank.'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!$this->hasErrors($attribute) && ($invalidColumn = $this->checkColumns($table)) !== null) { |
|
|
|
|
$invalidColumns[] = $invalidColumn; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ($invalidTables != array()) { |
|
|
|
|
$this->addError('tableName', 'Model class cannot take a reserved PHP keyword! Table name: ' . implode(', ', $invalidTables) . "."); |
|
|
|
|
} |
|
|
|
|
if ($invalidColumns != array()) { |
|
|
|
|
$this->addError('tableName', 'Column names that does not follow PHP variable naming convention: ' . implode(', ', $invalidColumns) . "."); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function validateBaseClass() |
|
|
|
|
{ |
|
|
|
|
$class = @Yii::import($this->baseClass, true); |
|
|
|
|
if (!is_string($class) || !$this->classExists($class)) { |
|
|
|
|
$this->addError('baseClass', "Class '{$this->baseClass}' does not exist or has syntax error."); |
|
|
|
|
} elseif ($class !== 'CActiveRecord' && !is_subclass_of($class, 'CActiveRecord')) { |
|
|
|
|
$this->addError('baseClass', "'{$this->model}' must extend from CActiveRecord."); |
|
|
|
|
} elseif (($table = $db->getTableSchema($this->tableName, true)) !== null) { |
|
|
|
|
$tableNames[] = $this->tableName; |
|
|
|
|
} |
|
|
|
|
return $tableNames; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|