Alexander Makarov
13 years ago
10 changed files with 1033 additions and 0 deletions
@ -0,0 +1,181 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* Console Application class file. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright © 2008-2012 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\console; |
||||||
|
|
||||||
|
/** |
||||||
|
* \yii\console\Application represents a console application. |
||||||
|
* |
||||||
|
* \yii\console\Application extends {@link \yii\base\Application} by providing functionalities |
||||||
|
* specific to console requests. In particular, it deals with console requests |
||||||
|
* through a command-based approach: |
||||||
|
* <ul> |
||||||
|
* <li>A console application consists of one or several possible user commands;</li> |
||||||
|
* <li>Each user command is implemented as a class extending {@link \yii\console\Command};</li> |
||||||
|
* <li>User specifies which command to run on the command line;</li> |
||||||
|
* <li>The command processes the user request with the specified parameters.</li> |
||||||
|
* </ul> |
||||||
|
* |
||||||
|
* The command classes reside in the directory {@link getCommandPath commandPath}. |
||||||
|
* The name of the class follows the pattern: <command-name>Command, and its |
||||||
|
* file name is the same the class name. For example, the 'ShellCommand' class defines |
||||||
|
* a 'shell' command and the class file name is 'ShellCommand.php'. |
||||||
|
* |
||||||
|
* To run the console application, enter the following on the command line: |
||||||
|
* <pre> |
||||||
|
* php path/to/entry_script.php <command name> [param 1] [param 2] ... |
||||||
|
* </pre> |
||||||
|
* |
||||||
|
* You may use the following to see help instructions about a command: |
||||||
|
* <pre> |
||||||
|
* php path/to/entry_script.php help <command name> |
||||||
|
* </pre> |
||||||
|
* |
||||||
|
* @property string $commandPath The directory that contains the command classes. Defaults to 'protected/commands'. |
||||||
|
* @property CommandRunner $commandRunner The command runner. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class Application extends \yii\base\Application |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @var array mapping from command name to command configurations. |
||||||
|
* Each command configuration can be either a string or an array. |
||||||
|
* If the former, the string should be the file path of the command class. |
||||||
|
* If the latter, the array must contain a 'class' element which specifies |
||||||
|
* the command's class name or {@link \YiiBase::getPathOfAlias class path alias}. |
||||||
|
* The rest name-value pairs in the array are used to initialize |
||||||
|
* the corresponding command properties. For example, |
||||||
|
* <pre> |
||||||
|
* array( |
||||||
|
* 'email'=>array( |
||||||
|
* 'class'=>'path.to.Mailer', |
||||||
|
* 'interval'=>3600, |
||||||
|
* ), |
||||||
|
* 'log'=>'path/to/LoggerCommand.php', |
||||||
|
* ) |
||||||
|
* </pre> |
||||||
|
*/ |
||||||
|
public $commandMap=array(); |
||||||
|
|
||||||
|
private $_commandPath; |
||||||
|
|
||||||
|
/** |
||||||
|
* @var \yii\console\CommandRunner |
||||||
|
*/ |
||||||
|
private $_runner; |
||||||
|
|
||||||
|
/** |
||||||
|
* Initializes the application by creating the command runner. |
||||||
|
*/ |
||||||
|
public function init() |
||||||
|
{ |
||||||
|
if(!isset($_SERVER['argv'])) |
||||||
|
{ |
||||||
|
die('This script must be run from the command line.'); |
||||||
|
} |
||||||
|
$this->_runner=$this->createCommandRunner(); |
||||||
|
$this->_runner->commands=$this->commandMap; |
||||||
|
$this->_runner->addCommands($this->getCommandPath()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Processes the user request. |
||||||
|
* This method creates a console command runner to handle the particular user command. |
||||||
|
*/ |
||||||
|
public function processRequest() |
||||||
|
{ |
||||||
|
$this->_runner->run($_SERVER['argv']); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates the command runner instance. |
||||||
|
* @return CommandRunner the command runner |
||||||
|
*/ |
||||||
|
protected function createCommandRunner() |
||||||
|
{ |
||||||
|
return new CommandRunner(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Displays the captured PHP error. |
||||||
|
* This method displays the error in console mode when there is |
||||||
|
* no active error handler. |
||||||
|
* @param integer $code error code |
||||||
|
* @param string $message error message |
||||||
|
* @param string $file error file |
||||||
|
* @param string $line error line |
||||||
|
*/ |
||||||
|
public function displayError($code,$message,$file,$line) |
||||||
|
{ |
||||||
|
echo "PHP Error[$code]: $message\n"; |
||||||
|
echo " in file $file at line $line\n"; |
||||||
|
$trace=debug_backtrace(); |
||||||
|
// skip the first 4 stacks as they do not tell the error position |
||||||
|
if(count($trace)>4) |
||||||
|
$trace=array_slice($trace,4); |
||||||
|
foreach($trace as $i=>$t) |
||||||
|
{ |
||||||
|
if(!isset($t['file'])) |
||||||
|
$t['file']='unknown'; |
||||||
|
if(!isset($t['line'])) |
||||||
|
$t['line']=0; |
||||||
|
if(!isset($t['function'])) |
||||||
|
$t['function']='unknown'; |
||||||
|
echo "#$i {$t['file']}({$t['line']}): "; |
||||||
|
if(isset($t['object']) && is_object($t['object'])) |
||||||
|
echo get_class($t['object']).'->'; |
||||||
|
echo "{$t['function']}()\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Displays the uncaught PHP exception. |
||||||
|
* This method displays the exception in console mode when there is |
||||||
|
* no active error handler. |
||||||
|
* @param Exception $exception the uncaught exception |
||||||
|
*/ |
||||||
|
public function displayException($exception) |
||||||
|
{ |
||||||
|
echo $exception; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return string the directory that contains the command classes. Defaults to 'protected/commands'. |
||||||
|
*/ |
||||||
|
public function getCommandPath() |
||||||
|
{ |
||||||
|
$applicationCommandPath = $this->getBasePath().DIRECTORY_SEPARATOR.'commands'; |
||||||
|
if($this->_commandPath===null && file_exists($applicationCommandPath)) |
||||||
|
$this->setCommandPath($applicationCommandPath); |
||||||
|
return $this->_commandPath; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param string $value the directory that contains the command classes. |
||||||
|
* @throws CException if the directory is invalid |
||||||
|
*/ |
||||||
|
public function setCommandPath($value) |
||||||
|
{ |
||||||
|
if(($this->_commandPath=realpath($value))===false || !is_dir($this->_commandPath)) |
||||||
|
throw new \yii\base\Exception(Yii::t('yii','The command path "{path}" is not a valid directory.', |
||||||
|
array('{path}'=>$value))); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the command runner. |
||||||
|
* @return CConsoleCommandRunner the command runner. |
||||||
|
*/ |
||||||
|
public function getCommandRunner() |
||||||
|
{ |
||||||
|
return $this->_runner; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,339 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* Command class file. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright © 2008-2011 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\console; |
||||||
|
|
||||||
|
/** |
||||||
|
* Command represents an executable console command. |
||||||
|
* |
||||||
|
* It works like {@link \yii\web\Controller} by parsing command line options and dispatching |
||||||
|
* the request to a specific action with appropriate option values. |
||||||
|
* |
||||||
|
* Users call a console command via the following command format: |
||||||
|
* <pre> |
||||||
|
* yiic CommandName ActionName --Option1=Value1 --Option2=Value2 ... |
||||||
|
* </pre> |
||||||
|
* |
||||||
|
* Child classes mainly needs to implement various action methods whose name must be |
||||||
|
* prefixed with "action". The parameters to an action method are considered as options |
||||||
|
* for that specific action. The action specified as {@link defaultAction} will be invoked |
||||||
|
* when a user does not specify the action name in his command. |
||||||
|
* |
||||||
|
* Options are bound to action parameters via parameter names. For example, the following |
||||||
|
* action method will allow us to run a command with <code>yiic sitemap --type=News</code>: |
||||||
|
* <pre> |
||||||
|
* class SitemapCommand { |
||||||
|
* public function actionIndex($type) { |
||||||
|
* .... |
||||||
|
* } |
||||||
|
* } |
||||||
|
* </pre> |
||||||
|
* |
||||||
|
* @property string $name The command name. |
||||||
|
* @property CommandRunner $commandRunner The command runner instance. |
||||||
|
* @property string $help The command description. Defaults to 'Usage: php entry-script.php command-name'. |
||||||
|
* @property array $optionHelp The command option help information. Each array element describes |
||||||
|
* the help information for a single action. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
abstract class Command extends \yii\base\Component |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @var string the name of the default action. Defaults to 'index'. |
||||||
|
*/ |
||||||
|
public $defaultAction='index'; |
||||||
|
|
||||||
|
private $_name; |
||||||
|
private $_runner; |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor. |
||||||
|
* @param string $name name of the command |
||||||
|
* @param CConsoleCommandRunner $runner the command runner |
||||||
|
*/ |
||||||
|
public function __construct($name,$runner) |
||||||
|
{ |
||||||
|
$this->_name=$name; |
||||||
|
$this->_runner=$runner; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Initializes the command object. |
||||||
|
* This method is invoked after a command object is created and initialized with configurations. |
||||||
|
* You may override this method to further customize the command before it executes. |
||||||
|
*/ |
||||||
|
public function init() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Executes the command. |
||||||
|
* The default implementation will parse the input parameters and |
||||||
|
* dispatch the command request to an appropriate action with the corresponding |
||||||
|
* option values |
||||||
|
* @param array $args command line parameters for this command. |
||||||
|
*/ |
||||||
|
public function run($args) |
||||||
|
{ |
||||||
|
list($action, $options, $args)=$this->resolveRequest($args); |
||||||
|
$methodName='action'.$action; |
||||||
|
if(!preg_match('/^\w+$/',$action) || !method_exists($this,$methodName)) |
||||||
|
$this->usageError("Unknown action: ".$action); |
||||||
|
|
||||||
|
$method=new \ReflectionMethod($this,$methodName); |
||||||
|
$params=array(); |
||||||
|
// named and unnamed options |
||||||
|
foreach($method->getParameters() as $param) |
||||||
|
{ |
||||||
|
$name=$param->getName(); |
||||||
|
if(isset($options[$name])) |
||||||
|
{ |
||||||
|
if($param->isArray()) |
||||||
|
$params[]=is_array($options[$name]) ? $options[$name] : array($options[$name]); |
||||||
|
else if(!is_array($options[$name])) |
||||||
|
$params[]=$options[$name]; |
||||||
|
else |
||||||
|
$this->usageError("Option --$name requires a scalar. Array is given."); |
||||||
|
} |
||||||
|
else if($name==='args') |
||||||
|
$params[]=$args; |
||||||
|
else if($param->isDefaultValueAvailable()) |
||||||
|
$params[]=$param->getDefaultValue(); |
||||||
|
else |
||||||
|
$this->usageError("Missing required option --$name."); |
||||||
|
unset($options[$name]); |
||||||
|
} |
||||||
|
|
||||||
|
// try global options |
||||||
|
if(!empty($options)) |
||||||
|
{ |
||||||
|
$class=new \ReflectionClass(get_class($this)); |
||||||
|
foreach($options as $name=>$value) |
||||||
|
{ |
||||||
|
if($class->hasProperty($name)) |
||||||
|
{ |
||||||
|
$property=$class->getProperty($name); |
||||||
|
if($property->isPublic() && !$property->isStatic()) |
||||||
|
{ |
||||||
|
$this->$name=$value; |
||||||
|
unset($options[$name]); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if(!empty($options)) |
||||||
|
$this->usageError("Unknown options: ".implode(', ',array_keys($options))); |
||||||
|
|
||||||
|
if($this->beforeAction($action,$params)) |
||||||
|
{ |
||||||
|
$method->invokeArgs($this,$params); |
||||||
|
$this->afterAction($action,$params); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This method is invoked right before an action is to be executed. |
||||||
|
* You may override this method to do last-minute preparation for the action. |
||||||
|
* @param string $action the action name |
||||||
|
* @param array $params the parameters to be passed to the action method. |
||||||
|
* @return boolean whether the action should be executed. |
||||||
|
*/ |
||||||
|
protected function beforeAction($action,$params) |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This method is invoked right after an action finishes execution. |
||||||
|
* You may override this method to do some postprocessing for the action. |
||||||
|
* @param string $action the action name |
||||||
|
* @param array $params the parameters to be passed to the action method. |
||||||
|
*/ |
||||||
|
protected function afterAction($action,$params) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Parses the command line arguments and determines which action to perform. |
||||||
|
* @param array $args command line arguments |
||||||
|
* @return array the action name, named options (name=>value), and unnamed options |
||||||
|
*/ |
||||||
|
protected function resolveRequest($args) |
||||||
|
{ |
||||||
|
$options=array(); // named parameters |
||||||
|
$params=array(); // unnamed parameters |
||||||
|
foreach($args as $arg) |
||||||
|
{ |
||||||
|
if(preg_match('/^--(\w+)(=(.*))?$/',$arg,$matches)) // an option |
||||||
|
{ |
||||||
|
$name=$matches[1]; |
||||||
|
$value=isset($matches[3]) ? $matches[3] : true; |
||||||
|
if(isset($options[$name])) |
||||||
|
{ |
||||||
|
if(!is_array($options[$name])) |
||||||
|
$options[$name]=array($options[$name]); |
||||||
|
$options[$name][]=$value; |
||||||
|
} |
||||||
|
else |
||||||
|
$options[$name]=$value; |
||||||
|
} |
||||||
|
else if(isset($action)) |
||||||
|
$params[]=$arg; |
||||||
|
else |
||||||
|
$action=$arg; |
||||||
|
} |
||||||
|
if(!isset($action)) |
||||||
|
$action=$this->defaultAction; |
||||||
|
|
||||||
|
return array($action,$options,$params); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return string the command name. |
||||||
|
*/ |
||||||
|
public function getName() |
||||||
|
{ |
||||||
|
return $this->_name; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return \yii\console\CommandRunner the command runner instance |
||||||
|
*/ |
||||||
|
public function getCommandRunner() |
||||||
|
{ |
||||||
|
return $this->_runner; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Provides the command description. |
||||||
|
* This method may be overridden to return the actual command description. |
||||||
|
* @return string the command description. Defaults to 'Usage: php entry-script.php command-name'. |
||||||
|
*/ |
||||||
|
public function getHelp() |
||||||
|
{ |
||||||
|
$help='Usage: '.$this->getCommandRunner()->getScriptName().' '.$this->getName(); |
||||||
|
$options=$this->getOptionHelp(); |
||||||
|
if(empty($options)) |
||||||
|
return $help; |
||||||
|
if(count($options)===1) |
||||||
|
return $help.' '.$options[0]; |
||||||
|
$help.=" <action>\nActions:\n"; |
||||||
|
foreach($options as $option) |
||||||
|
$help.=' '.$option."\n"; |
||||||
|
return $help; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Provides the command option help information. |
||||||
|
* The default implementation will return all available actions together with their |
||||||
|
* corresponding option information. |
||||||
|
* @return array the command option help information. Each array element describes |
||||||
|
* the help information for a single action. |
||||||
|
*/ |
||||||
|
public function getOptionHelp() |
||||||
|
{ |
||||||
|
$options=array(); |
||||||
|
$class=new \ReflectionClass(get_class($this)); |
||||||
|
foreach($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) |
||||||
|
{ |
||||||
|
$name=$method->getName(); |
||||||
|
if(!strncasecmp($name,'action',6) && strlen($name)>6) |
||||||
|
{ |
||||||
|
$name=substr($name,6); |
||||||
|
$name[0]=strtolower($name[0]); |
||||||
|
$help=$name; |
||||||
|
|
||||||
|
foreach($method->getParameters() as $param) |
||||||
|
{ |
||||||
|
$optional=$param->isDefaultValueAvailable(); |
||||||
|
$defaultValue=$optional ? $param->getDefaultValue() : null; |
||||||
|
$name=$param->getName(); |
||||||
|
if($optional) |
||||||
|
$help.=" [--$name=$defaultValue]"; |
||||||
|
else |
||||||
|
$help.=" --$name=value"; |
||||||
|
} |
||||||
|
$options[]=$help; |
||||||
|
} |
||||||
|
} |
||||||
|
return $options; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Displays a usage error. |
||||||
|
* This method will then terminate the execution of the current application. |
||||||
|
* @param string $message the error message |
||||||
|
*/ |
||||||
|
public function usageError($message) |
||||||
|
{ |
||||||
|
echo "Error: $message\n\n".$this->getHelp()."\n"; |
||||||
|
exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Renders a view file. |
||||||
|
* @param string $_viewFile_ view file path |
||||||
|
* @param array $_data_ optional data to be extracted as local view variables |
||||||
|
* @param boolean $_return_ whether to return the rendering result instead of displaying it |
||||||
|
* @return mixed the rendering result if required. Null otherwise. |
||||||
|
*/ |
||||||
|
public function renderFile($_viewFile_,$_data_=null,$_return_=false) |
||||||
|
{ |
||||||
|
if(is_array($_data_)) |
||||||
|
extract($_data_,EXTR_PREFIX_SAME,'data'); |
||||||
|
else |
||||||
|
$data=$_data_; |
||||||
|
if($_return_) |
||||||
|
{ |
||||||
|
ob_start(); |
||||||
|
ob_implicit_flush(false); |
||||||
|
require($_viewFile_); |
||||||
|
return ob_get_clean(); |
||||||
|
} |
||||||
|
else |
||||||
|
require($_viewFile_); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 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 |
||||||
|
* @return mixed line read as a string, or false if input has been closed |
||||||
|
*/ |
||||||
|
public function prompt($message) |
||||||
|
{ |
||||||
|
if(extension_loaded('readline')) |
||||||
|
{ |
||||||
|
$input = readline($message.' '); |
||||||
|
readline_add_history($input); |
||||||
|
return $input; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
echo $message.' '; |
||||||
|
return trim(fgets(STDIN)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Asks user to confirm by typing y or n. |
||||||
|
* |
||||||
|
* @param string $message to echo out before waiting for user input |
||||||
|
* @return bool if user confirmed |
||||||
|
*/ |
||||||
|
public function confirm($message) |
||||||
|
{ |
||||||
|
echo $message.' [yes|no] '; |
||||||
|
return !strncasecmp(trim(fgets(STDIN)),'y',1); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,144 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* CConsoleCommandRunner class file. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright © 2008-2011 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\console; |
||||||
|
|
||||||
|
/** |
||||||
|
* CConsoleCommandRunner manages commands and executes the requested command. |
||||||
|
* |
||||||
|
* @property string $scriptName The entry script name. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @version $Id: CConsoleCommandRunner.php 3426 2011-10-25 00:01:09Z alexander.makarow $ |
||||||
|
* @package system.console |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class CommandRunner extends \yii\base\Component |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @var array list of all available commands (command name=>command configuration). |
||||||
|
* Each command configuration can be either a string or an array. |
||||||
|
* If the former, the string should be the class name or |
||||||
|
* {@link YiiBase::getPathOfAlias class path alias} of the command. |
||||||
|
* If the latter, the array must contain a 'class' element which specifies |
||||||
|
* the command's class name or {@link YiiBase::getPathOfAlias class path alias}. |
||||||
|
* The rest name-value pairs in the array are used to initialize |
||||||
|
* the corresponding command properties. For example, |
||||||
|
* <pre> |
||||||
|
* array( |
||||||
|
* 'email'=>array( |
||||||
|
* 'class'=>'path.to.Mailer', |
||||||
|
* 'interval'=>3600, |
||||||
|
* ), |
||||||
|
* 'log'=>'path.to.LoggerCommand', |
||||||
|
* ) |
||||||
|
* </pre> |
||||||
|
*/ |
||||||
|
public $commands=array(); |
||||||
|
|
||||||
|
private $_scriptName; |
||||||
|
|
||||||
|
/** |
||||||
|
* Executes the requested command. |
||||||
|
* @param array $args list of user supplied parameters (including the entry script name and the command name). |
||||||
|
*/ |
||||||
|
public function run($args) |
||||||
|
{ |
||||||
|
$this->_scriptName=$args[0]; |
||||||
|
array_shift($args); |
||||||
|
if(isset($args[0])) |
||||||
|
{ |
||||||
|
$name=$args[0]; |
||||||
|
array_shift($args); |
||||||
|
} |
||||||
|
else |
||||||
|
$name='help'; |
||||||
|
|
||||||
|
if(($command=$this->createCommand($name))===null) |
||||||
|
$command=$this->createCommand('help'); |
||||||
|
$command->init(); |
||||||
|
$command->run($args); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return string the entry script name |
||||||
|
*/ |
||||||
|
public function getScriptName() |
||||||
|
{ |
||||||
|
return $this->_scriptName; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Searches for commands under the specified directory. |
||||||
|
* @param string $path the directory containing the command class files. |
||||||
|
* @return array list of commands (command name=>command class file) |
||||||
|
*/ |
||||||
|
public function findCommands($path) |
||||||
|
{ |
||||||
|
if(($dir=@opendir($path))===false) |
||||||
|
return array(); |
||||||
|
$commands=array(); |
||||||
|
while(($name=readdir($dir))!==false) |
||||||
|
{ |
||||||
|
$file=$path.DIRECTORY_SEPARATOR.$name; |
||||||
|
if(!strcasecmp(substr($name,-11),'Command.php') && is_file($file)) |
||||||
|
$commands[strtolower(substr($name,0,-11))]=$file; |
||||||
|
} |
||||||
|
closedir($dir); |
||||||
|
return $commands; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Adds commands from the specified command path. |
||||||
|
* If a command already exists, the new one will be ignored. |
||||||
|
* @param string $path the alias of the directory containing the command class files. |
||||||
|
*/ |
||||||
|
public function addCommands($path) |
||||||
|
{ |
||||||
|
if(($commands=$this->findCommands($path))!==array()) |
||||||
|
{ |
||||||
|
foreach($commands as $name=>$file) |
||||||
|
{ |
||||||
|
if(!isset($this->commands[$name])) |
||||||
|
$this->commands[$name]=$file; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param string $name command name (case-insensitive) |
||||||
|
* @return \yii\console\Command the command object. Null if the name is invalid. |
||||||
|
*/ |
||||||
|
public function createCommand($name) |
||||||
|
{ |
||||||
|
$name=strtolower($name); |
||||||
|
if(isset($this->commands[$name])) |
||||||
|
{ |
||||||
|
if(is_string($this->commands[$name])) // class file path or alias |
||||||
|
{ |
||||||
|
if(strpos($this->commands[$name],'/')!==false || strpos($this->commands[$name],'\\')!==false) |
||||||
|
{ |
||||||
|
$className=substr(basename($this->commands[$name]),0,-4); |
||||||
|
if(!class_exists($className,false)) |
||||||
|
require_once($this->commands[$name]); |
||||||
|
} |
||||||
|
else // an alias |
||||||
|
$className=\Yii::import($this->commands[$name]); |
||||||
|
return new $className($name,$this); |
||||||
|
} |
||||||
|
else // an array configuration |
||||||
|
return \Yii::create($this->commands[$name],$name,$this); |
||||||
|
} |
||||||
|
else if($name==='help') |
||||||
|
return new HelpCommand('help',$this); |
||||||
|
else |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,79 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* CHelpCommand class file. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright © 2008-2011 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\console; |
||||||
|
|
||||||
|
/** |
||||||
|
* CHelpCommand represents a console help command. |
||||||
|
* |
||||||
|
* CHelpCommand displays the available command list or the help instructions |
||||||
|
* about a specific command. |
||||||
|
* |
||||||
|
* To use this command, enter the following on the command line: |
||||||
|
* <pre> |
||||||
|
* php path/to/entry_script.php help [command name] |
||||||
|
* </pre> |
||||||
|
* In the above, if the command name is not provided, it will display all |
||||||
|
* available commands. |
||||||
|
* |
||||||
|
* @property string $help The command description. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @version $Id: CHelpCommand.php 3426 2011-10-25 00:01:09Z alexander.makarow $ |
||||||
|
* @package system.console |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class HelpCommand extends Command |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Execute the action. |
||||||
|
* @param array $args command line parameters specific for this command |
||||||
|
*/ |
||||||
|
public function run($args) |
||||||
|
{ |
||||||
|
$runner=$this->getCommandRunner(); |
||||||
|
$commands=$runner->commands; |
||||||
|
if(isset($args[0])) |
||||||
|
{ |
||||||
|
$name=strtolower($args[0]); |
||||||
|
} |
||||||
|
if(!isset($args[0]) || !isset($commands[$name])) |
||||||
|
{ |
||||||
|
if(!empty($commands)) |
||||||
|
{ |
||||||
|
echo "Yii command runner (based on Yii v".\Yii::getVersion().")\n"; |
||||||
|
echo "Usage: ".$runner->getScriptName()." <command-name> [parameters...]\n"; |
||||||
|
echo "\nThe following commands are available:\n"; |
||||||
|
$commandNames=array_keys($commands); |
||||||
|
sort($commandNames); |
||||||
|
echo ' - '.implode("\n - ",$commandNames); |
||||||
|
echo "\n\nTo see individual command help, use the following:\n"; |
||||||
|
echo " ".$runner->getScriptName()." help <command-name>\n"; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
echo "No available commands.\n"; |
||||||
|
echo "Please define them under the following directory:\n"; |
||||||
|
echo "\t".\Yii::$app->getCommandPath()."\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
echo $runner->createCommand($name)->getHelp(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Provides the command description. |
||||||
|
* @return string the command description. |
||||||
|
*/ |
||||||
|
public function getHelp() |
||||||
|
{ |
||||||
|
return parent::getHelp().' [command-name]'; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,141 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* Filesystem helper class file. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @author Alex Makarov <sam@rmcreative.ru> |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright © 2008-2012 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\util; |
||||||
|
|
||||||
|
/** |
||||||
|
* Filesystem helper |
||||||
|
* |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class File |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Copies a list of files from one place to another. |
||||||
|
* @param array $fileList the list of files to be copied (name=>spec). |
||||||
|
* The array keys are names displayed during the copy process, and array values are specifications |
||||||
|
* for files to be copied. Each array value must be an array of the following structure: |
||||||
|
* <ul> |
||||||
|
* <li>source: required, the full path of the file/directory to be copied from</li> |
||||||
|
* <li>target: required, the full path of the file/directory to be copied to</li> |
||||||
|
* <li>callback: optional, the callback to be invoked when copying a file. The callback function |
||||||
|
* should be declared as follows: |
||||||
|
* <pre> |
||||||
|
* function foo($source,$params) |
||||||
|
* </pre> |
||||||
|
* where $source parameter is the source file path, and the content returned |
||||||
|
* by the function will be saved into the target file.</li> |
||||||
|
* <li>params: optional, the parameters to be passed to the callback</li> |
||||||
|
* </ul> |
||||||
|
* @see buildFileList |
||||||
|
*/ |
||||||
|
public function copyFiles($fileList) |
||||||
|
{ |
||||||
|
$overwriteAll=false; |
||||||
|
foreach($fileList as $name=>$file) |
||||||
|
{ |
||||||
|
$source=strtr($file['source'],'/\\',DIRECTORY_SEPARATOR); |
||||||
|
$target=strtr($file['target'],'/\\',DIRECTORY_SEPARATOR); |
||||||
|
$callback=isset($file['callback']) ? $file['callback'] : null; |
||||||
|
$params=isset($file['params']) ? $file['params'] : null; |
||||||
|
|
||||||
|
if(is_dir($source)) |
||||||
|
{ |
||||||
|
$this->ensureDirectory($target); |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
if($callback!==null) |
||||||
|
$content=call_user_func($callback,$source,$params); |
||||||
|
else |
||||||
|
$content=file_get_contents($source); |
||||||
|
if(is_file($target)) |
||||||
|
{ |
||||||
|
if($content===file_get_contents($target)) |
||||||
|
{ |
||||||
|
echo " unchanged $name\n"; |
||||||
|
continue; |
||||||
|
} |
||||||
|
if($overwriteAll) |
||||||
|
echo " overwrite $name\n"; |
||||||
|
else |
||||||
|
{ |
||||||
|
echo " exist $name\n"; |
||||||
|
echo " ...overwrite? [Yes|No|All|Quit] "; |
||||||
|
$answer=trim(fgets(STDIN)); |
||||||
|
if(!strncasecmp($answer,'q',1)) |
||||||
|
return; |
||||||
|
else if(!strncasecmp($answer,'y',1)) |
||||||
|
echo " overwrite $name\n"; |
||||||
|
else if(!strncasecmp($answer,'a',1)) |
||||||
|
{ |
||||||
|
echo " overwrite $name\n"; |
||||||
|
$overwriteAll=true; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
echo " skip $name\n"; |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
$this->ensureDirectory(dirname($target)); |
||||||
|
echo " generate $name\n"; |
||||||
|
} |
||||||
|
file_put_contents($target,$content); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Builds the file list of a directory. |
||||||
|
* This method traverses through the specified directory and builds |
||||||
|
* a list of files and subdirectories that the directory contains. |
||||||
|
* The result of this function can be passed to {@link copyFiles}. |
||||||
|
* @param string $sourceDir the source directory |
||||||
|
* @param string $targetDir the target directory |
||||||
|
* @param string $baseDir base directory |
||||||
|
* @return array the file list (see {@link copyFiles}) |
||||||
|
*/ |
||||||
|
public function buildFileList($sourceDir, $targetDir, $baseDir='') |
||||||
|
{ |
||||||
|
$list=array(); |
||||||
|
$handle=opendir($sourceDir); |
||||||
|
while(($file=readdir($handle))!==false) |
||||||
|
{ |
||||||
|
if($file==='.' || $file==='..' || $file==='.svn' ||$file==='.yii') |
||||||
|
continue; |
||||||
|
$sourcePath=$sourceDir.DIRECTORY_SEPARATOR.$file; |
||||||
|
$targetPath=$targetDir.DIRECTORY_SEPARATOR.$file; |
||||||
|
$name=$baseDir===''?$file : $baseDir.'/'.$file; |
||||||
|
$list[$name]=array('source'=>$sourcePath, 'target'=>$targetPath); |
||||||
|
if(is_dir($sourcePath)) |
||||||
|
$list=array_merge($list,$this->buildFileList($sourcePath,$targetPath,$name)); |
||||||
|
} |
||||||
|
closedir($handle); |
||||||
|
return $list; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates all parent directories if they do not exist. |
||||||
|
* @param string $directory the directory to be checked |
||||||
|
*/ |
||||||
|
public function ensureDirectory($directory) |
||||||
|
{ |
||||||
|
if(!is_dir($directory)) |
||||||
|
{ |
||||||
|
$this->ensureDirectory(dirname($directory)); |
||||||
|
echo " mkdir ".strtr($directory,'\\','/')."\n"; |
||||||
|
mkdir($directory); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* Text helper class file. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @author Alex Makarov <sam@rmcreative.ru> |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright © 2008-2012 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\util; |
||||||
|
|
||||||
|
/** |
||||||
|
* Text helper |
||||||
|
* |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class Text |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Converts a word to its plural form. |
||||||
|
* @param string $name the word to be pluralized |
||||||
|
* @return string the pluralized word |
||||||
|
*/ |
||||||
|
public function pluralize($name) |
||||||
|
{ |
||||||
|
$rules=array( |
||||||
|
'/(x|ch|ss|sh|us|as|is|os)$/i' => '\1es', |
||||||
|
'/(?:([^f])fe|([lr])f)$/i' => '\1\2ves', |
||||||
|
'/(m)an$/i' => '\1en', |
||||||
|
'/(child)$/i' => '\1ren', |
||||||
|
'/(r)y$/i' => '\1ies', |
||||||
|
'/s$/' => 's', |
||||||
|
); |
||||||
|
foreach($rules as $rule=>$replacement) |
||||||
|
{ |
||||||
|
if(preg_match($rule,$name)) |
||||||
|
return preg_replace($rule,$replacement,$name); |
||||||
|
} |
||||||
|
return $name.'s'; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* HttpException class file. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright © 2008-2012 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\web; |
||||||
|
|
||||||
|
/** |
||||||
|
* CHttpException represents an exception caused by invalid operations of end-users. |
||||||
|
* |
||||||
|
* The HTTP error code can be obtained via {@link statusCode}. |
||||||
|
* Error handlers may use this status code to decide how to format the error page. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class HttpException extends \yii\base\Exception |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @var integer HTTP status code, such as 403, 404, 500, etc. |
||||||
|
*/ |
||||||
|
public $statusCode; |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor. |
||||||
|
* @param integer $status HTTP status code, such as 404, 500, etc. |
||||||
|
* @param string $message error message |
||||||
|
* @param integer $code error code |
||||||
|
*/ |
||||||
|
public function __construct($status,$message=null,$code=0) |
||||||
|
{ |
||||||
|
$this->statusCode=$status; |
||||||
|
parent::__construct($message,$code); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
#!/usr/bin/env php |
||||||
|
<?php |
||||||
|
/** |
||||||
|
* Yii command line script for Unix/Linux. |
||||||
|
* |
||||||
|
* This is the bootstrap script for running yiic on Unix/Linux. |
||||||
|
* |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright © 2012 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
require_once(__DIR__.'/yiic.php'); |
@ -0,0 +1,22 @@ |
|||||||
|
@echo off |
||||||
|
|
||||||
|
rem ------------------------------------------------------------- |
||||||
|
rem Yii command line script for Windows. |
||||||
|
rem |
||||||
|
rem This is the bootstrap script for running yiic on Windows. |
||||||
|
rem |
||||||
|
rem @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
rem @link http://www.yiiframework.com/ |
||||||
|
rem @copyright Copyright © 2012 Yii Software LLC |
||||||
|
rem @license http://www.yiiframework.com/license/ |
||||||
|
rem ------------------------------------------------------------- |
||||||
|
|
||||||
|
@setlocal |
||||||
|
|
||||||
|
set YII_PATH=%~dp0 |
||||||
|
|
||||||
|
if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe |
||||||
|
|
||||||
|
"%PHP_COMMAND%" "%YII_PATH%yiic" %* |
||||||
|
|
||||||
|
@endlocal |
@ -0,0 +1,30 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* Yii console bootstrap file. |
||||||
|
* |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright © 2008-2012 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
// fcgi doesn't have STDIN defined by default |
||||||
|
defined('STDIN') or define('STDIN', fopen('php://stdin', 'r')); |
||||||
|
|
||||||
|
require(__DIR__.'/yii.php'); |
||||||
|
|
||||||
|
if(isset($config)) |
||||||
|
{ |
||||||
|
$app=new \yii\console\Application($config); |
||||||
|
$app->commandRunner->addCommands(YII_PATH.'/cli/commands'); |
||||||
|
$env=@getenv('YII_CONSOLE_COMMANDS'); |
||||||
|
if(!empty($env)) |
||||||
|
$app->commandRunner->addCommands($env); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
$app=new \yii\console\Application(array( |
||||||
|
'basePath'=>__DIR__.'/cli', |
||||||
|
)); |
||||||
|
} |
||||||
|
|
||||||
|
$app->run(); |
Loading…
Reference in new issue