1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: namespace Cake\Command;
16:
17: use Cake\Console\Arguments;
18: use Cake\Console\Command;
19: use Cake\Console\CommandCollection;
20: use Cake\Console\CommandCollectionAwareInterface;
21: use Cake\Console\ConsoleIo;
22: use Cake\Console\ConsoleOptionParser;
23: use Cake\Console\ConsoleOutput;
24: use Cake\Utility\Inflector;
25: use SimpleXMLElement;
26:
27: 28: 29:
30: class HelpCommand extends Command implements CommandCollectionAwareInterface
31: {
32: 33: 34: 35: 36:
37: protected $commands;
38:
39: 40: 41:
42: public function setCommandCollection(CommandCollection $commands)
43: {
44: $this->commands = $commands;
45: }
46:
47: 48: 49: 50: 51: 52: 53:
54: public function execute(Arguments $args, ConsoleIo $io)
55: {
56: if (!$args->getOption('xml')) {
57: $io->out('<info>Current Paths:</info>', 2);
58: $io->out('* app: ' . APP_DIR . DIRECTORY_SEPARATOR);
59: $io->out('* root: ' . ROOT . DIRECTORY_SEPARATOR);
60: $io->out('* core: ' . CORE_PATH);
61: $io->out('');
62:
63: $io->out('<info>Available Commands:</info>', 2);
64: }
65:
66: $commands = $this->commands->getIterator();
67: $commands->ksort();
68:
69: if ($args->getOption('xml')) {
70: $this->asXml($io, $commands);
71:
72: return static::CODE_SUCCESS;
73: }
74:
75: $this->asText($io, $commands);
76:
77: return static::CODE_SUCCESS;
78: }
79:
80: 81: 82: 83: 84: 85: 86:
87: protected function asText($io, $commands)
88: {
89: $invert = [];
90: foreach ($commands as $name => $class) {
91: if (is_object($class)) {
92: $class = get_class($class);
93: }
94: if (!isset($invert[$class])) {
95: $invert[$class] = [];
96: }
97: $invert[$class][] = $name;
98: }
99:
100: $prefixed = [];
101: foreach ($invert as $class => $names) {
102: $prefixedName = $this->findPrefixedName($names);
103: if (!$prefixedName) {
104: $prefix = preg_match('#^Cake\\\\(Command|Shell)\\\\#', $class) ? '[core]' : '[app]';
105: $prefixed[$prefix][] = $this->getShortestName($names);
106: continue;
107: }
108:
109: list ($prefix, $name) = explode('.', $prefixedName, 2);
110: $prefix = Inflector::camelize($prefix);
111:
112: $shortestName = $this->getShortestName($names);
113: if (strpos($shortestName, '.') !== false) {
114: list (, $shortestName) = explode('.', $shortestName, 2);
115: }
116:
117: $prefixed[$prefix][] = $shortestName;
118: }
119:
120: ksort($prefixed);
121:
122: foreach ($prefixed as $prefix => $names) {
123: $io->out($prefix . ':');
124: sort($names);
125: foreach ($names as $name) {
126: $io->out(' - ' . $name);
127: }
128: }
129: $io->out('');
130:
131: $io->out('To run a command, type <info>`cake command_name [args|options]`</info>');
132: $io->out('To get help on a specific command, type <info>`cake command_name --help`</info>', 2);
133: }
134:
135: 136: 137: 138: 139:
140: protected function findPrefixedName(array $names)
141: {
142: foreach ($names as $name) {
143: if (strpos($name, '.') !== false) {
144: return $name;
145: }
146: }
147:
148: return null;
149: }
150:
151: 152: 153: 154:
155: protected function getShortestName(array $names)
156: {
157: if (count($names) <= 1) {
158: return array_shift($names);
159: }
160:
161: usort($names, function ($a, $b) {
162: return strlen($a) - strlen($b);
163: });
164:
165: return array_shift($names);
166: }
167:
168: 169: 170: 171: 172: 173: 174:
175: protected function asXml($io, $commands)
176: {
177: $shells = new SimpleXMLElement('<shells></shells>');
178: foreach ($commands as $name => $class) {
179: if (is_object($class)) {
180: $class = get_class($class);
181: }
182: $shell = $shells->addChild('shell');
183: $shell->addAttribute('name', $name);
184: $shell->addAttribute('call_as', $name);
185: $shell->addAttribute('provider', $class);
186: $shell->addAttribute('help', $name . ' -h');
187: }
188: $io->setOutputAs(ConsoleOutput::RAW);
189: $io->out($shells->saveXML());
190: }
191:
192: 193: 194: 195: 196: 197:
198: protected function buildOptionParser(ConsoleOptionParser $parser)
199: {
200: $parser->setDescription(
201: 'Get the list of available commands for this application.'
202: )->addOption('xml', [
203: 'help' => 'Get the listing as XML.',
204: 'boolean' => true
205: ]);
206:
207: return $parser;
208: }
209: }
210: