CConsoleCommandRunner.php 4.6 KB

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