Manage the available sub-commands along with their arguments and help

@see http://book.cakephp.org/3.0/en/console-and-shells.html#configuring-options-and-generating-help
@return \Cake\Console\ConsoleOptionParser
421799
public function getOptionParser(): ConsoleOptionParser
    {
        $parser = parent::getOptionParser();

        $updateFromCatalogParser = parent::getOptionParser();
        $updateFromCatalogParser->addOption('domain', [
            'default' => 'default',
            'help' => 'The domain to use',
        ]);
        $updateFromCatalogParser->addOption('overwrite', [
            'default' => false,
            'help' => 'If set, there will be no interactive question whether to continue.',
            'boolean' => true,
        ]);
        $updateFromCatalogParser->addOption('strip-references', [
            'boolean' => true,
            'help' => 'Whether to remove file usage references from resulting po and mo files.',
        ]);

        return $parser
            ->setDescription([
                'CkTools Shell',
                '',
                'Utilities',
            ])
            ->addSubcommand('updateFromCatalog', [
                'help' => 'Updates the PO file from the given catalog',
                'parser' => $updateFromCatalogParser,
            ]);
    }
222030
public function getOptionParser()
    {
        $parser = parent::getOptionParser();
        $parser->addSubcommand('generate', [
            'help' => __('Regenerate thumbnails for a specific table.'),
            'parser' => [
                'description' => [__('Use this command to regenerate the thumbnails for a specific table.')],
                'arguments' => [
                    'table' => ['help' => __('The table to regenerate thumbs for'), 'required' => true]
                ],
                'options' => [
                    'path-class' => [
                        'short' => 'p',
                        'help' => __('Fully name spaced custom path class, you must use double backslash.')
                    ],
                    'image-class' => [
                        'short' => 'i',
                        'help' => __('Fully name spaced custom image transform class, you must use double backslash.')
                    ],
                    'remove-behaviors' => [
                        'help' => __('The behaviors to remove before generate.'),
                    ],
                ]
            ]
        ]);
        $parser->addSubcommand('cleanup', [
            'help' => __('Clean up old images on the file system which are not linked in the database.'),
            'parser' => [
                'description' => [__('This command will delete images which are not part of the model configuration.')],
                'arguments' => [
                    'table' => ['help' => __('The table to regenerate thumbs for'), 'required' => true]
                ],
                'options' => [
                    'dry-run' => [
                        'short' => 'd',
                        'help' => __('Do a dry run and don\'t delete any files.'),
                        'boolean' => true
                    ],
                    'remove-behaviors' => [
                        'help' => __('The behaviors to remove before cleanup.'),
                    ],
                ]
            ],
        ]);

        return $parser;
    }
1328145
protected function _command() {
        $class = '\Gcs\Framework\Core\Terminal\Terminal' . ucfirst($this->_argv[0]);

        if (isset($this->_argv[1])) {
            $method = $this->_argv[1];
        }
        else if ($this->_argv[0] == 'help') {
            $method = 'help';
        }
        else {
            $method = '';
        }

        if (method_exists($class, $method)) {
            $instance = new $class($this->_argv);
            $instance->$method($this->_argv);
        }
        else {
            if (isset($this->_argv[1])) {
                echo '[ERROR] unrecognized command "' . $this->_argv[0] . ' ' . $this->_argv[1] . '"';
            }
            else {
                echo '[ERROR] unrecognized command "' . $this->_argv[0] . '"\n';
            }
        }
    }
707462
public function getOptionParser()
	{
		$parser = parent::getOptionParser();
		return $parser->description(
			'The Auditable shell.' .
			'')
			->addOption('connection', array(
					'short' => 'c',
					'default' => 'default',
					'help' => __d('Auditable', 'Set db config <config>. Uses \'default\' if none is specified.')))
			->addOption('force', array(
					'short' => 'f',
					'boolean' => true,
					'help' => __d('Auditable', 'Force changes in all tables of database.')))
			->addSubcommand('insert', array(
				'help' => __d('Auditable', 'Insert columns \'created_by\' and \'modified_by\' in all database tables.')))
			->addSubcommand('remove', array(
				'help' => __d('Auditable', 'Remove columns \'created_by\' and \'modified_by\' from all database tables.')));
	}
