CommandListShell.php 5.6 KB

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