1: <?php
2: /**
3: * CConsoleCommandRunner class file.
4: *
5: * @author Qiang Xue <qiang.xue@gmail.com>
6: * @link http://www.yiiframework.com/
7: * @copyright 2008-2013 Yii Software LLC
8: * @license http://www.yiiframework.com/license/
9: */
10:
11: /**
12: * CConsoleCommandRunner manages commands and executes the requested command.
13: *
14: * @property string $scriptName The entry script name.
15: * @property CConsoleCommand $command The currently active command.
16: *
17: * @author Qiang Xue <qiang.xue@gmail.com>
18: * @package system.console
19: * @since 1.0
20: */
21: class CConsoleCommandRunner extends CComponent
22: {
23: /**
24: * @var array list of all available commands (command name=>command configuration).
25: * Each command configuration can be either a string or an array.
26: * If the former, the string should be the class name or
27: * {@link YiiBase::getPathOfAlias class path alias} of the command.
28: * If the latter, the array must contain a 'class' element which specifies
29: * the command's class name or {@link YiiBase::getPathOfAlias class path alias}.
30: * The rest name-value pairs in the array are used to initialize
31: * the corresponding command properties. For example,
32: * <pre>
33: * array(
34: * 'email'=>array(
35: * 'class'=>'path.to.Mailer',
36: * 'interval'=>3600,
37: * ),
38: * 'log'=>'path.to.LoggerCommand',
39: * )
40: * </pre>
41: */
42: public $commands=array();
43:
44: private $_scriptName;
45: private $_command;
46:
47: /**
48: * Executes the requested command.
49: * @param array $args list of user supplied parameters (including the entry script name and the command name).
50: * @return integer|null application exit code returned by the command.
51: * if null is returned, application will not exit explicitly. See also {@link CConsoleApplication::processRequest()}.
52: * (return value is available since version 1.1.11)
53: */
54: public function run($args)
55: {
56: $this->_scriptName=$args[0];
57: array_shift($args);
58: if(isset($args[0]))
59: {
60: $name=$args[0];
61: array_shift($args);
62: }
63: else
64: $name='help';
65:
66: $oldCommand=$this->_command;
67: if(($command=$this->createCommand($name))===null)
68: $command=$this->createCommand('help');
69: $this->_command=$command;
70: $command->init();
71: $exitCode=$command->run($args);
72: $this->_command=$oldCommand;
73: return $exitCode;
74: }
75:
76: /**
77: * @return string the entry script name
78: */
79: public function getScriptName()
80: {
81: return $this->_scriptName;
82: }
83:
84: /**
85: * Returns the currently running command.
86: * @return CConsoleCommand|null the currently active command.
87: * @since 1.1.14
88: */
89: public function getCommand()
90: {
91: return $this->_command;
92: }
93:
94: /**
95: * @param CConsoleCommand $value the currently active command.
96: * @since 1.1.14
97: */
98: public function setCommand($value)
99: {
100: $this->_command=$value;
101: }
102:
103: /**
104: * Searches for commands under the specified directory.
105: * @param string $path the directory containing the command class files.
106: * @return array list of commands (command name=>command class file)
107: */
108: public function findCommands($path)
109: {
110: if(($dir=@opendir($path))===false)
111: return array();
112: $commands=array();
113: while(($name=readdir($dir))!==false)
114: {
115: $file=$path.DIRECTORY_SEPARATOR.$name;
116: if(!strcasecmp(substr($name,-11),'Command.php') && is_file($file))
117: $commands[strtolower(substr($name,0,-11))]=$file;
118: }
119: closedir($dir);
120: return $commands;
121: }
122:
123: /**
124: * Adds commands from the specified command path.
125: * If a command already exists, the new one will be ignored.
126: * @param string $path the alias of the directory containing the command class files.
127: */
128: public function addCommands($path)
129: {
130: if(($commands=$this->findCommands($path))!==array())
131: {
132: foreach($commands as $name=>$file)
133: {
134: if(!isset($this->commands[$name]))
135: $this->commands[$name]=$file;
136: }
137: }
138: }
139:
140: /**
141: * @param string $name command name (case-insensitive)
142: * @return CConsoleCommand the command object. Null if the name is invalid.
143: */
144: public function createCommand($name)
145: {
146: $name=strtolower($name);
147:
148: $command=null;
149: if(isset($this->commands[$name]))
150: $command=$this->commands[$name];
151: else
152: {
153: $commands=array_change_key_case($this->commands);
154: if(isset($commands[$name]))
155: $command=$commands[$name];
156: }
157:
158: if($command!==null)
159: {
160: if(is_string($command)) // class file path or alias
161: {
162: if(strpos($command,'/')!==false || strpos($command,'\\')!==false)
163: {
164: $className=substr(basename($command),0,-4);
165: if(!class_exists($className,false))
166: require_once($command);
167: }
168: else // an alias
169: $className=Yii::import($command);
170: return new $className($name,$this);
171: }
172: else // an array configuration
173: return Yii::createComponent($command,$name,$this);
174: }
175: elseif($name==='help')
176: return new CHelpCommand('help',$this);
177: else
178: return null;
179: }
180: }