Browse Source

console app cleanup.

tags/2.0.0-beta
Qiang Xue 12 years ago
parent
commit
5b357d2eed
  1. 59
      framework/console/Controller.php
  2. 139
      framework/console/controllers/MigrateController.php
  3. 149
      framework/console/controllers/ShellController.php

59
framework/console/Controller.php

@ -32,6 +32,12 @@ use yii\base\InvalidRouteException;
class Controller extends \yii\base\Controller class Controller extends \yii\base\Controller
{ {
/** /**
* @var boolean whether the call of [[confirm()]] requires a user input.
* If false, [[confirm()]] will always return true no matter what user enters or not.
*/
public $interactive = true;
/**
* Runs an action with the specified action ID and parameters. * Runs an action with the specified action ID and parameters.
* If the action ID is empty, the method will use [[defaultAction]]. * If the action ID is empty, the method will use [[defaultAction]].
* @param string $id the ID of the action to be executed. * @param string $id the ID of the action to be executed.
@ -80,43 +86,6 @@ class Controller extends \yii\base\Controller
} }
/** /**
* Reads input via the readline PHP extension if that's available, or fgets() if readline is not installed.
*
* @param string $message to echo out before waiting for user input
* @param string $default the default string to be returned when user does not write anything.
* Defaults to null, means that default string is disabled.
* @return mixed line read as a string, or false if input has been closed
*/
public function prompt($message, $default = null)
{
if($default !== null) {
$message .= " [$default] ";
}
else {
$message .= ' ';
}
if(extension_loaded('readline')) {
$input = readline($message);
if($input !== false) {
readline_add_history($input);
}
}
else {
echo $message;
$input = fgets(STDIN);
}
if($input === false) {
return false;
}
else {
$input = trim($input);
return ($input === '' && $default !== null) ? $default : $input;
}
}
/**
* Asks user to confirm by typing y or n. * Asks user to confirm by typing y or n.
* *
* @param string $message to echo out before waiting for user input * @param string $message to echo out before waiting for user input
@ -125,9 +94,23 @@ class Controller extends \yii\base\Controller
*/ */
public function confirm($message, $default = false) public function confirm($message, $default = false)
{ {
if ($this->interactive) {
echo $message . ' (yes|no) [' . ($default ? 'yes' : 'no') . ']:'; echo $message . ' (yes|no) [' . ($default ? 'yes' : 'no') . ']:';
$input = trim(fgets(STDIN)); $input = trim(fgets(STDIN));
return empty($input) ? $default : !strncasecmp($input, 'y', 1); return empty($input) ? $default : !strncasecmp($input, 'y', 1);
} else {
return true;
}
}
public function error($message)
{
echo "\nError: $message\n";
Yii::$application->end(1);
}
public function globalOptions()
{
return array();
} }
} }

139
framework/console/controllers/MigrateController.php