63531
protected function parseArguments() {
        $this->config['arguments'] = [];

        $commandFound =false;

        for ($index = 0; $index < count($this->config['args']); $index++) {
            // Ignore binary name:
            if ($index === 0) {
                continue;
            }

            $arg = $this->config['args'][$index];

            // Ignore command:
            if (array_key_exists($arg, $this->config['commands']) &&
                $commandFound === false) {
                $commandFound = true;
                continue;
            }

            // Ignore options:
            if (strpos($arg, '--') === 0) {
                foreach ($this->options as $option) {
                    if (!array_key_exists('long', $option)) {
                        continue;
                    }

                    if ('--' . $option['long'] !== $arg) {
                        continue;
                    }

                    if ($option['value'] !== self::NO_VALUE &&
                        strpos($arg, '--' . $option['long'] . '=') === 0) {
                        break;
                    } elseif ($option['value'] === self::NO_VALUE) {
                        $index += 1;
                        break;
                    } else {
                        $index += 2;
                        break;
                    }
                }
            } elseif (strpos($arg, '-') === 0) {
                foreach ($this->options as $option) {
                    if (!array_key_exists('short', $option)) {
                        continue;
                    }

                    if ('-' . $option['short'] !== $arg) {
                        continue;
                    }

                    if ($option['value'] === self::NO_VALUE) {
                        $index += 1;
                        break;
                    } else {
                        $index += 2;
                        break;
                    }
                }
            } else {
                $this->config['arguments'][] = $arg;
            }
        }

        return $this;
    }
1225770
public function listCommand()
    {
        $this->console->writeLn('manaphp commands:', Console::FC_GREEN | Console::AT_BOLD);
        foreach (glob(__DIR__ . '/*Controller.php') as $file) {
            $plainName = basename($file, '.php');
            if (in_array($plainName, ['BashCompletionController', 'HelpController'], true)) {
                continue;
            }
            $this->console->writeLn(' - ' . $this->console->colorize(Text::underscore(basename($plainName, 'Controller')), Console::FC_YELLOW));
            $commands = $this->_getCommands(__NAMESPACE__ . "\\" . $plainName);

            $width = max(max(array_map('strlen', array_keys($commands))), 18);
            foreach ($commands as $command => $description) {
                $this->console->writeLn('    ' . $this->console->colorize($command, Console::FC_CYAN, $width) . ' ' . $description);
            }
        }

        if ($this->alias->has('@cli')) {
            $this->console->writeLn('application commands: ', Console::FC_GREEN | Console::AT_BOLD);

            foreach (glob($this->alias->resolve('@cli/*Controller.php')) as $file) {
                $plainName = basename($file, '.php');
                $this->console->writeLn(' - ' . $this->console->colorize(Text::underscore(basename($plainName, 'Controller')), Console::FC_YELLOW));

                $commands = $this->_getCommands($this->alias->resolveNS("@ns.cli\\$plainName"));

                $width = max(max(array_map('strlen', array_keys($commands))), 18);
                foreach ($commands as $command => $description) {
                    $this->console->writeLn('    ' . $this->console->colorize($command, Console::FC_CYAN, $width + 1) . ' ' . $description);
                }
            }
        }

        return 0;
    }
