From 28423486f164b81da4ddc3e1390bcf0cc7bcccc5 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Sat, 24 Aug 2013 07:10:18 -0400 Subject: [PATCH] model generator WIP --- framework/yii/db/Connection.php | 5 +- framework/yii/gii/Generator.php | 13 +++-- framework/yii/gii/generators/model/Generator.php | 61 ++++++++++++++-------- .../yii/gii/generators/model/templates/model.php | 6 +-- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/framework/yii/db/Connection.php b/framework/yii/db/Connection.php index a843823..d7da806 100644 --- a/framework/yii/db/Connection.php +++ b/framework/yii/db/Connection.php @@ -497,14 +497,15 @@ class Connection extends Component * Processes a SQL statement by quoting table and column names that are enclosed within double brackets. * Tokens enclosed within double curly brackets are treated as table names, while * tokens enclosed within double square brackets are column names. They will be quoted accordingly. - * Also, the percentage character "%" in a table name will be replaced with [[tablePrefix]]. + * Also, the percentage character "%" at the beginning or ending of a table name will be replaced + * with [[tablePrefix]]. * @param string $sql the SQL to be quoted * @return string the quoted SQL */ public function quoteSql($sql) { $db = $this; - return preg_replace_callback('/(\\{\\{([%\w\-\. ]+)\\}\\}|\\[\\[([\w\-\. ]+)\\]\\])/', + return preg_replace_callback('/(\\{\\{(%?[\w\-\. ]+)\\}\\}|\\{\\{([\w\-\. ]+%?)\\}\\}|\\[\\[([\w\-\. ]+)\\]\\])/', function ($matches) use ($db) { if (isset($matches[3])) { return $db->quoteColumnName($matches[3]); diff --git a/framework/yii/gii/Generator.php b/framework/yii/gii/Generator.php index 5a6da98..f0e06ab 100644 --- a/framework/yii/gii/Generator.php +++ b/framework/yii/gii/Generator.php @@ -302,16 +302,19 @@ abstract class Generator extends Model */ public function validateClass($attribute, $params) { + $class = $this->$attribute; 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."); + if (class_exists($class)) { + if (isset($params['extends'])) { + if (ltrim($class, '\\') !== ltrim($params['extends'], '\\') && !is_subclass_of($class, $params['extends'])) { + $this->addError($attribute, "'$class' must extend from {$params['extends']} or its child class."); + } } } else { - $this->addError($attribute, "Class '{$this->$attribute}' does not exist or has syntax error."); + $this->addError($attribute, "Class '$class' does not exist or has syntax error."); } } catch (\Exception $e) { - $this->addError($attribute, "Class '{$this->$attribute}' does not exist or has syntax error."); + $this->addError($attribute, "Class '$class' does not exist or has syntax error."); } } diff --git a/framework/yii/gii/generators/model/Generator.php b/framework/yii/gii/generators/model/Generator.php index bba3e9e..ff0e35c 100644 --- a/framework/yii/gii/generators/model/Generator.php +++ b/framework/yii/gii/generators/model/Generator.php @@ -24,7 +24,7 @@ class Generator extends \yii\gii\Generator public $ns = 'app\models'; public $tableName; public $modelClass; - public $baseClass = '\yii\db\ActiveRecord'; + public $baseClass = 'yii\db\ActiveRecord'; public $generateRelations = true; public $generateLabelsFromComments = false; @@ -46,7 +46,7 @@ class Generator extends \yii\gii\Generator array('db, ns, tableName, baseClass', 'required'), array('db, modelClass', 'match', 'pattern' => '/^\w+$/', 'message' => 'Only word characters are allowed.'), array('ns, baseClass', 'match', 'pattern' => '/^[\w\\\\]+$/', 'message' => 'Only word characters and backslashes are allowed.'), - array('tableName', 'match', 'pattern' => '/^(\w+\.)?\w+\*?$/', 'message' => 'Only word characters, and optionally an asterisk and/or a dot are allowed.'), + array('tableName', 'match', 'pattern' => '/^(\w+\.)?([\w\*]+)$/', 'message' => 'Only word characters, and optionally an asterisk and/or a dot are allowed.'), array('db', 'validateDb'), array('ns', 'validateNamespace'), array('tableName', 'validateTableName'), @@ -123,7 +123,7 @@ class Generator extends \yii\gii\Generator 'labels' => $this->generateLabels($tableSchema), ); $files[] = new CodeFile( - Yii::getAlias('@' . $this->ns) . '/' . $className . '.php', + Yii::getAlias('@' . str_replace('\\', '/', $this->ns)) . '/' . $className . '.php', $this->render('model.php', $params) ); } @@ -142,6 +142,8 @@ class Generator extends \yii\gii\Generator foreach ($table->columns as $column) { if ($this->generateLabelsFromComments && !empty($column->comment)) { $labels[$column->name] = $column->comment; + } elseif (!strcasecmp($column->name, 'id')) { + $labels[$column->name] = 'ID'; } else { $label = Inflector::camel2words($column->name); if (strcasecmp(substr($label, -3), ' id') === 0) { @@ -317,22 +319,30 @@ class Generator extends \yii\gii\Generator protected function generateClassName($tableName) { - if ($this->tableName === $tableName || ($pos = strrpos($this->tableName, '.')) !== false && substr($this->tableName, $pos + 1) === $tableName) { - return $this->modelClass; + if (($pos = strrpos($tableName, '.')) !== false) { + $tableName = substr($tableName, $pos + 1); } - $tableName = $this->removePrefix($tableName, false); - if (($pos = strpos($tableName, '.')) !== false) // remove schema part (e.g. remove 'public2.' from 'public2.post') - { - $tableName = substr($tableName, $pos + 1); + $db = $this->getDbConnection(); + $patterns = array(); + if (strpos($this->tableName, '*') !== false) { + $pattern = $this->tableName; + if (($pos = strrpos($pattern, '.')) !== false) { + $pattern = substr($pattern, $pos + 1); + } + $patterns[] = '/^' . str_replace('*', '(\w+)', $pattern) . '$/'; } - $className = ''; - foreach (explode('_', $tableName) as $name) { - if ($name !== '') { - $className .= ucfirst($name); + if (!empty($db->tablePrefix)) { + $patterns[] = "/^{$db->tablePrefix}(.*?)|(.*?){$db->tablePrefix}$/"; + } + + $className = $tableName; + foreach ($patterns as $pattern) { + if (preg_match($pattern, $tableName, $matches)) { + $className = $matches[1]; } } - return $className; + return Inflector::id2camel($className, '_'); } /** @@ -375,14 +385,17 @@ 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', 'Database Connection ID must refer to a valid application component.'); + if (Yii::$app->hasComponent($this->db) === false) { + $this->addError('db', 'There is no application component named "db".'); + } elseif (!Yii::$app->getComponent($this->db) instanceof Connection) { + $this->addError('db', 'The "db" application component must be a DB connection instance.'); } } public function validateNamespace() { - $path = Yii::getAlias('@' . ltrim($this->ns, '\\'), false); + $this->ns = ltrim($this->ns, '\\'); + $path = Yii::getAlias('@' . str_replace('\\', '/', $this->ns), false); if ($path === false) { $this->addError('ns', 'Namespace must be associated with an existing directory.'); } @@ -400,14 +413,18 @@ class Generator extends \yii\gii\Generator public function validateTableName() { + if (($pos = strpos($this->tableName, '*')) !== false && strpos($this->tableName, '*', $pos + 1) !== false) { + $this->addError('tableName', 'At most one asterisk is allowed.'); + return; + } $tables = $this->getTableNames(); if (empty($tables)) { - $this->addError('tableName', "Table '{$this->tableName}' does not exist.'"); + $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."); + $this->addError('tableName', "Table '$table' will generate a class which is a reserved PHP keyword."); break; } } @@ -418,13 +435,13 @@ class Generator extends \yii\gii\Generator { $db = $this->getDbConnection(); $tableNames = array(); - if ($this->tableName[strlen($this->tableName) - 1] === '*') { + if (strpos($this->tableName, '*') !== false) { if (($pos = strrpos($this->tableName, '.')) !== false) { $schema = substr($this->tableName, 0, $pos); - $pattern = '/' . str_replace('*', '\w+', substr($this->tableName, $pos + 1)) . '/'; + $pattern = '/^' . str_replace('*', '\w+', substr($this->tableName, $pos + 1)) . '$/'; } else { $schema = ''; - $pattern = '/' . str_replace('*', '\w+', $this->tableName) . '/'; + $pattern = '/^' . str_replace('*', '\w+', $this->tableName) . '$/'; } foreach ($db->schema->getTableNames($schema) as $table) { diff --git a/framework/yii/gii/generators/model/templates/model.php b/framework/yii/gii/generators/model/templates/model.php index a0b15e0..7a7558c 100644 --- a/framework/yii/gii/generators/model/templates/model.php +++ b/framework/yii/gii/generators/model/templates/model.php @@ -17,14 +17,10 @@ * - $relations: list of relations (name=>relation declaration) */ -$pos = strrpos($className, '\\'); -$ns = ltrim(substr($className, 0, $pos), '\\'); -$className = substr($className, $pos + 1); - echo " -namespace ; +namespace ns; ?>; /** * This is the model class for table "".