@ -10,6 +10,7 @@
namespace yii\console\controllers; namespace yii\console\controllers;
use Yii;
use yii\console\Controller; use yii\console\Controller;
/** /**
@ -67,7 +68,7 @@ class MigrateController extends Controller
* in terms of a path alias, and the corresponding directory must exist. * in terms of a path alias, and the corresponding directory must exist.
* Defaults to 'application.migrations' (meaning 'protected/migrations'). * Defaults to 'application.migrations' (meaning 'protected/migrations').
*/ */
public $migrationPath='application.migrations'; public $migrationPath = '@application/migrations';
/** /**
* @var string the name of the table for keeping applied migration information. * @var string the name of the table for keeping applied migration information.
* This table will be automatically created if not exists. Defaults to 'tbl_migration'. * This table will be automatically created if not exists. Defaults to 'tbl_migration'.
@ -95,16 +96,17 @@ class MigrateController extends Controller
*/ */
public $interactive = true; public $interactive = true;
public function beforeAction($action) public function beforeAction($action)
{ {
$path = \Yii::getAlias($this->migrationPath); $path = Yii::getAlias($this->migrationPath);
if ($path === false || !is_dir($path)) { if ($path === false || !is_dir($path)) {
echo 'Error: The migration directory does not exist: ' . $this->migrationPath . "\n"; echo 'Error: the migration directory does not exist "' . $this->migrationPath . "\"\n";
\Yii::$application->end(1); return false;
} }
$this->migrationPath = $path; $this->migrationPath = $path;
$yiiVersion = \Yii::getVersion(); $yiiVersion = Yii::getVersion();
echo "\nYii Migration Tool v2.0 (based on Yii v{$yiiVersion})\n\n"; echo "\nYii Migration Tool v2.0 (based on Yii v{$yiiVersion})\n\n";
return parent::beforeAction($action); return parent::beforeAction($action);
@ -115,10 +117,9 @@ class MigrateController extends Controller
*/ */
public function actionUp($args) public function actionUp($args)
{ {
if(($migrations = $this->getNewMigrations())===array()) if (($migrations = $this->getNewMigrations()) === array()) {
{
echo "No new migration found. Your system is up-to-date.\n"; echo "No new migration found. Your system is up-to-date.\n";
\Yii::$application->end(); Yii::$application->end();
} }
$total = count($migrations); $total = count($migrations);
@ -131,18 +132,17 @@ class MigrateController extends Controller
if ($n === $total) if ($n === $total)
echo "Total $n new " . ($n === 1 ? 'migration' : 'migrations') . " to be applied:\n"; echo "Total $n new " . ($n === 1 ? 'migration' : 'migrations') . " to be applied:\n";
else else
{
echo "Total $n out of $total new " . ($total === 1 ? 'migration' : 'migrations') . " to be applied:\n"; echo "Total $n out of $total new " . ($total === 1 ? 'migration' : 'migrations') . " to be applied:\n";
}
foreach ($migrations as $migration) foreach ($migrations as $migration)
echo " $migration\n"; echo " $migration\n";
echo "\n"; echo "\n";
if($this->confirm('Apply the above '.($n===1 ? 'migration':'migrations')."?")) if ($this->confirm('Apply the above ' . ($n === 1 ? 'migration' : 'migrations') . "?")) {
{ foreach ($migrations as $migration) {
foreach($migrations as $migration) if ($this->migrateUp($migration) === false) {
{
if($this->migrateUp($migration)===false)
{
echo "\nMigration failed. All later migrations are canceled.\n"; echo "\nMigration failed. All later migrations are canceled.\n";
return; return;
} }
@ -157,8 +157,7 @@ class MigrateController extends Controller
if ($step < 1) if ($step < 1)
die("Error: The step parameter must be greater than 0.\n"); die("Error: The step parameter must be greater than 0.\n");
if(($migrations=$this->getMigrationHistory($step))===array()) if (($migrations = $this->getMigrationHistory($step)) === array()) {
{
echo "No migration has been done before.\n"; echo "No migration has been done before.\n";
return; return;
} }
@ -170,12 +169,9 @@ class MigrateController extends Controller
echo " $migration\n"; echo " $migration\n";
echo "\n"; echo "\n";
if($this->confirm('Revert the above '.($n===1 ? 'migration':'migrations')."?")) if ($this->confirm('Revert the above ' . ($n === 1 ? 'migration' : 'migrations') . "?")) {
{ foreach ($migrations as $migration) {
foreach($migrations as $migration) if ($this->migrateDown($migration) === false) {
{
if($this->migrateDown($migration)===false)
{
echo "\nMigration failed. All later migrations are canceled.\n"; echo "\nMigration failed. All later migrations are canceled.\n";
return; return;
} }
@ -190,8 +186,7 @@ class MigrateController extends Controller
if ($step < 1) if ($step < 1)
die("Error: The step parameter must be greater than 0.\n"); die("Error: The step parameter must be greater than 0.\n");
if(($migrations=$this->getMigrationHistory($step))===array()) if (($migrations = $this->getMigrationHistory($step)) === array()) {
{
echo "No migration has been done before.\n"; echo "No migration has been done before.\n";
return; return;
} }
@ -203,20 +198,15 @@ class MigrateController extends Controller
echo " $migration\n"; echo " $migration\n";
echo "\n"; echo "\n";
if($this->confirm('Redo the above '.($n===1 ? 'migration':'migrations')."?")) if ($this->confirm('Redo the above ' . ($n === 1 ? 'migration' : 'migrations') . "?")) {
{ foreach ($migrations as $migration) {
foreach($migrations as $migration) if ($this->migrateDown($migration) === false) {
{
if($this->migrateDown($migration)===false)
{
echo "\nMigration failed. All later migrations are canceled.\n"; echo "\nMigration failed. All later migrations are canceled.\n";
return; return;
} }
} }
foreach(array_reverse($migrations) as $migration) foreach (array_reverse($migrations) as $migration) {
{ if ($this->migrateUp($migration) === false) {
if($this->migrateUp($migration)===false)
{
echo "\nMigration failed. All later migrations are canceled.\n"; echo "\nMigration failed. All later migrations are canceled.\n";
return; return;
} }
@ -240,10 +230,8 @@ class MigrateController extends Controller
// try migrate up // try migrate up
$migrations = $this->getNewMigrations(); $migrations = $this->getNewMigrations();
foreach($migrations as $i=>$migration) foreach ($migrations as $i => $migration) {
{ if (strpos($migration, $version . '_') === 0) {
if(strpos($migration,$version.'_')===0)
{
$this->actionUp(array($i + 1)); $this->actionUp(array($i + 1));
return; return;
} }
@ -251,10 +239,8 @@ class MigrateController extends Controller
// try migrate down // try migrate down
$migrations = array_keys($this->getMigrationHistory(-1)); $migrations = array_keys($this->getMigrationHistory(-1));
foreach($migrations as $i=>$migration) foreach ($migrations as $i => $migration) {
{ if (strpos($migration, $version . '_') === 0) {
if(strpos($migration,$version.'_')===0)
{
if ($i === 0) if ($i === 0)
echo "Already at '$originalVersion'. Nothing needs to be done.\n"; echo "Already at '$originalVersion'. Nothing needs to be done.\n";
else else
@ -282,15 +268,11 @@ class MigrateController extends Controller
// try mark up // try mark up
$migrations = $this->getNewMigrations(); $migrations = $this->getNewMigrations();
foreach($migrations as $i=>$migration) foreach ($migrations as $i => $migration) {
{ if (strpos($migration, $version . '_') === 0) {
if(strpos($migration,$version.'_')===0) if ($this->confirm("Set migration history at $originalVersion?")) {
{
if($this->confirm("Set migration history at $originalVersion?"))
{
$command = $db->createCommand(); $command = $db->createCommand();
for($j=0;$j<=$i;++$j) for ($j = 0; $j <= $i; ++$j) {
{
$command->insert($this->migrationTable, array( $command->insert($this->migrationTable, array(
'version' => $migrations[$j], 'version' => $migrations[$j],
'apply_time' => time(), 'apply_time' => time(),
@ -304,16 +286,12 @@ class MigrateController extends Controller
// try mark down // try mark down
$migrations = array_keys($this->getMigrationHistory(-1)); $migrations = array_keys($this->getMigrationHistory(-1));
foreach($migrations as $i=>$migration) foreach ($migrations as $i => $migration) {
{ if (strpos($migration, $version . '_') === 0) {
if(strpos($migration,$version.'_')===0)
{
if ($i === 0) if ($i === 0)
echo "Already at '$originalVersion'. Nothing needs to be done.\n"; echo "Already at '$originalVersion'. Nothing needs to be done.\n";
else else {
{ if ($this->confirm("Set migration history at $originalVersion?")) {
if($this->confirm("Set migration history at $originalVersion?"))
{
$command = $db->createCommand(); $command = $db->createCommand();
for ($j = 0; $j < $i; ++$j) for ($j = 0; $j < $i; ++$j)
$command->delete($this->migrationTable, $db->quoteColumnName('version') . '=:version', array(':version' => $migrations[$j])); $command->delete($this->migrationTable, $db->quoteColumnName('version') . '=:version', array(':version' => $migrations[$j]));
@ -333,8 +311,7 @@ class MigrateController extends Controller
$migrations = $this->getMigrationHistory($limit); $migrations = $this->getMigrationHistory($limit);
if ($migrations === array()) if ($migrations === array())
echo "No migration has been done before.\n"; echo "No migration has been done before.\n";
else else {
{
$n = count($migrations); $n = count($migrations);
if ($limit > 0) if ($limit > 0)
echo "Showing the last $n applied " . ($n === 1 ? 'migration' : 'migrations') . ":\n"; echo "Showing the last $n applied " . ($n === 1 ? 'migration' : 'migrations') . ":\n";
@ -351,15 +328,12 @@ class MigrateController extends Controller
$migrations = $this->getNewMigrations(); $migrations = $this->getNewMigrations();
if ($migrations === array()) if ($migrations === array())
echo "No new migrations found. Your system is up-to-date.\n"; echo "No new migrations found. Your system is up-to-date.\n";
else else {
{
$n = count($migrations); $n = count($migrations);
if($limit>0 && $n>$limit) if ($limit > 0 && $n > $limit) {
{
$migrations = array_slice($migrations, 0, $limit); $migrations = array_slice($migrations, 0, $limit);
echo "Showing $limit out of $n new " . ($n === 1 ? 'migration' : 'migrations') . ":\n"; echo "Showing $limit out of $n new " . ($n === 1 ? 'migration' : 'migrations') . ":\n";
} } else
else
echo "Found $n new " . ($n === 1 ? 'migration' : 'migrations') . ":\n"; echo "Found $n new " . ($n === 1 ? 'migration' : 'migrations') . ":\n";
foreach ($migrations as $migration) foreach ($migrations as $migration)
@ -381,20 +355,12 @@ class MigrateController extends Controller
$content = strtr($this->getTemplate(), array('{ClassName}' => $name)); $content = strtr($this->getTemplate(), array('{ClassName}' => $name));
$file = $this->migrationPath . DIRECTORY_SEPARATOR . $name . '.php'; $file = $this->migrationPath . DIRECTORY_SEPARATOR . $name . '.php';
if($this->confirm("Create new migration '$file'?")) if ($this->confirm("Create new migration '$file'?")) {
{
file_put_contents($file, $content); file_put_contents($file, $content);
echo "New migration created successfully.\n"; echo "New migration created successfully.\n";
} }
} }
public function confirm($message)
{
if(!$this->interactive)
return true;
return parent::confirm($message);
}
protected function migrateUp($class) protected function migrateUp($class)
{ {
if ($class === self::BASE_MIGRATION) if ($class === self::BASE_MIGRATION)
@ -403,17 +369,14 @@ class MigrateController extends Controller
echo "*** applying $class\n"; echo "*** applying $class\n";
$start = microtime(true); $start = microtime(true);
$migration = $this->instantiateMigration($class); $migration = $this->instantiateMigration($class);
if($migration->up()!==false) if ($migration->up() !== false) {
{
$this->getDb()->createCommand()->insert($this->migrationTable, array( $this->getDb()->createCommand()->insert($this->migrationTable, array(
'version' => $class, 'version' => $class,
'apply_time' => time(), 'apply_time' => time(),
)); ));
$time = microtime(true) - $start; $time = microtime(true) - $start;
echo "*** applied $class (time: " . sprintf("%.3f", $time) . "s)\n\n"; echo "*** applied $class (time: " . sprintf("%.3f", $time) . "s)\n\n";
} } else {
else
{
$time = microtime(true) - $start; $time = microtime(true) - $start;
echo "*** failed to apply $class (time: " . sprintf("%.3f", $time) . "s)\n\n"; echo "*** failed to apply $class (time: " . sprintf("%.3f", $time) . "s)\n\n";
return false; return false;
@ -428,15 +391,12 @@ class MigrateController extends Controller
echo "*** reverting $class\n"; echo "*** reverting $class\n";
$start = microtime(true); $start = microtime(true);
$migration = $this->instantiateMigration($class); $migration = $this->instantiateMigration($class);
if($migration->down()!==false) if ($migration->down() !== false) {
{
$db = $this->getDb(); $db = $this->getDb();
$db->createCommand()->delete($this->migrationTable, $db->quoteColumnName('version') . '=:version', array(':version' => $class)); $db->createCommand()->delete($this->migrationTable, $db->quoteColumnName('version') . '=:version', array(':version' => $class));
$time = microtime(true) - $start; $time = microtime(true) - $start;
echo "*** reverted $class (time: " . sprintf("%.3f", $time) . "s)\n\n"; echo "*** reverted $class (time: " . sprintf("%.3f", $time) . "s)\n\n";
} } else {
else
{
$time = microtime(true) - $start; $time = microtime(true) - $start;
echo "*** failed to revert $class (time: " . sprintf("%.3f", $time) . "s)\n\n"; echo "*** failed to revert $class (time: " . sprintf("%.3f", $time) . "s)\n\n";
return false; return false;
@ -456,11 +416,12 @@ class MigrateController extends Controller
* @var CDbConnection * @var CDbConnection
*/ */
private $_db; private $_db;
protected function getDb() protected function getDb()
{ {
if ($this->_db !== null) if ($this->_db !== null)
return $this->_db; return $this->_db;
else if(($this->_db=\Yii::$application->getComponent($this->connectionID)) instanceof CDbConnection) else if (($this->_db = Yii::$application->getComponent($this->connectionID)) instanceof CDbConnection)
return $this->_db; return $this->_db;
else else
die("Error: CMigrationCommand.connectionID '{$this->connectionID}' is invalid. Please make sure it refers to the ID of a CDbConnection application component.\n"); die("Error: CMigrationCommand.connectionID '{$this->connectionID}' is invalid. Please make sure it refers to the ID of a CDbConnection application component.\n");
@ -469,8 +430,7 @@ class MigrateController extends Controller
protected function getMigrationHistory($limit) protected function getMigrationHistory($limit)
{ {
$db = $this->getDb(); $db = $this->getDb();
if($db->schema->getTable($this->migrationTable)===null) if ($db->schema->getTable($this->migrationTable) === null) {
{
$this->createMigrationHistoryTable(); $this->createMigrationHistoryTable();
} }
return CHtml::listData($db->createCommand() return CHtml::listData($db->createCommand()
@ -504,8 +464,7 @@ class MigrateController extends Controller
$migrations = array(); $migrations = array();
$handle = opendir($this->migrationPath); $handle = opendir($this->migrationPath);
while(($file=readdir($handle))!==false) while (($file = readdir($handle)) !== false) {
{
if ($file === '.' || $file === '..') if ($file === '.' || $file === '..')
continue; continue;
$path = $this->migrationPath . DIRECTORY_SEPARATOR . $file; $path = $this->migrationPath . DIRECTORY_SEPARATOR . $file;

149
framework/console/controllers/ShellController.php

@ -1,149 +0,0 @@
<?php
/**
* ShellController class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\console\controllers;
use yii\console\Controller;
/**
* This command executes the specified Web application and provides a shell for interaction.
*
* @property string $help The help information for the shell command.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class ShellController extends Controller
{
/**
* @return string the help information for the shell command
*/
public function getHelp()
{
return <<<EOD
USAGE
yiic shell [entry-script | config-file]
DESCRIPTION
This command allows you to interact with a Web application
on the command line. It also provides tools to automatically
generate new controllers, views and data models.
It is recommended that you execute this command under
the directory that contains the entry script file of
the Web application.
PARAMETERS
* entry-script | config-file: optional, the path to
the entry script file or the configuration file for
the Web application. If not given, it is assumed to be
the 'index.php' file under the current directory.
EOD;
}
/**
* Execute the action.
* @param array $args command line parameters specific for this command
*/
public function run($args)
{
if(!isset($args[0]))
$args[0]='index.php';
$entryScript=isset($args[0]) ? $args[0] : 'index.php';
if(($entryScript=realpath($args[0]))===false || !is_file($entryScript))
$this->usageError("{$args[0]} does not exist or is not an entry script file.");
// fake the web server setting
$cwd=getcwd();
chdir(dirname($entryScript));
$_SERVER['SCRIPT_NAME']='/'.basename($entryScript);
$_SERVER['REQUEST_URI']=$_SERVER['SCRIPT_NAME'];
$_SERVER['SCRIPT_FILENAME']=$entryScript;
$_SERVER['HTTP_HOST']='localhost';
$_SERVER['SERVER_NAME']='localhost';
$_SERVER['SERVER_PORT']=80;
// reset context to run the web application
restore_error_handler();
restore_exception_handler();
Yii::setApplication(null);
Yii::setPathOfAlias('application',null);
ob_start();
$config=require($entryScript);
ob_end_clean();
// oops, the entry script turns out to be a config file
if(is_array($config))
{
chdir($cwd);
$_SERVER['SCRIPT_NAME']='/index.php';
$_SERVER['REQUEST_URI']=$_SERVER['SCRIPT_NAME'];
$_SERVER['SCRIPT_FILENAME']=$cwd.DIRECTORY_SEPARATOR.'index.php';
Yii::createWebApplication($config);
}
restore_error_handler();
restore_exception_handler();
$yiiVersion=Yii::getVersion();
echo <<<EOD
Yii Interactive Tool v1.1 (based on Yii v{$yiiVersion})
Please type 'help' for help. Type 'exit' to quit.
EOD;
$this->runShell();
}
protected function runShell()
{
// disable E_NOTICE so that the shell is more friendly
error_reporting(E_ALL ^ E_NOTICE);
$_runner_=new CConsoleCommandRunner;
$_runner_->addCommands(dirname(__FILE__).'/shell');
$_runner_->addCommands(Yii::getPathOfAlias('application.commands.shell'));
if(($_path_=@getenv('YIIC_SHELL_COMMAND_PATH'))!==false)
$_runner_->addCommands($_path_);
$_commands_=$_runner_->commands;
$log=\Yii::$application->log;
while(($_line_=$this->prompt("\n>>"))!==false)
{
$_line_=trim($_line_);
if($_line_==='exit')
return;
try
{
$_args_=preg_split('/[\s,]+/',rtrim($_line_,';'),-1,PREG_SPLIT_NO_EMPTY);
if(isset($_args_[0]) && isset($_commands_[$_args_[0]]))
{
$_command_=$_runner_->createCommand($_args_[0]);
array_shift($_args_);
$_command_->init();
$_command_->run($_args_);
}
else
echo eval($_line_.';');
}
catch(Exception $e)
{
if($e instanceof ShellException)
echo $e->getMessage();
else
echo $e;
}
}
}
}
class ShellException extends CException
{
}
Loading…
Cancel
Save