mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-20 10:27:18 +08:00
refactored generators.
This commit is contained in:
@ -293,6 +293,28 @@ abstract class Generator extends Model
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An inline validator that checks if the attribute value refers to an existing class name.
|
||||
* If the `extends` option is specified, it will also check if the class is a child class
|
||||
* of the class represented by the `extends` option.
|
||||
* @param string $attribute the attribute being validated
|
||||
* @param array $params the validation options
|
||||
*/
|
||||
public function validateClass($attribute, $params)
|
||||
{
|
||||
try {
|
||||
if (class_exists($this->$attribute)) {
|
||||
if (isset($params['extends']) && !is_subclass_of($this->$attribute, $params['extends'])) {
|
||||
$this->addError($attribute, "'{$this->$attribute}' must extend from {$params['extends']} or its child class.");
|
||||
}
|
||||
} else {
|
||||
$this->addError($attribute, "Class '{$this->$attribute}' does not exist or has syntax error.");
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->addError($attribute, "Class '{$this->$attribute}' does not exist or has syntax error.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value the attribute to be validated
|
||||
* @return boolean whether the value is a reserved PHP keyword.
|
||||
|
@ -63,7 +63,7 @@ class Generator extends \yii\gii\Generator
|
||||
array('modelClass, viewName, scenarioName, viewPath', 'filter', 'filter' => 'trim'),
|
||||
array('modelClass, viewName, viewPath', 'required'),
|
||||
array('modelClass', 'match', 'pattern' => '/^[\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'),
|
||||
array('modelClass', 'validateModel'),
|
||||
array('modelClass', 'validateClass', 'extends' => Model::className()),
|
||||
array('viewName', 'match', 'pattern' => '/^\w+[\\-\\/\w]*$/', 'message' => 'Only word characters, dashes and slashes are allowed.'),
|
||||
array('viewPath', 'match', 'pattern' => '/^@?\w+[\\-\\/\w]*$/', 'message' => 'Only word characters, dashes, slashes and @ are allowed.'),
|
||||
array('viewPath', 'validateViewPath'),
|
||||
@ -129,25 +129,6 @@ class Generator extends \yii\gii\Generator
|
||||
EOD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the model class to make sure it exists and is valid.
|
||||
*/
|
||||
public function validateModel()
|
||||
{
|
||||
try {
|
||||
if (class_exists($this->modelClass)) {
|
||||
if (!is_subclass_of($this->modelClass, Model::className())) {
|
||||
$this->addError('modelClass', "'{$this->modelClass}' must extend from Model or its child class.");
|
||||
}
|
||||
} else {
|
||||
$this->addError('modelClass', "Class '{$this->modelClass}' does not exist or has syntax error.");
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->addError('modelClass', "Class '{$this->modelClass}' does not exist or has syntax error.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates [[viewPath]] to make sure it is a valid path or path alias and exists.
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
* @var yii\gii\generators\form\Generator $generator
|
||||
*/
|
||||
|
||||
echo $form->field($generator, 'tableName');
|
||||
echo $form->field($generator, 'tableNamess');
|
||||
echo $form->field($generator, 'modelClass');
|
||||
echo $form->field($generator, 'ns');
|
||||
echo $form->field($generator, 'baseClass');
|
||||
|
@ -6,12 +6,12 @@
|
||||
* @var yii\gii\generators\model\Generator $generator
|
||||
* @var string $tableName
|
||||
* @var string $className
|
||||
* @var yii\db\ColumnSchema[] $columns
|
||||
* @var yii\db\TableSchema $tableSchema
|
||||
* @var string[] $labels
|
||||
*
|
||||
* - $tableName: the table name for this class (prefix is already removed if necessary)
|
||||
* - $modelClass: the model class name
|
||||
* - $columns: list of table columns (name=>CDbColumnSchema)
|
||||
* - $tableSchema: list of table columns (name=>CDbColumnSchema)
|
||||
* - $labels: list of attribute labels (name=>label)
|
||||
* - $rules: list of validation rules
|
||||
* - $relations: list of relations (name=>relation declaration)
|
||||
@ -31,7 +31,7 @@ namespace <?php echo $ns; ?>;
|
||||
*
|
||||
* Attributes:
|
||||
*
|
||||
<?php foreach ($columns as $column): ?>
|
||||
<?php foreach ($tableSchema->columns as $column): ?>
|
||||
* @property <?php echo "{$column->phpType} \${$column->name}\n"; ?>
|
||||
<?php endforeach; ?>
|
||||
*/
|
||||
|
Reference in New Issue
Block a user