CommandListShell.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. /**
  3. * Command list Shell
  4. *
  5. * PHP 5
  6. *
  7. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  8. * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  9. *
  10. * Licensed under The MIT License
  11. * Redistributions of files must retain the above copyright notice.
  12. *
  13. * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14. * @link http://cakephp.org CakePHP Project
  15. * @package Cake.Console.Command
  16. * @since CakePHP v 2.0
  17. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  18. */
  19. App::uses('Inflector', 'Utility');
  20. /**
  21. * Shows a list of commands available from the console.
  22. *
  23. * @package Cake.Console.Command
  24. */
  25. class CommandListShell extends Shell {
  26. /**
  27. * startup
  28. *
  29. * @return void
  30. */
  31. public function startup() {
  32. if (empty($this->params['xml'])) {
  33. parent::startup();
  34. }
  35. }
  36. /**
  37. * Main function Prints out the list of shells.
  38. *
  39. * @return void
  40. */
  41. public function main() {
  42. if (empty($this->params['xml'])) {
  43. $this->out(__d('cake_console', "<info>Current Paths:</info>"), 2);
  44. $this->out(" -app: ". APP_DIR);
  45. $this->out(" -working: " . rtrim(APP, DS));
  46. $this->out(" -root: " . rtrim(ROOT, DS));
  47. $this->out(" -core: " . rtrim(CORE_PATH, DS));
  48. $this->out("");
  49. $this->out(__d('cake_console', "<info>Changing Paths:</info>"), 2);
  50. $this->out(__d('cake_console', "Your working path should be the same as your application path to change your path use the '-app' param."));
  51. $this->out(__d('cake_console', "Example: -app relative/path/to/myapp or -app /absolute/path/to/myapp"), 2);
  52. $this->out(__d('cake_console', "<info>Available Shells:</info>"), 2);
  53. }
  54. $shellList = $this->_getShellList();
  55. if ($shellList) {
  56. ksort($shellList);
  57. if (empty($this->params['xml'])) {
  58. if (!empty($this->params['sort'])) {
  59. $this->_asSorted($shellList);
  60. } else {
  61. $this->_asText($shellList);
  62. }
  63. } else {
  64. $this->_asXml($shellList);
  65. }
  66. }
  67. }
  68. /**
  69. * Gets the shell command listing.
  70. *
  71. * @return array
  72. */
  73. protected function _getShellList() {
  74. $shellList = array();
  75. $shells = App::objects('file', App::core('Console/Command'));
  76. $shellList = $this->_appendShells('CORE', $shells, $shellList);
  77. $appShells = App::objects('Console/Command', null, false);
  78. $appShells = array_diff($appShells, $shells);
  79. $shellList = $this->_appendShells('app', $appShells, $shellList);
  80. $plugins = CakePlugin::loaded();
  81. foreach ($plugins as $plugin) {
  82. $pluginShells = App::objects($plugin . '.Console/Command');
  83. $shellList = $this->_appendShells($plugin, $pluginShells, $shellList);
  84. }
  85. return $shellList;
  86. }
  87. /**
  88. * Scan the provided paths for shells, and append them into $shellList
  89. *
  90. * @param string $type
  91. * @param array $shells
  92. * @param array $shellList
  93. * @return array
  94. */
  95. protected function _appendShells($type, $shells, $shellList) {
  96. foreach ($shells as $shell) {
  97. $shell = Inflector::underscore(str_replace('Shell', '', $shell));
  98. $shellList[$shell][$type] = $type;
  99. }
  100. return $shellList;
  101. }
  102. /**
  103. * Output text.
  104. *
  105. * @param array $shellList
  106. * @return void
  107. */
  108. protected function _asText($shellList) {
  109. if (DS === '/') {
  110. $width = exec('tput cols') - 2;
  111. }
  112. if (empty($width)) {
  113. $width = 80;
  114. }
  115. $columns = max(1, floor($width / 30));
  116. $rows = ceil(count($shellList) / $columns);
  117. foreach ($shellList as $shell => $types) {
  118. sort($types);
  119. $shellList[$shell] = str_pad($shell . ' [' . implode ($types, ', ') . ']', $width / $columns);
  120. }
  121. $out = array_chunk($shellList, $rows);
  122. for ($i = 0; $i < $rows; $i++) {
  123. $row = '';
  124. for ($j = 0; $j < $columns; $j++) {
  125. if (!isset($out[$j][$i])) {
  126. continue;
  127. }
  128. $row .= $out[$j][$i];
  129. }
  130. $this->out(" " . $row);
  131. }
  132. $this->out();
  133. $this->out(__d('cake_console', "To run an app or core command, type <info>cake shell_name [args]</info>"));
  134. $this->out(__d('cake_console', "To run a plugin command, type <info>cake Plugin.shell_name [args]</info>"));
  135. $this->out(__d('cake_console', "To get help on a specific command, type <info>cake shell_name --help</info>"), 2);
  136. }
  137. /**
  138. * Generates the shell list sorted by where the shells are found.
  139. *
  140. * @param array $shellList
  141. * @return void
  142. */
  143. protected function _asSorted($shellList) {
  144. $grouped = array();
  145. foreach ($shellList as $shell => $types) {
  146. foreach ($types as $type) {
  147. $type = Inflector::camelize($type);
  148. if (empty($grouped[$type])) {
  149. $grouped[$type] = array();
  150. }
  151. $grouped[$type][] = $shell;
  152. }
  153. }
  154. if (!empty($grouped['App'])) {
  155. sort($grouped['App'], SORT_STRING);
  156. $this->out('[ App ]');
  157. $this->out(' ' . implode(', ', $grouped['App']), 2);
  158. unset($grouped['App']);
  159. }
  160. foreach ($grouped as $section => $shells) {
  161. if ($section == 'CORE') {
  162. continue;
  163. }
  164. sort($shells, SORT_STRING);
  165. $this->out('[ ' . $section . ' ]');
  166. $this->out(' ' . implode(', ', $shells), 2);
  167. }
  168. if (!empty($grouped['CORE'])) {
  169. sort($grouped['CORE'], SORT_STRING);
  170. $this->out('[ Core ]');
  171. $this->out(' ' . implode(', ', $grouped['CORE']), 2);
  172. }
  173. $this->out();
  174. }
  175. /**
  176. * Output as XML
  177. *
  178. * @param array $shellList
  179. * @return void
  180. */
  181. protected function _asXml($shellList) {
  182. $plugins = CakePlugin::loaded();
  183. $shells = new SimpleXmlElement('<shells></shells>');
  184. foreach ($shellList as $name => $location) {
  185. $source = current($location);
  186. $callable = $name;
  187. if (in_array($source, $plugins)) {
  188. $callable = Inflector::camelize($source) . '.' . $name;
  189. }
  190. $shell = $shells->addChild('shell');
  191. $shell->addAttribute('name', $name);
  192. $shell->addAttribute('call_as', $callable);
  193. $shell->addAttribute('provider', $source);
  194. $shell->addAttribute('help', $callable . ' -h');
  195. }
  196. $this->stdout->outputAs(ConsoleOutput::RAW);
  197. $this->out($shells->saveXml());
  198. }
  199. /**
  200. * get the option parser
  201. *
  202. * @return void
  203. */
  204. public function getOptionParser() {
  205. $parser = parent::getOptionParser();
  206. return $parser->description(__d('cake_console', 'Get the list of available shells for this CakePHP application.'))
  207. ->addOption('xml', array(
  208. 'help' => __d('cake_console', 'Get the listing as XML.'),
  209. 'boolean' => true
  210. ))->addOption('sort', array(
  211. 'help' => __d('cake_console', 'Sorts the commands by where they are located.'),
  212. 'boolean' => true
  213. ));
  214. }
  215. }