CommandListShell.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. $shellList = $this->_appendShells('app', $appShells, $shellList);
  79. $plugins = CakePlugin::loaded();
  80. foreach ($plugins as $plugin) {
  81. $pluginShells = App::objects($plugin . '.Console/Command');
  82. $shellList = $this->_appendShells($plugin, $pluginShells, $shellList);
  83. }
  84. return $shellList;
  85. }
  86. /**
  87. * Scan the provided paths for shells, and append them into $shellList
  88. *
  89. * @param string $type
  90. * @param array $shells
  91. * @param array $shellList
  92. * @return array
  93. */
  94. protected function _appendShells($type, $shells, $shellList) {
  95. foreach ($shells as $shell) {
  96. $shell = Inflector::underscore(str_replace('Shell', '', $shell));
  97. $shellList[$shell][$type] = $type;
  98. }
  99. return $shellList;
  100. }
  101. /**
  102. * Output text.
  103. *
  104. * @param array $shellList
  105. * @return void
  106. */
  107. protected function _asText($shellList) {
  108. if (DS === '/') {
  109. $width = exec('tput cols') - 2;
  110. }
  111. if (empty($width)) {
  112. $width = 80;
  113. }
  114. $columns = max(1, floor($width / 30));
  115. $rows = ceil(count($shellList) / $columns);
  116. foreach ($shellList as $shell => $types) {
  117. sort($types);
  118. $shellList[$shell] = str_pad($shell . ' [' . implode ($types, ', ') . ']', $width / $columns);
  119. }
  120. $out = array_chunk($shellList, $rows);
  121. for ($i = 0; $i < $rows; $i++) {
  122. $row = '';
  123. for ($j = 0; $j < $columns; $j++) {
  124. if (!isset($out[$j][$i])) {
  125. continue;
  126. }
  127. $row .= $out[$j][$i];
  128. }
  129. $this->out(" " . $row);
  130. }
  131. $this->out();
  132. $this->out(__d('cake_console', "To run a command, type <info>cake shell_name [args]</info>"));
  133. $this->out(__d('cake_console', "To get help on a specific command, type <info>cake shell_name --help</info>"), 2);
  134. }
  135. /**
  136. * Generates the shell list sorted by where the shells are found.
  137. *
  138. * @param array $shellList
  139. * @return void
  140. */
  141. protected function _asSorted($shellList) {
  142. $grouped = array();
  143. foreach ($shellList as $shell => $types) {
  144. foreach ($types as $type) {
  145. $type = Inflector::camelize($type);
  146. if (empty($grouped[$type])) {
  147. $grouped[$type] = array();
  148. }
  149. $grouped[$type][] = $shell;
  150. }
  151. }
  152. if (!empty($grouped['App'])) {
  153. sort($grouped['App'], SORT_STRING);
  154. $this->out('[ App ]');
  155. $this->out(' ' . implode(', ', $grouped['App']), 2);
  156. unset($grouped['App']);
  157. }
  158. foreach ($grouped as $section => $shells) {
  159. if ($section == 'CORE') {
  160. continue;
  161. }
  162. sort($shells, SORT_STRING);
  163. $this->out('[ ' . $section . ' ]');
  164. $this->out(' ' . implode(', ', $shells), 2);
  165. }
  166. if (!empty($grouped['CORE'])) {
  167. sort($grouped['CORE'], SORT_STRING);
  168. $this->out('[ Core ]');
  169. $this->out(' ' . implode(', ', $grouped['CORE']), 2);
  170. }
  171. $this->out();
  172. }
  173. /**
  174. * Output as XML
  175. *
  176. * @param array $shellList
  177. * @return void
  178. */
  179. protected function _asXml($shellList) {
  180. $plugins = CakePlugin::loaded();
  181. $shells = new SimpleXmlElement('<shells></shells>');
  182. foreach ($shellList as $name => $location) {
  183. $source = current($location);
  184. $callable = $name;
  185. if (in_array($source, $plugins)) {
  186. $callable = Inflector::camelize($source) . '.' . $name;
  187. }
  188. $shell = $shells->addChild('shell');
  189. $shell->addAttribute('name', $name);
  190. $shell->addAttribute('call_as', $callable);
  191. $shell->addAttribute('provider', $source);
  192. $shell->addAttribute('help', $callable . ' -h');
  193. }
  194. $this->stdout->outputAs(ConsoleOutput::RAW);
  195. $this->out($shells->saveXml());
  196. }
  197. /**
  198. * get the option parser
  199. *
  200. * @return void
  201. */
  202. public function getOptionParser() {
  203. $parser = parent::getOptionParser();
  204. return $parser->description(__d('cake_console', 'Get the list of available shells for this CakePHP application.'))
  205. ->addOption('xml', array(
  206. 'help' => __d('cake_console', 'Get the listing as XML.'),
  207. 'boolean' => true
  208. ))->addOption('sort', array(
  209. 'help' => __d('cake_console', 'Sorts the commands by where they are located.'),
  210. 'boolean' => true
  211. ));
  212. }
  213. }