|
2 | 2 |
|
3 | 3 | namespace Inhere\Console\Concern;
|
4 | 4 |
|
| 5 | +use Inhere\Console\Application; |
| 6 | +use Inhere\Console\Console; |
| 7 | +use Inhere\Console\Util\FormatUtil; |
| 8 | +use ReflectionClass; |
| 9 | +use Toolkit\Cli\ColorTag; |
| 10 | +use Toolkit\Stdlib\Str; |
| 11 | +use Toolkit\Stdlib\Util\PhpDoc; |
| 12 | +use function array_merge; |
| 13 | +use function implode; |
| 14 | +use function ksort; |
| 15 | +use function lcfirst; |
| 16 | +use function sprintf; |
| 17 | +use function strpos; |
| 18 | +use function ucfirst; |
| 19 | +use const PHP_EOL; |
| 20 | + |
5 | 21 | /**
|
6 | 22 | * Trait ControllerHelpTrait
|
7 | 23 | *
|
8 | 24 | * @package Inhere\Console\Concern
|
9 | 25 | */
|
10 | 26 | trait ControllerHelpTrait
|
11 | 27 | {
|
| 28 | + /** |
| 29 | + * Show help of the controller command group or specified command action |
| 30 | + * @usage <info>{name}:[command] -h</info> OR <info>{command} [command]</info> OR <info>{name} [command] -h</info> |
| 31 | + * |
| 32 | + * @options |
| 33 | + * -s, --search Search command by input keywords |
| 34 | + * --format Set the help information dump format(raw, xml, json, markdown) |
| 35 | + * @return int |
| 36 | + * @example |
| 37 | + * {script} {name} -h |
| 38 | + * {script} {name}:help |
| 39 | + * {script} {name}:help index |
| 40 | + * {script} {name}:index -h |
| 41 | + * {script} {name} index |
| 42 | + */ |
| 43 | + public function helpCommand(): int |
| 44 | + { |
| 45 | + $action = $this->action; |
| 46 | + |
| 47 | + // Not input action, for all sub-commands of the controller |
| 48 | + if (!$action) { |
| 49 | + $this->showCommandList(); |
| 50 | + return 0; |
| 51 | + } |
| 52 | + |
| 53 | + $action = Str::camelCase($action); |
| 54 | + $method = $this->actionSuffix ? $action . ucfirst($this->actionSuffix) : $action; |
| 55 | + $aliases = $this->getCommandAliases($action); |
| 56 | + |
| 57 | + // up: find global aliases from app |
| 58 | + if ($this->app) { |
| 59 | + $commandId = $this->input->getCommandId(); |
| 60 | + $gAliases = $this->app->getAliases($commandId); |
| 61 | + |
| 62 | + if ($gAliases) { |
| 63 | + $aliases = array_merge($aliases, $gAliases); |
| 64 | + } |
| 65 | + } |
| 66 | + |
| 67 | + $this->log(Console::VERB_DEBUG, "display help for the controller method: $method", [ |
| 68 | + 'group' => static::$name, |
| 69 | + 'action' => $action, |
| 70 | + ]); |
| 71 | + |
| 72 | + // For a specified sub-command. |
| 73 | + return $this->showHelpByMethodAnnotations($method, $action, $aliases); |
| 74 | + } |
| 75 | + |
| 76 | + protected function beforeShowCommandList(): void |
| 77 | + { |
| 78 | + // do something ... |
| 79 | + } |
| 80 | + |
| 81 | + /** |
| 82 | + * Display all sub-commands list of the controller class |
| 83 | + */ |
| 84 | + public function showCommandList(): void |
| 85 | + { |
| 86 | + $this->logf(Console::VERB_DEBUG, 'display all sub-commands list of the group: %s', static::$name); |
| 87 | + |
| 88 | + $this->beforeShowCommandList(); |
| 89 | + |
| 90 | + $ref = new ReflectionClass($this); |
| 91 | + $sName = lcfirst(self::getName() ?: $ref->getShortName()); |
| 92 | + |
| 93 | + if (!($classDes = self::getDescription())) { |
| 94 | + $classDes = PhpDoc::description($ref->getDocComment()) ?: 'No description for the command group'; |
| 95 | + } |
| 96 | + |
| 97 | + $commands = []; |
| 98 | + $showDisabled = (bool)$this->getOpt('show-disabled', false); |
| 99 | + $defaultDes = 'No description message'; |
| 100 | + |
| 101 | + /** |
| 102 | + * @var $cmd string The command name. |
| 103 | + */ |
| 104 | + foreach ($this->getAllCommandMethods($ref) as $cmd => $m) { |
| 105 | + if (!$cmd) { |
| 106 | + continue; |
| 107 | + } |
| 108 | + |
| 109 | + $desc = $this->getCommandMeta('desc', $defaultDes, $cmd); |
| 110 | + if ($phpDoc = $m->getDocComment()) { |
| 111 | + $desc = PhpDoc::firstLine($phpDoc); |
| 112 | + } |
| 113 | + |
| 114 | + // is a annotation tag |
| 115 | + if (strpos($desc, '@') === 0) { |
| 116 | + $desc = $defaultDes; |
| 117 | + } |
| 118 | + |
| 119 | + if ($this->isDisabled($cmd)) { |
| 120 | + if (!$showDisabled) { |
| 121 | + continue; |
| 122 | + } |
| 123 | + |
| 124 | + $desc .= '(<red>DISABLED</red>)'; |
| 125 | + } |
| 126 | + |
| 127 | + $aliases = $this->getCommandAliases($cmd); |
| 128 | + $desc .= $aliases ? ColorTag::wrap(' (alias: ' . implode(',', $aliases) . ')', 'info') : ''; |
| 129 | + |
| 130 | + $commands[$cmd] = $desc; |
| 131 | + } |
| 132 | + |
| 133 | + // sort commands |
| 134 | + ksort($commands); |
| 135 | + |
| 136 | + // move 'help' to last. |
| 137 | + if ($helpCmd = $commands['help'] ?? null) { |
| 138 | + unset($commands['help']); |
| 139 | + $commands['help'] = $helpCmd; |
| 140 | + } |
| 141 | + |
| 142 | + $script = $this->getScriptName(); |
| 143 | + |
| 144 | + // if is alone running. |
| 145 | + if ($detached = $this->isDetached()) { |
| 146 | + $name = $sName . ' '; |
| 147 | + $usage = "$script <info>{command}</info> [--options ...] [arguments ...]"; |
| 148 | + } else { |
| 149 | + $name = $sName . $this->delimiter; |
| 150 | + // $usage = "$script {$name}<info>{command}</info> [--options ...] [arguments ...]"; |
| 151 | + $usage = [ |
| 152 | + "$script $name<info>{command}</info> [--options ...] [arguments ...]", |
| 153 | + "$script $sName <info>{command}</info> [--options ...] [arguments ...]", |
| 154 | + ]; |
| 155 | + } |
| 156 | + |
| 157 | + $globalOptions = array_merge(Application::getGlobalOptions(), static::$globalOptions); |
| 158 | + |
| 159 | + $this->output->startBuffer(); |
| 160 | + $this->output->write(ucfirst($classDes) . PHP_EOL); |
| 161 | + |
| 162 | + if ($aliases = $this->getAliases()) { |
| 163 | + $this->output->writef("<comment>Alias:</comment> %s\n", implode(',', $aliases)); |
| 164 | + } |
| 165 | + |
| 166 | + $this->output->mList([ |
| 167 | + 'Usage:' => $usage, |
| 168 | + //'Group Name:' => "<info>$sName</info>", |
| 169 | + 'Global Options:' => FormatUtil::alignOptions($globalOptions), |
| 170 | + 'Available Commands:' => $commands, |
| 171 | + ], [ |
| 172 | + 'sepChar' => ' ', |
| 173 | + ]); |
| 174 | + |
| 175 | + $msgTpl = 'More information about a command, please see: <cyan>%s %s {command} -h</cyan>'; |
| 176 | + $this->output->write(sprintf($msgTpl, $script, $detached ? '' : $sName)); |
| 177 | + $this->output->flush(); |
| 178 | + } |
| 179 | + |
12 | 180 | }
|
0 commit comments