1081306
public function helpCommand()
    {
        $args = $this->cliHandler->getArgs();
        if (isset($args[2]) && $args[2] !== 'help' && $args[2][0] !== '-') {
            $actionName = $args[2];
        } elseif (isset($args[3]) && $args[2] === 'help' && $args[3][0] !== '-') {
            $actionName = $args[3];
        } else {
            $actionName = '';
        }

        foreach (get_class_methods($this) as $method) {
            if (!preg_match('#^([a-z].*)Command$#', $method, $match)) {
                continue;
            }

            if ($actionName && $match[1] !== $actionName) {
                continue;
            }

            $rm = new \ReflectionMethod($this, $method);
            if (!$rm->isPublic()) {
                continue;
            }

            $lines = [];
            foreach (preg_split('#[\r\n]+#', $rm->getDocComment()) as $line) {
                $lines[] = trim($line, "\t /*\r\n");
            }

            $description = '';
            foreach ($lines as $line) {
                if (!$line) {
                    continue;
                }

                if ($line[0] !== '@') {
                    $description = $line;
                }
                break;
            }

            $command = $this->console->colorize(str_pad(basename($method, 'Command'), 10), Console::FC_YELLOW) . ' ' . $description;
            $this->console->writeLn($command);

            $defaultValues = [];
            foreach ($rm->getParameters() as $parameter) {
                if ($parameter->isDefaultValueAvailable()) {
                    $defaultValues[$parameter->getName()] = $parameter->getDefaultValue();
                }
            }

            $params = [];
            foreach ($lines as $line) {
                if (strpos($line, '@param') === false) {
                    continue;
                }

                $parts = preg_split('#\s+#', $line, 4);
                if (count($parts) < 3 || $parts[0] !== '@param') {
                    continue;
                }
                $name = substr($parts[2], 1);
                $type = $parts[1];

                if (isset($defaultValues[$name])) {
                    if ($type === 'bool' || $type === 'boolean') {
                        $defaultValues[$name] = $defaultValues[$name] ? 'YES' : 'NO';
                    } elseif ($type === 'int' || $type === 'integer') {
                        $defaultValues[$name] = (int)$defaultValues[$name];
                    } elseif ($type === 'float' || $type === 'double') {
                        $defaultValues[$name] = (float)$defaultValues[$name];
                    } elseif ($type === 'string') {
                        $defaultValues[$name] = json_encode($defaultValues[$name], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
                    } elseif ($type === 'array') {
                        $defaultValues[$name] = json_encode($defaultValues[$name], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
                    }
                }

                $params[$name] = isset($parts[3]) ? trim($parts[3]) : '';
            }

            if ($params) {
                $shortNames = [];
                foreach ($params as $name => $description) {
                    $short = $name[0];
                    if (isset($shortNames[$short])) {
                        $shortNames[$short] = false;
                    } else {
                        $shortNames[$short] = $name;
                    }
                }
                $shortNames = array_flip(array_filter($shortNames));

                $width = 1;
                foreach ($params as $name => $description) {
                    $width = max($width, strlen($name) + 2 + (isset($shortNames[$name]) ? 4 : 0));
                }
                $this->console->writeLn('  Options:');

                foreach ($params as $name => $value) {
                    $option = '--' . $name;
                    if (isset($shortNames[$name])) {
                        $option .= ', -' . $shortNames[$name];
                    }
                    $this->console->writeLn(['    :option :value :default',
                        'option' => $this->console->colorize($option, Console::FC_CYAN, $width),
                        'value' => $value ? "  $value" : '',
                        'default' => isset($defaultValues[$name]) ? " (default: $defaultValues[$name])" : '']);
                }
            }
        }
    }
772059
protected function configureIO()
	{
		if ($this->consoleInput->hasParameterOption(['--ansi'], true))
		{
			$this->consoleOutput->setDecorated(true);
		}
		elseif ($this->consoleInput->hasParameterOption(['--no-ansi'], true))
		{
			$this->consoleOutput->setDecorated(false);
		}

		if ($this->consoleInput->hasParameterOption(['--no-interaction', '-n'], true))
		{
			$this->consoleInput->setInteractive(false);
		}

		if ($this->consoleInput->hasParameterOption(['--quiet', '-q'], true))
		{
			$this->consoleOutput->setVerbosity(OutputInterface::VERBOSITY_QUIET);
			$this->consoleInput->setInteractive(false);
		}
		else
		{
			if ($this->consoleInput->hasParameterOption('-vvv', true)
				|| $this->consoleInput->hasParameterOption('--verbose=3', true)
				|| $this->consoleInput->getParameterOption('--verbose', false, true) === 3
			)
			{
				$this->consoleOutput->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
			}
			elseif ($this->consoleInput->hasParameterOption('-vv', true)
				|| $this->consoleInput->hasParameterOption('--verbose=2', true)
				|| $this->consoleInput->getParameterOption('--verbose', false, true) === 2
			)
			{
				$this->consoleOutput->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
			}
			elseif ($this->consoleInput->hasParameterOption('-v', true)
				|| $this->consoleInput->hasParameterOption('--verbose=1', true)
				|| $this->consoleInput->hasParameterOption('--verbose', true)
				|| $this->consoleInput->getParameterOption('--verbose', false, true)
			)
			{
				$this->consoleOutput->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
			}
		}
	}
444714
public function getOptionParser()
    {
        list($root, $name) = explode(' ', $this->name, 2);
        $parser = new ConsoleOptionParser($name);
        $parser->setRootName($root);

        $parser = $this->buildOptionParser($parser);
        if (!($parser instanceof ConsoleOptionParser)) {
            throw new RuntimeException(sprintf(
                "Invalid option parser returned from buildOptionParser(). Expected %s, got %s",
                ConsoleOptionParser::class,
                getTypeName($parser)
            ));
        }

        return $parser;
    }
1043682
protected function displayHelp(ConsoleOptionParser $parser, Arguments $args, ConsoleIo $io)
    {
        $format = 'text';
        if ($args->getArgumentAt(0) === 'xml') {
            $format = 'xml';
            $io->setOutputAs(ConsoleOutput::RAW);
        }

        $io->out($parser->help(null, $format));
    }
1358354
protected function configure()
    {
        parent::configure();

        $this
            ->setName(self::COMMAND_NAME)
            ->setDescription(self::COMMAND_DESCRIPTION)
            ->addArgument(
                self::ARGUMENT_DIR,
                (InputArgument::OPTIONAL | InputArgument::IS_ARRAY),
                self::ARGUMENT_DIR_DESCRIPTION,
                [self::ARGUMENT_DIR_DEFAULT]
            )
            ->addOption(
                self::OPTION_THRESHOLD,
                self::OPTION_THRESHOLD_SHORTCUT,
                InputOption::VALUE_OPTIONAL,
                self::OPTION_THRESHOLD_DESCRIPTION,
                self::OPTION_THRESHOLD_DEFAULT
            )
            ->addOption(
                self::OPTION_SORT_BY_NAME,
                null,
                InputOption::VALUE_NONE,
                self::OPTION_SORT_BY_NAME_DESCRIPTION
            )
            ->addOption(
                self::OPTION_PUBLIC_ONLY,
                null,
                InputOption::VALUE_REQUIRED,
                self::OPTION_PUBLIC_ONLY_DESCRIPTION,
                self::OPTION_PUBLIC_ONLY_DEFAULT
            )
            ->addOption(
                self::OPTION_EXCLUDE,
                null,
                (InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY),
                self::OPTION_EXCLUDE_DESCRIPTION,
                self::OPTION_EXCLUDE_DEFAULT
            );
    }
440590
public function getOptionParser()
    {
        $parser = parent::getOptionParser();
        $initParser = [
            'options' => [
                'plugin' => [
                    'help' => 'Plugin name.',
                    'short' => 'p'
                ],
                'force' => [
                    'help' => 'Force overwriting.',
                    'short' => 'f',
                    'boolean' => true
                ]
            ],
            'arguments' => [
                'language' => [
                    'help' => 'Two-letter language code.'
                ]
            ]
        ];

        $parser->setDescription(
            'I18n Shell generates .pot files(s) with translations.'
        )->addSubcommand('extract', [
            'help' => 'Extract the po translations from your application',
            'parser' => $this->Extract->getOptionParser()
        ])
        ->addSubcommand('init', [
            'help' => 'Init PO language file from POT file',
            'parser' => $initParser
        ]);

        return $parser;
    }
247966
public function actionAllCmd()
    {
        /**
         * @var $controllerHelp HelpController
         */
        $controllerHelp = \Yii::$app->createController('help')[0];
        $commands = $controllerHelp->getCommands();

        foreach ($controllerHelp->getCommands() as $controller) {
            $subController = \Yii::$app->createController($controller)[0];
            $actions = $controllerHelp->getActions($subController);

            if ($actions) {
                foreach ($actions as $actionId) {
                    $commands[] = $controller . "/" . $actionId;
                }
            }
        };

        $this->stdout(implode("\n", $commands));
    }
688662
public function getOptions() {
        if (is_null($this->result)) {
            $this->parse();
        }
        return $this->result[Parser::RESULT_OPTIONS];
    }
706614
private function generateOptions(): string
    {
        /** @var string[] $inputs */
        $inputs = [
            (string) (new VerbosityString($this->output)),
        ];

        $userDefinition = $this->console->getUserDefinition();
        // Get user arguments
        foreach ($userDefinition->getArguments() as $argument) {
            $inputs[] = Argument::toString($this->input, $argument);
        }

        // Get user options
        foreach ($userDefinition->getOptions() as $option) {
            $inputs[] = Option::toString($this->input, $option);
        }

        return implode(' ', array_filter($inputs, static function (string $item): bool {
            return $item !== '';
        }));
    }
555945
final public function optionHelp()
    {
        // Show Usage
        output()->write(
            (new Format())
                ->setContextualClass(Format::INFO)
                ->setString(language()->getLine('CLI_USAGE') . ':')
                ->setNewLinesBefore(1)
                ->setNewLinesAfter(1)
        );

        // Show Actions
        $this->loadActions();

        if (count($this->actionsPool)) {
            output()->write(
                (new Format())
                    ->setContextualClass(Format::INFO)
                    ->setString($this->commandName . '/action --option=value')
            );

            output()->write(
                (new Format())
                    ->setString(language()->getLine('CLI_ACTIONS') . ':')
                    ->setNewLinesBefore(2)
                    ->setNewLinesAfter(1)
            );

            $table = new Table();
            $table->isShowBorder = false;

            foreach ($this->actionsPool as $action) {

                if ($action instanceof AbstractCommander) {
                    $table
                        ->addRow()
                        ->addColumn($action->getCommandName())
                        ->addColumn(language()->getLine($action->getCommandDescription()));
                }
            }

            output()->write(
                (new Format())
                    ->setString($table->render())
            );
        } else {
            output()->write(
                (new Format())
                    ->setContextualClass(Format::INFO)
                    ->setString($this->commandName . ' --option=value')
            );
        }

        // Show Options
        output()->write(
            (new Format())
                ->setString(language()->getLine('CLI_OPTIONS') . ':')
                ->setNewLinesBefore(2)
                ->setNewLinesAfter(1)
        );

        $table = new Table();
        $table->isShowBorder = false;

        foreach ($this->commandOptions as $optionCaller => $optionProps) {
            $table
                ->addRow()
                ->addColumn('--' . $optionCaller)
                ->addColumn($optionProps[ 'shortcut' ])
                ->addColumn(language()->getLine($optionProps[ 'description' ]));
        }

        output()->write(
            (new Format())
                ->setString($table->render())
                ->setNewLinesAfter(2)
        );

        exit(EXIT_SUCCESS);
    }
440677
public function cmdAddAlias()
    {
        $params = $this->getParam();

        if (count($params) != 3) {
            $this->errorAndExit($this->text('Invalid command'));
        }

        list($entity, $entity_id, $alias) = $params;

        if (empty($entity) || empty($entity_id) || empty($alias) || !is_numeric($entity_id)) {
            $this->errorAndExit($this->text('Invalid argument'));
        }

        if (!$this->alias->loadEntity($entity, $entity_id)) {
            $this->errorAndExit($this->text('Invalid argument'));
        }

        $result = $this->addAlias($entity, $entity_id, $alias);

        if (empty($result)) {
            $this->errorAndExit($this->text('Unexpected result'));
        }

        $this->line($result);
        $this->output();
    }