CommandListShell.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. <?php
  2. /**
  3. * CommandListTest file
  4. *
  5. * PHP 5
  6. *
  7. * CakePHP : Rapid Development Framework (http://cakephp.org)
  8. * Copyright 2005-2011, 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 2005-2011, 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.Command
  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(__d('cake_console', "<info>Current Paths:</info>"), 2);
  43. $this->out(" -app: ". APP_DIR);
  44. $this->out(" -working: " . rtrim(APP, DS));
  45. $this->out(" -root: " . rtrim(ROOT, DS));
  46. $this->out(" -core: " . rtrim(CORE_PATH, DS));
  47. $this->out("");
  48. $this->out(__d('cake_console', "<info>Changing Paths:</info>"), 2);
  49. $this->out(__d('cake_console', "Your working path should be the same as your application path to change your path use the '-app' param."));
  50. $this->out(__d('cake_console', "Example: -app relative/path/to/myapp or -app /absolute/path/to/myapp"), 2);
  51. $this->out(__d('cake_console', "<info>Available Shells:</info>"), 2);
  52. }
  53. $shellList = $this->_getShellList();
  54. if ($shellList) {
  55. ksort($shellList);
  56. if (empty($this->params['xml'])) {
  57. if (!empty($this->params['sort'])) {
  58. $this->_asSorted($shellList);
  59. } else {
  60. $this->_asText($shellList);
  61. }
  62. } else {
  63. $this->_asXml($shellList);
  64. }
  65. }
  66. }
  67. /**
  68. * Gets the shell command listing.
  69. *
  70. * @return array
  71. */
  72. protected function _getShellList() {
  73. $shellList = array();
  74. $shells = App::objects('file', App::core('Console/Command'));
  75. $shellList = $this->_appendShells('CORE', $shells, $shellList);
  76. $appShells = App::objects('Console/Command', null, false);
  77. $shellList = $this->_appendShells('app', $appShells, $shellList);
  78. $plugins = CakePlugin::loaded();
  79. foreach ($plugins as $plugin) {
  80. $pluginShells = App::objects($plugin . '.Console/Command');
  81. $shellList = $this->_appendShells($plugin, $pluginShells, $shellList);
  82. }
  83. return $shellList;
  84. }
  85. /**
  86. * Scan the provided paths for shells, and append them into $shellList
  87. *
  88. * @return array
  89. */
  90. protected function _appendShells($type, $shells, $shellList) {
  91. foreach ($shells as $shell) {
  92. $shell = Inflector::underscore(str_replace('Shell', '', $shell));
  93. $shellList[$shell][$type] = $type;
  94. }
  95. return $shellList;
  96. }
  97. /**
  98. * Output text.
  99. *
  100. * @return void
  101. */
  102. protected function _asText($shellList) {
  103. if (DS === '/') {
  104. $width = exec('tput cols') - 2;
  105. }
  106. if (empty($width)) {
  107. $width = 80;
  108. }
  109. $columns = max(1, floor($width / 30));
  110. $rows = ceil(count($shellList) / $columns);
  111. foreach ($shellList as $shell => $types) {
  112. sort($types);
  113. $shellList[$shell] = str_pad($shell . ' [' . implode ($types, ', ') . ']', $width / $columns);
  114. }
  115. $out = array_chunk($shellList, $rows);
  116. for ($i = 0; $i < $rows; $i++) {
  117. $row = '';
  118. for ($j = 0; $j < $columns; $j++) {
  119. if (!isset($out[$j][$i])) {
  120. continue;
  121. }
  122. $row .= $out[$j][$i];
  123. }
  124. $this->out(" " . $row);
  125. }
  126. $this->out();
  127. $this->out(__d('cake_console', "To run a command, type <info>cake shell_name [args]</info>"));
  128. $this->out(__d('cake_console', "To get help on a specific command, type <info>cake shell_name --help</info>"), 2);
  129. }
  130. /**
  131. * Generates the shell list sorted by where the shells are found.
  132. *
  133. * @return void
  134. */
  135. protected function _asSorted($shellList) {
  136. $grouped = array();
  137. foreach ($shellList as $shell => $types) {
  138. foreach ($types as $type) {
  139. $type = Inflector::camelize($type);
  140. if (empty($grouped[$type])) {
  141. $grouped[$type] = array();
  142. }
  143. $grouped[$type][] = $shell;
  144. }
  145. }
  146. if (!empty($grouped['App'])) {
  147. sort($grouped['App'], SORT_STRING);
  148. $this->out('[ App ]');
  149. $this->out(' ' . implode(', ', $grouped['App']), 2);
  150. unset($grouped['App']);
  151. }
  152. foreach ($grouped as $section => $shells) {
  153. if ($section == 'CORE') {
  154. continue;
  155. }
  156. sort($shells, SORT_STRING);
  157. $this->out('[ ' . $section . ' ]');
  158. $this->out(' ' . implode(', ', $shells), 2);
  159. }
  160. if (!empty($grouped['CORE'])) {
  161. sort($grouped['CORE'], SORT_STRING);
  162. $this->out('[ Core ]');
  163. $this->out(' ' . implode(', ', $grouped['CORE']), 2);
  164. }
  165. $this->out();
  166. }
  167. /**
  168. * Output as XML
  169. *
  170. * @return void
  171. */
  172. protected function _asXml($shellList) {
  173. $plugins = CakePlugin::loaded();
  174. $shells = new SimpleXmlElement('<shells></shells>');
  175. foreach ($shellList as $name => $location) {
  176. $source = current($location);
  177. $callable = $name;
  178. if (in_array($source, $plugins)) {
  179. $callable = Inflector::camelize($source) . '.' . $name;
  180. }
  181. $shell = $shells->addChild('shell');
  182. $shell->addAttribute('name', $name);
  183. $shell->addAttribute('call_as', $callable);
  184. $shell->addAttribute('provider', $source);
  185. $shell->addAttribute('help', $callable . ' -h');
  186. }
  187. $this->stdout->outputAs(ConsoleOutput::RAW);
  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(__d('cake_console', 'Get the list of available shells for this CakePHP application.'))
  198. ->addOption('xml', array(
  199. 'help' => __d('cake_console', 'Get the listing as XML.'),
  200. 'boolean' => true
  201. ))->addOption('sort', array(
  202. 'help' => __d('cake_console', 'Sorts the commands by where they are located.'),
  203. 'boolean' => true
  204. ));
  205. }
  206. }