Commit 28423486 by Qiang Xue

model generator WIP

parent 2d6ec6bb
...@@ -497,14 +497,15 @@ class Connection extends Component ...@@ -497,14 +497,15 @@ class Connection extends Component
* Processes a SQL statement by quoting table and column names that are enclosed within double brackets. * 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 curly brackets are treated as table names, while
* tokens enclosed within double square brackets are column names. They will be quoted accordingly. * 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 * @param string $sql the SQL to be quoted
* @return string the quoted SQL * @return string the quoted SQL
*/ */
public function quoteSql($sql) public function quoteSql($sql)
{ {
$db = $this; $db = $this;
return preg_replace_callback('/(\\{\\{([%\w\-\. ]+)\\}\\}|\\[\\[([\w\-\. ]+)\\]\\])/', return preg_replace_callback('/(\\{\\{(%?[\w\-\. ]+)\\}\\}|\\{\\{([\w\-\. ]+%?)\\}\\}|\\[\\[([\w\-\. ]+)\\]\\])/',
function ($matches) use ($db) { function ($matches) use ($db) {
if (isset($matches[3])) { if (isset($matches[3])) {
return $db->quoteColumnName($matches[3]); return $db->quoteColumnName($matches[3]);
......
...@@ -302,16 +302,19 @@ abstract class Generator extends Model ...@@ -302,16 +302,19 @@ abstract class Generator extends Model
*/ */
public function validateClass($attribute, $params) public function validateClass($attribute, $params)
{ {
$class = $this->$attribute;
try { try {
if (class_exists($this->$attribute)) { if (class_exists($class)) {
if (isset($params['extends']) && !is_subclass_of($this->$attribute, $params['extends'])) { if (isset($params['extends'])) {
$this->addError($attribute, "'{$this->$attribute}' must extend from {$params['extends']} or its child class."); 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 { } 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) { } 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.");
} }
} }
......
...@@ -24,7 +24,7 @@ class Generator extends \yii\gii\Generator ...@@ -24,7 +24,7 @@ class Generator extends \yii\gii\Generator
public $ns = 'app\models'; public $ns = 'app\models';
public $tableName; public $tableName;
public $modelClass; public $modelClass;
public $baseClass = '\yii\db\ActiveRecord'; public $baseClass = 'yii\db\ActiveRecord';
public $generateRelations = true; public $generateRelations = true;
public $generateLabelsFromComments = false; public $generateLabelsFromComments = false;
...@@ -46,7 +46,7 @@ class Generator extends \yii\gii\Generator ...@@ -46,7 +46,7 @@ class Generator extends \yii\gii\Generator
array('db, ns, tableName, baseClass', 'required'), array('db, ns, tableName, baseClass', 'required'),
array('db, modelClass', 'match', 'pattern' => '/^\w+$/', 'message' => 'Only word characters are allowed.'), 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('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('db', 'validateDb'),
array('ns', 'validateNamespace'), array('ns', 'validateNamespace'),
array('tableName', 'validateTableName'), array('tableName', 'validateTableName'),
...@@ -123,7 +123,7 @@ class Generator extends \yii\gii\Generator ...@@ -123,7 +123,7 @@ class Generator extends \yii\gii\Generator
'labels' => $this->generateLabels($tableSchema), 'labels' => $this->generateLabels($tableSchema),
); );
$files[] = new CodeFile( $files[] = new CodeFile(
Yii::getAlias('@' . $this->ns) . '/' . $className . '.php', Yii::getAlias('@' . str_replace('\\', '/', $this->ns)) . '/' . $className . '.php',
$this->render('model.php', $params) $this->render('model.php', $params)
); );
} }
...@@ -142,6 +142,8 @@ class Generator extends \yii\gii\Generator ...@@ -142,6 +142,8 @@ class Generator extends \yii\gii\Generator
foreach ($table->columns as $column) { foreach ($table->columns as $column) {
if ($this->generateLabelsFromComments && !empty($column->comment)) { if ($this->generateLabelsFromComments && !empty($column->comment)) {
$labels[$column->name] = $column->comment; $labels[$column->name] = $column->comment;
} elseif (!strcasecmp($column->name, 'id')) {
$labels[$column->name] = 'ID';
} else { } else {
$label = Inflector::camel2words($column->name); $label = Inflector::camel2words($column->name);
if (strcasecmp(substr($label, -3), ' id') === 0) { if (strcasecmp(substr($label, -3), ' id') === 0) {
...@@ -317,22 +319,30 @@ class Generator extends \yii\gii\Generator ...@@ -317,22 +319,30 @@ class Generator extends \yii\gii\Generator
protected function generateClassName($tableName) protected function generateClassName($tableName)
{ {
if ($this->tableName === $tableName || ($pos = strrpos($this->tableName, '.')) !== false && substr($this->tableName, $pos + 1) === $tableName) { if (($pos = strrpos($tableName, '.')) !== false) {
return $this->modelClass; $tableName = substr($tableName, $pos + 1);
} }
$tableName = $this->removePrefix($tableName, false); $db = $this->getDbConnection();
if (($pos = strpos($tableName, '.')) !== false) // remove schema part (e.g. remove 'public2.' from 'public2.post') $patterns = array();
{ if (strpos($this->tableName, '*') !== false) {
$tableName = substr($tableName, $pos + 1); $pattern = $this->tableName;
if (($pos = strrpos($pattern, '.')) !== false) {
$pattern = substr($pattern, $pos + 1);
} }
$className = ''; $patterns[] = '/^' . str_replace('*', '(\w+)', $pattern) . '$/';
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 ...@@ -375,14 +385,17 @@ class Generator extends \yii\gii\Generator
public function validateDb() public function validateDb()
{ {
if (Yii::$app->hasComponent($this->db) === false || !(Yii::$app->getComponent($this->db) instanceof Connection)) { if (Yii::$app->hasComponent($this->db) === false) {
$this->addError('db', 'Database Connection ID must refer to a valid application component.'); $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() 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) { if ($path === false) {
$this->addError('ns', 'Namespace must be associated with an existing directory.'); $this->addError('ns', 'Namespace must be associated with an existing directory.');
} }
...@@ -400,14 +413,18 @@ class Generator extends \yii\gii\Generator ...@@ -400,14 +413,18 @@ class Generator extends \yii\gii\Generator
public function validateTableName() 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(); $tables = $this->getTableNames();
if (empty($tables)) { if (empty($tables)) {
$this->addError('tableName', "Table '{$this->tableName}' does not exist.'"); $this->addError('tableName', "Table '{$this->tableName}' does not exist.");
} else { } else {
foreach ($tables as $table) { foreach ($tables as $table) {
$class = $this->generateClassName($table); $class = $this->generateClassName($table);
if ($this->isReservedKeyword($class)) { 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; break;
} }
} }
...@@ -418,13 +435,13 @@ class Generator extends \yii\gii\Generator ...@@ -418,13 +435,13 @@ class Generator extends \yii\gii\Generator
{ {
$db = $this->getDbConnection(); $db = $this->getDbConnection();
$tableNames = array(); $tableNames = array();
if ($this->tableName[strlen($this->tableName) - 1] === '*') { if (strpos($this->tableName, '*') !== false) {
if (($pos = strrpos($this->tableName, '.')) !== false) { if (($pos = strrpos($this->tableName, '.')) !== false) {
$schema = substr($this->tableName, 0, $pos); $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 { } else {
$schema = ''; $schema = '';
$pattern = '/' . str_replace('*', '\w+', $this->tableName) . '/'; $pattern = '/^' . str_replace('*', '\w+', $this->tableName) . '$/';
} }
foreach ($db->schema->getTableNames($schema) as $table) { foreach ($db->schema->getTableNames($schema) as $table) {
......
...@@ -17,14 +17,10 @@ ...@@ -17,14 +17,10 @@
* - $relations: list of relations (name=>relation declaration) * - $relations: list of relations (name=>relation declaration)
*/ */
$pos = strrpos($className, '\\');
$ns = ltrim(substr($className, 0, $pos), '\\');
$className = substr($className, $pos + 1);
echo "<?php\n"; echo "<?php\n";
?> ?>
namespace <?php echo $ns; ?>; namespace <?php echo $generator->ns; ?>;
/** /**
* This is the model class for table "<?php echo $tableName; ?>". * This is the model class for table "<?php echo $tableName; ?>".
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment