diff --git a/core/library/think/Console.php b/core/library/think/Console.php
deleted file mode 100644
index a28845d4..00000000
--- a/core/library/think/Console.php
+++ /dev/null
@@ -1,987 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think;
-
-use think\console\command\Command;
-use think\console\command\Help as HelpCommand;
-use think\console\helper\Debug as DebugFormatterHelper;
-use think\console\helper\Formatter as FormatterHelper;
-use think\console\helper\Process as ProcessHelper;
-use think\console\helper\Question as QuestionHelper;
-use think\console\helper\Set as HelperSet;
-use think\console\Input as ConsoleInput;
-use think\console\input\Argument as InputArgument;
-use think\console\input\Definition as InputDefinition;
-use think\console\input\Option as InputOption;
-use think\console\Output;
-use think\console\output\Nothing;
-use think\console\output\Stream;
-
-class Console
-{
-
- private $name;
- private $version;
-
- /** @var Command[] */
- private $commands = [];
-
- private $wantHelps = false;
-
- /** @var Command */
- private $runningCommand;
-
- private $catchExceptions = true;
- private $autoExit = true;
- private $definition;
- private $helperSet;
- private $terminalDimensions;
- private $defaultCommand;
-
- private static $defaultCommands = [
- "think\\console\\command\\Help",
- "think\\console\\command\\Lists",
- "think\\console\\command\\Build",
- "think\\console\\command\\make\\Controller",
- "think\\console\\command\\make\\Model",
- ];
-
- public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
- {
- $this->name = $name;
- $this->version = $version;
-
- $this->defaultCommand = 'list';
- $this->helperSet = $this->getDefaultHelperSet();
- $this->definition = $this->getDefaultInputDefinition();
-
- foreach ($this->getDefaultCommands() as $command) {
- $this->add($command);
- }
- }
-
- public static function init($run = true)
- {
- static $console;
- if (!$console) {
- // 实例化console
- $console = new self('Think Console', '0.1');
- // 读取指令集
- if (is_file(CONF_PATH . 'command' . EXT)) {
- $commands = include CONF_PATH . 'command' . EXT;
- if (is_array($commands)) {
- foreach ($commands as $command) {
- if (class_exists($command) && is_subclass_of($command, "\\think\\console\\command\\Command")) {
- // 注册指令
- $console->add(new $command());
- }
- }
- }
- }
- }
- if ($run) {
- // 运行
- $console->run();
- } else {
- return $console;
- }
- }
-
- public static function call($command, array $parameters = [])
- {
- $console = self::init(false);
-
- array_unshift($parameters, $command);
-
- $input = new ConsoleInput($parameters);
-
- $console->find($command)->run($input, new Nothing());
- }
-
- /**
- * 执行当前的指令
- * @return int
- * @throws \Exception
- * @api
- */
- public function run()
- {
- $input = new ConsoleInput();
- $output = new Output();
-
- $this->configureIO($input, $output);
-
- try {
- $exitCode = $this->doRun($input, $output);
- } catch (\Exception $e) {
- if (!$this->catchExceptions) {
- throw $e;
- }
-
- $this->renderException($e, $output->getErrorOutput());
-
- $exitCode = $e->getCode();
- if (is_numeric($exitCode)) {
- $exitCode = (int)$exitCode;
- if (0 === $exitCode) {
- $exitCode = 1;
- }
- } else {
- $exitCode = 1;
- }
- }
-
- if ($this->autoExit) {
- if ($exitCode > 255) {
- $exitCode = 255;
- }
-
- exit($exitCode);
- }
-
- return $exitCode;
- }
-
- /**
- * 执行指令
- * @param ConsoleInput $input
- * @param Output $output
- * @return int
- */
- public function doRun(ConsoleInput $input, Output $output)
- {
- if (true === $input->hasParameterOption(['--version', '-V'])) {
- $output->writeln($this->getLongVersion());
-
- return 0;
- }
-
- $name = $this->getCommandName($input);
-
- if (true === $input->hasParameterOption(['--help', '-h'])) {
- if (!$name) {
- $name = 'help';
- $input = new ConsoleInput(['help']);
- } else {
- $this->wantHelps = true;
- }
- }
-
- if (!$name) {
- $name = $this->defaultCommand;
- $input = new ConsoleInput([$this->defaultCommand]);
- }
-
- $command = $this->find($name);
-
- $this->runningCommand = $command;
- $exitCode = $this->doRunCommand($command, $input, $output);
- $this->runningCommand = null;
-
- return $exitCode;
- }
-
- /**
- * 设置助手集
- * @param HelperSet $helperSet
- */
- public function setHelperSet(HelperSet $helperSet)
- {
- $this->helperSet = $helperSet;
- }
-
- /**
- * 获取助手集
- * @return HelperSet
- */
- public function getHelperSet()
- {
- return $this->helperSet;
- }
-
- /**
- * 设置输入参数定义
- * @param InputDefinition $definition
- */
- public function setDefinition(InputDefinition $definition)
- {
- $this->definition = $definition;
- }
-
- /**
- * 获取输入参数定义
- * @return InputDefinition The InputDefinition instance
- */
- public function getDefinition()
- {
- return $this->definition;
- }
-
- /**
- * Gets the help message.
- * @return string A help message.
- */
- public function getHelp()
- {
- return $this->getLongVersion();
- }
-
- /**
- * 是否捕获异常
- * @param bool $boolean
- * @api
- */
- public function setCatchExceptions($boolean)
- {
- $this->catchExceptions = (bool)$boolean;
- }
-
- /**
- * 是否自动退出
- * @param bool $boolean
- * @api
- */
- public function setAutoExit($boolean)
- {
- $this->autoExit = (bool)$boolean;
- }
-
- /**
- * 获取名称
- * @return string
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * 设置名称
- * @param string $name
- */
- public function setName($name)
- {
- $this->name = $name;
- }
-
- /**
- * 获取版本
- * @return string
- * @api
- */
- public function getVersion()
- {
- return $this->version;
- }
-
- /**
- * 设置版本
- * @param string $version
- */
- public function setVersion($version)
- {
- $this->version = $version;
- }
-
- /**
- * 获取完整的版本号
- * @return string
- */
- public function getLongVersion()
- {
- if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) {
- return sprintf('%s version %s', $this->getName(), $this->getVersion());
- }
-
- return 'Console Tool';
- }
-
- /**
- * 注册一个指令
- * @param string $name
- * @return Command
- */
- public function register($name)
- {
- return $this->add(new Command($name));
- }
-
- /**
- * 添加指令
- * @param Command[] $commands
- */
- public function addCommands(array $commands)
- {
- foreach ($commands as $command) {
- $this->add($command);
- }
- }
-
- /**
- * 添加一个指令
- * @param Command $command
- * @return Command
- */
- public function add(Command $command)
- {
- $command->setConsole($this);
-
- if (!$command->isEnabled()) {
- $command->setConsole(null);
- return null;
- }
-
- if (null === $command->getDefinition()) {
- throw new \LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
- }
-
- $this->commands[$command->getName()] = $command;
-
- foreach ($command->getAliases() as $alias) {
- $this->commands[$alias] = $command;
- }
-
- return $command;
- }
-
- /**
- * 获取指令
- * @param string $name 指令名称
- * @return Command
- * @throws \InvalidArgumentException
- */
- public function get($name)
- {
- if (!isset($this->commands[$name])) {
- throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name));
- }
-
- $command = $this->commands[$name];
-
- if ($this->wantHelps) {
- $this->wantHelps = false;
-
- /** @var HelpCommand $helpCommand */
- $helpCommand = $this->get('help');
- $helpCommand->setCommand($command);
-
- return $helpCommand;
- }
-
- return $command;
- }
-
- /**
- * 某个指令是否存在
- * @param string $name 指令民初
- * @return bool
- */
- public function has($name)
- {
- return isset($this->commands[$name]);
- }
-
- /**
- * 获取所有的命名空间
- * @return array
- */
- public function getNamespaces()
- {
- $namespaces = [];
- foreach ($this->commands as $command) {
- $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
-
- foreach ($command->getAliases() as $alias) {
- $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
- }
- }
-
- return array_values(array_unique(array_filter($namespaces)));
- }
-
- /**
- * 查找注册命名空间中的名称或缩写。
- * @param string $namespace
- * @return string
- * @throws \InvalidArgumentException
- */
- public function findNamespace($namespace)
- {
- $allNamespaces = $this->getNamespaces();
- $expr = preg_replace_callback('{([^:]+|)}', function ($matches) {
- return preg_quote($matches[1]) . '[^:]*';
- }, $namespace);
- $namespaces = preg_grep('{^' . $expr . '}', $allNamespaces);
-
- if (empty($namespaces)) {
- $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
-
- if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
- if (1 == count($alternatives)) {
- $message .= "\n\nDid you mean this?\n ";
- } else {
- $message .= "\n\nDid you mean one of these?\n ";
- }
-
- $message .= implode("\n ", $alternatives);
- }
-
- throw new \InvalidArgumentException($message);
- }
-
- $exact = in_array($namespace, $namespaces, true);
- if (count($namespaces) > 1 && !$exact) {
- throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))));
- }
-
- return $exact ? $namespace : reset($namespaces);
- }
-
- /**
- * 查找指令
- * @param string $name 名称或者别名
- * @return Command
- * @throws \InvalidArgumentException
- */
- public function find($name)
- {
- $allCommands = array_keys($this->commands);
- $expr = preg_replace_callback('{([^:]+|)}', function ($matches) {
- return preg_quote($matches[1]) . '[^:]*';
- }, $name);
- $commands = preg_grep('{^' . $expr . '}', $allCommands);
-
- if (empty($commands) || count(preg_grep('{^' . $expr . '$}', $commands)) < 1) {
- if (false !== $pos = strrpos($name, ':')) {
- $this->findNamespace(substr($name, 0, $pos));
- }
-
- $message = sprintf('Command "%s" is not defined.', $name);
-
- if ($alternatives = $this->findAlternatives($name, $allCommands)) {
- if (1 == count($alternatives)) {
- $message .= "\n\nDid you mean this?\n ";
- } else {
- $message .= "\n\nDid you mean one of these?\n ";
- }
- $message .= implode("\n ", $alternatives);
- }
-
- throw new \InvalidArgumentException($message);
- }
-
- if (count($commands) > 1) {
- $commandList = $this->commands;
- $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
- $commandName = $commandList[$nameOrAlias]->getName();
-
- return $commandName === $nameOrAlias || !in_array($commandName, $commands);
- });
- }
-
- $exact = in_array($name, $commands, true);
- if (count($commands) > 1 && !$exact) {
- $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
-
- throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions));
- }
-
- return $this->get($exact ? $name : reset($commands));
- }
-
- /**
- * 获取所有的指令
- * @param string $namespace 命名空间
- * @return Command[]
- * @api
- */
- public function all($namespace = null)
- {
- if (null === $namespace) {
- return $this->commands;
- }
-
- $commands = [];
- foreach ($this->commands as $name => $command) {
- if ($this->extractNamespace($name, substr_count($namespace, ':') + 1) === $namespace) {
- $commands[$name] = $command;
- }
- }
-
- return $commands;
- }
-
- /**
- * 获取可能的指令名
- * @param array $names
- * @return array
- */
- public static function getAbbreviations($names)
- {
- $abbrevs = [];
- foreach ($names as $name) {
- for ($len = strlen($name); $len > 0; --$len) {
- $abbrev = substr($name, 0, $len);
- $abbrevs[$abbrev][] = $name;
- }
- }
-
- return $abbrevs;
- }
-
- /**
- * 呈现捕获的异常
- * @param \Exception $e
- * @param Stream $output
- */
- public function renderException(\Exception $e, Stream $output)
- {
- do {
- $title = sprintf(' [%s] ', get_class($e));
-
- $len = $this->stringWidth($title);
-
- $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
-
- if (defined('HHVM_VERSION') && $width > 1 << 31) {
- $width = 1 << 31;
- }
- $formatter = $output->getFormatter();
- $lines = [];
- foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
- foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
-
- $lineLength = $this->stringWidth(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4;
- $lines[] = [$line, $lineLength];
-
- $len = max($lineLength, $len);
- }
- }
-
- $messages = ['', ''];
- $messages[] = $emptyLine = $formatter->format(sprintf('%s', str_repeat(' ', $len)));
- $messages[] = $formatter->format(sprintf('%s%s', $title, str_repeat(' ', max(0, $len - $this->stringWidth($title)))));
- foreach ($lines as $line) {
- $messages[] = $formatter->format(sprintf(' %s %s', $line[0], str_repeat(' ', $len - $line[1])));
- }
- $messages[] = $emptyLine;
- $messages[] = '';
- $messages[] = '';
-
- $output->writeln($messages, Output::OUTPUT_RAW);
-
- if (Output::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
- $output->writeln('Exception trace:');
-
- // exception related properties
- $trace = $e->getTrace();
- array_unshift($trace, [
- 'function' => '',
- 'file' => $e->getFile() !== null ? $e->getFile() : 'n/a',
- 'line' => $e->getLine() !== null ? $e->getLine() : 'n/a',
- 'args' => [],
- ]);
-
- for ($i = 0, $count = count($trace); $i < $count; ++$i) {
- $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
- $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
- $function = $trace[$i]['function'];
- $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
- $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
-
- $output->writeln(sprintf(' %s%s%s() at %s:%s', $class, $type, $function, $file, $line));
- }
-
- $output->writeln('');
- $output->writeln('');
- }
- } while ($e = $e->getPrevious());
-
- if (null !== $this->runningCommand) {
- $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName())));
- $output->writeln('');
- $output->writeln('');
- }
- }
-
- /**
- * 获取终端宽度
- * @return int|null
- */
- protected function getTerminalWidth()
- {
- $dimensions = $this->getTerminalDimensions();
-
- return $dimensions[0];
- }
-
- /**
- * 获取终端高度
- * @return int|null
- */
- protected function getTerminalHeight()
- {
- $dimensions = $this->getTerminalDimensions();
-
- return $dimensions[1];
- }
-
- /**
- * 获取当前终端的尺寸
- * @return array
- */
- public function getTerminalDimensions()
- {
- if ($this->terminalDimensions) {
- return $this->terminalDimensions;
- }
-
- if ('\\' === DS) {
- if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
- return [(int)$matches[1], (int)$matches[2]];
- }
- if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
- return [(int)$matches[1], (int)$matches[2]];
- }
- }
-
- if ($sttyString = $this->getSttyColumns()) {
- if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
- return [(int)$matches[2], (int)$matches[1]];
- }
- if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
- return [(int)$matches[2], (int)$matches[1]];
- }
- }
-
- return [null, null];
- }
-
- /**
- * 设置终端尺寸
- * @param int $width
- * @param int $height
- * @return Console
- */
- public function setTerminalDimensions($width, $height)
- {
- $this->terminalDimensions = [$width, $height];
-
- return $this;
- }
-
- /**
- * 配置基于用户的参数和选项的输入和输出实例。
- * @param ConsoleInput $input 输入实例
- * @param Output $output 输出实例
- */
- protected function configureIO(ConsoleInput $input, Output $output)
- {
- if (true === $input->hasParameterOption(['--ansi'])) {
- $output->setDecorated(true);
- } elseif (true === $input->hasParameterOption(['--no-ansi'])) {
- $output->setDecorated(false);
- }
-
- if (true === $input->hasParameterOption(['--no-interaction', '-n'])) {
- $input->setInteractive(false);
- } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
- $inputStream = $this->getHelperSet()->get('question')->getInputStream();
- if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
- $input->setInteractive(false);
- }
- }
-
- if (true === $input->hasParameterOption(['--quiet', '-q'])) {
- $output->setVerbosity(Output::VERBOSITY_QUIET);
- } else {
- if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
- $output->setVerbosity(Output::VERBOSITY_DEBUG);
- } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) {
- $output->setVerbosity(Output::VERBOSITY_VERY_VERBOSE);
- } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
- $output->setVerbosity(Output::VERBOSITY_VERBOSE);
- }
- }
- }
-
- /**
- * 执行指令
- * @param Command $command 指令实例
- * @param ConsoleInput $input 输入实例
- * @param Output $output 输出实例
- * @return int
- * @throws \Exception
- */
- protected function doRunCommand(Command $command, ConsoleInput $input, Output $output)
- {
- return $command->run($input, $output);
- }
-
- /**
- * 获取指令的基础名称
- * @param ConsoleInput $input
- * @return string
- */
- protected function getCommandName(ConsoleInput $input)
- {
- return $input->getFirstArgument();
- }
-
- /**
- * 获取默认输入定义
- * @return InputDefinition
- */
- protected function getDefaultInputDefinition()
- {
- return new InputDefinition([
- new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
- new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
- new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this console version'),
- new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
- new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
- new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
- new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
- new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
- ]);
- }
-
- /**
- * 设置默认命令
- * @return Command[] An array of default Command instances
- */
- protected function getDefaultCommands()
- {
- $defaultCommands = [];
-
- foreach (self::$defaultCommands as $classname) {
- if (class_exists($classname) && is_subclass_of($classname, "think\\console\\command\\Command")) {
- $defaultCommands[] = new $classname();
- }
- }
-
- return $defaultCommands;
- }
-
- public static function addDefaultCommands(array $classnames)
- {
- self::$defaultCommands = array_merge(self::$defaultCommands, $classnames);
- }
-
- /**
- * 设置默认助手
- * @return HelperSet
- */
- protected function getDefaultHelperSet()
- {
- return new HelperSet([
- new FormatterHelper(),
- new DebugFormatterHelper(),
- new ProcessHelper(),
- new QuestionHelper(),
- ]);
- }
-
- /**
- * 获取stty列数
- * @return string
- */
- private function getSttyColumns()
- {
- if (!function_exists('proc_open')) {
- return null;
- }
-
- $descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
- $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, ['suppress_errors' => true]);
- if (is_resource($process)) {
- $info = stream_get_contents($pipes[1]);
- fclose($pipes[1]);
- fclose($pipes[2]);
- proc_close($process);
-
- return $info;
- }
- return null;
- }
-
- /**
- * 获取终端模式
- * @return string x 或 null
- */
- private function getConsoleMode()
- {
- if (!function_exists('proc_open')) {
- return null;
- }
-
- $descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
- $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, ['suppress_errors' => true]);
- if (is_resource($process)) {
- $info = stream_get_contents($pipes[1]);
- fclose($pipes[1]);
- fclose($pipes[2]);
- proc_close($process);
-
- if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
- return $matches[2] . 'x' . $matches[1];
- }
- }
- return null;
- }
-
- /**
- * 获取可能的建议
- * @param array $abbrevs
- * @return string
- */
- private function getAbbreviationSuggestions($abbrevs)
- {
- return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
- }
-
- /**
- * 返回命名空间部分
- * @param string $name 指令
- * @param string $limit 部分的命名空间的最大数量
- * @return string
- */
- public function extractNamespace($name, $limit = null)
- {
- $parts = explode(':', $name);
- array_pop($parts);
-
- return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
- }
-
- /**
- * 查找可替代的建议
- * @param string $name
- * @param array|\Traversable $collection
- * @return array
- */
- private function findAlternatives($name, $collection)
- {
- $threshold = 1e3;
- $alternatives = [];
-
- $collectionParts = [];
- foreach ($collection as $item) {
- $collectionParts[$item] = explode(':', $item);
- }
-
- foreach (explode(':', $name) as $i => $subname) {
- foreach ($collectionParts as $collectionName => $parts) {
- $exists = isset($alternatives[$collectionName]);
- if (!isset($parts[$i]) && $exists) {
- $alternatives[$collectionName] += $threshold;
- continue;
- } elseif (!isset($parts[$i])) {
- continue;
- }
-
- $lev = levenshtein($subname, $parts[$i]);
- if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
- $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
- } elseif ($exists) {
- $alternatives[$collectionName] += $threshold;
- }
- }
- }
-
- foreach ($collection as $item) {
- $lev = levenshtein($name, $item);
- if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
- $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
- }
- }
-
- $alternatives = array_filter($alternatives, function ($lev) use ($threshold) {
- return $lev < 2 * $threshold;
- });
- asort($alternatives);
-
- return array_keys($alternatives);
- }
-
- /**
- * 设置默认的指令
- * @param string $commandName The Command name
- */
- public function setDefaultCommand($commandName)
- {
- $this->defaultCommand = $commandName;
- }
-
- private function stringWidth($string)
- {
- if (!function_exists('mb_strwidth')) {
- return strlen($string);
- }
-
- if (false === $encoding = mb_detect_encoding($string)) {
- return strlen($string);
- }
-
- return mb_strwidth($string, $encoding);
- }
-
- private function splitStringByWidth($string, $width)
- {
- if (!function_exists('mb_strwidth')) {
- return str_split($string, $width);
- }
-
- if (false === $encoding = mb_detect_encoding($string)) {
- return str_split($string, $width);
- }
-
- $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
- $lines = [];
- $line = '';
- foreach (preg_split('//u', $utf8String) as $char) {
- if (mb_strwidth($line . $char, 'utf8') <= $width) {
- $line .= $char;
- continue;
- }
- $lines[] = str_pad($line, $width);
- $line = $char;
- }
- if (strlen($line)) {
- $lines[] = count($lines) ? str_pad($line, $width) : $line;
- }
-
- mb_convert_variables($encoding, 'utf8', $lines);
-
- return $lines;
- }
-
- /**
- * 返回所有的命名空间
- * @param string $name
- * @return array
- */
- private function extractAllNamespaces($name)
- {
- $parts = explode(':', $name, -1);
- $namespaces = [];
-
- foreach ($parts as $part) {
- if (count($namespaces)) {
- $namespaces[] = end($namespaces) . ':' . $part;
- } else {
- $namespaces[] = $part;
- }
- }
-
- return $namespaces;
- }
-
-}
diff --git a/core/library/think/console/Input.php b/core/library/think/console/Input.php
deleted file mode 100644
index 889ee39e..00000000
--- a/core/library/think/console/Input.php
+++ /dev/null
@@ -1,471 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console;
-
-use think\console\input\Definition;
-use think\console\input\Argument;
-use think\console\input\Option;
-
-class Input
-{
-
- /**
- * @var Definition
- */
- protected $definition;
-
- /**
- * @var Option[]
- */
- protected $options = [];
-
- /**
- * @var Argument[]
- */
- protected $arguments = [];
-
- protected $interactive = true;
-
- private $tokens;
- private $parsed;
-
-
- public function __construct($argv = null)
- {
- if (null === $argv) {
- $argv = $_SERVER['argv'];
- // 去除命令名
- array_shift($argv);
- }
-
- $this->tokens = $argv;
-
- $this->definition = new Definition();
- }
-
-
- protected function setTokens(array $tokens)
- {
- $this->tokens = $tokens;
- }
-
- /**
- * 绑定实例
- * @param Definition $definition A InputDefinition instance
- */
- public function bind(Definition $definition)
- {
- $this->arguments = [];
- $this->options = [];
- $this->definition = $definition;
-
- $this->parse();
- }
-
-
- /**
- * 解析参数
- */
- protected function parse()
- {
- $parseOptions = true;
- $this->parsed = $this->tokens;
- while (null !== $token = array_shift($this->parsed)) {
- if ($parseOptions && '' == $token) {
- $this->parseArgument($token);
- } elseif ($parseOptions && '--' == $token) {
- $parseOptions = false;
- } elseif ($parseOptions && 0 === strpos($token, '--')) {
- $this->parseLongOption($token);
- } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
- $this->parseShortOption($token);
- } else {
- $this->parseArgument($token);
- }
- }
- }
-
-
- /**
- * 解析短选项
- * @param string $token 当前的指令.
- */
- private function parseShortOption($token)
- {
- $name = substr($token, 1);
-
- if (strlen($name) > 1) {
- if ($this->definition->hasShortcut($name[0])
- && $this->definition->getOptionForShortcut($name[0])->acceptValue()
- ) {
- $this->addShortOption($name[0], substr($name, 1));
- } else {
- $this->parseShortOptionSet($name);
- }
- } else {
- $this->addShortOption($name, null);
- }
- }
-
- /**
- * 解析短选项
- * @param string $name 当前指令
- * @throws \RuntimeException
- */
- private function parseShortOptionSet($name)
- {
- $len = strlen($name);
- for ($i = 0; $i < $len; ++$i) {
- if (!$this->definition->hasShortcut($name[$i])) {
- throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
- }
-
- $option = $this->definition->getOptionForShortcut($name[$i]);
- if ($option->acceptValue()) {
- $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
-
- break;
- } else {
- $this->addLongOption($option->getName(), null);
- }
- }
- }
-
- /**
- * 解析完整选项
- * @param string $token 当前指令
- */
- private function parseLongOption($token)
- {
- $name = substr($token, 2);
-
- if (false !== $pos = strpos($name, '=')) {
- $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));
- } else {
- $this->addLongOption($name, null);
- }
- }
-
- /**
- * 解析参数
- * @param string $token 当前指令
- * @throws \RuntimeException
- */
- private function parseArgument($token)
- {
- $c = count($this->arguments);
-
- if ($this->definition->hasArgument($c)) {
- $arg = $this->definition->getArgument($c);
-
- $this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token;
-
- } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
- $arg = $this->definition->getArgument($c - 1);
-
- $this->arguments[$arg->getName()][] = $token;
- } else {
- throw new \RuntimeException('Too many arguments.');
- }
- }
-
-
- /**
- * 添加一个短选项的值
- * @param string $shortcut 短名称
- * @param mixed $value 值
- * @throws \RuntimeException
- */
- private function addShortOption($shortcut, $value)
- {
- if (!$this->definition->hasShortcut($shortcut)) {
- throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
- }
-
- $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
- }
-
- /**
- * 添加一个完整选项的值
- * @param string $name 选项名
- * @param mixed $value 值
- * @throws \RuntimeException
- */
- private function addLongOption($name, $value)
- {
- if (!$this->definition->hasOption($name)) {
- throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name));
- }
-
- $option = $this->definition->getOption($name);
-
- if (false === $value) {
- $value = null;
- }
-
- if (null !== $value && !$option->acceptValue()) {
- throw new \RuntimeException(sprintf('The "--%s" option does not accept a value.', $name, $value));
- }
-
- if (null === $value && $option->acceptValue() && count($this->parsed)) {
- $next = array_shift($this->parsed);
- if (isset($next[0]) && '-' !== $next[0]) {
- $value = $next;
- } elseif (empty($next)) {
- $value = '';
- } else {
- array_unshift($this->parsed, $next);
- }
- }
-
- if (null === $value) {
- if ($option->isValueRequired()) {
- throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name));
- }
-
- if (!$option->isArray()) {
- $value = $option->isValueOptional() ? $option->getDefault() : true;
- }
- }
-
- if ($option->isArray()) {
- $this->options[$name][] = $value;
- } else {
- $this->options[$name] = $value;
- }
- }
-
- /**
- * 获取第一个参数
- * @return string|null
- */
- public function getFirstArgument()
- {
- foreach ($this->tokens as $token) {
- if ($token && '-' === $token[0]) {
- continue;
- }
-
- return $token;
- }
- return null;
- }
-
-
- /**
- * 检查原始参数是否包含某个值
- * @param string|array $values 需要检查的值
- * @return bool
- */
- public function hasParameterOption($values)
- {
- $values = (array)$values;
-
- foreach ($this->tokens as $token) {
- foreach ($values as $value) {
- if ($token === $value || 0 === strpos($token, $value . '=')) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * 获取原始选项的值
- * @param string|array $values 需要检查的值
- * @param mixed $default 默认值
- * @return mixed The option value
- */
- public function getParameterOption($values, $default = false)
- {
- $values = (array)$values;
- $tokens = $this->tokens;
-
- while (0 < count($tokens)) {
- $token = array_shift($tokens);
-
- foreach ($values as $value) {
- if ($token === $value || 0 === strpos($token, $value . '=')) {
- if (false !== $pos = strpos($token, '=')) {
- return substr($token, $pos + 1);
- }
-
- return array_shift($tokens);
- }
- }
- }
-
- return $default;
- }
-
-
- /**
- * 验证输入
- * @throws \RuntimeException
- */
- public function validate()
- {
- if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) {
- throw new \RuntimeException('Not enough arguments.');
- }
- }
-
- /**
- * 检查输入是否是交互的
- * @return bool
- */
- public function isInteractive()
- {
- return $this->interactive;
- }
-
- /**
- * 设置输入的交互
- * @param bool
- */
- public function setInteractive($interactive)
- {
- $this->interactive = (bool)$interactive;
- }
-
- /**
- * 获取所有的参数
- * @return Argument[]
- */
- public function getArguments()
- {
- return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
- }
-
- /**
- * 根据名称获取参数
- * @param string $name 参数名
- * @return mixed
- * @throws \InvalidArgumentException
- */
- public function getArgument($name)
- {
- if (!$this->definition->hasArgument($name)) {
- throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
- }
-
- return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)
- ->getDefault();
- }
-
- /**
- * 设置参数的值
- * @param string $name 参数名
- * @param string $value 值
- * @throws \InvalidArgumentException
- */
- public function setArgument($name, $value)
- {
- if (!$this->definition->hasArgument($name)) {
- throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
- }
-
- $this->arguments[$name] = $value;
- }
-
- /**
- * 检查是否存在某个参数
- * @param string|int $name 参数名或位置
- * @return bool
- */
- public function hasArgument($name)
- {
- return $this->definition->hasArgument($name);
- }
-
- /**
- * 获取所有的选项
- * @return Option[]
- */
- public function getOptions()
- {
- return array_merge($this->definition->getOptionDefaults(), $this->options);
- }
-
- /**
- * 获取选项值
- * @param string $name 选项名称
- * @return mixed
- * @throws \InvalidArgumentException
- */
- public function getOption($name)
- {
- if (!$this->definition->hasOption($name)) {
- throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
- }
-
- return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
- }
-
- /**
- * 设置选项值
- * @param string $name 选项名
- * @param string|bool $value 值
- * @throws \InvalidArgumentException
- */
- public function setOption($name, $value)
- {
- if (!$this->definition->hasOption($name)) {
- throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
- }
-
- $this->options[$name] = $value;
- }
-
- /**
- * 是否有某个选项
- * @param string $name 选项名
- * @return bool
- */
- public function hasOption($name)
- {
- return $this->definition->hasOption($name) && isset($this->options[$name]);
- }
-
- /**
- * 转义指令
- * @param string $token
- * @return string
- */
- public function escapeToken($token)
- {
- return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
- }
-
- /**
- * 返回传递给命令的参数的字符串
- * @return string
- */
- public function __toString()
- {
- $tokens = array_map(function ($token) {
- if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
- return $match[1] . $this->escapeToken($match[2]);
- }
-
- if ($token && $token[0] !== '-') {
- return $this->escapeToken($token);
- }
-
- return $token;
- }, $this->tokens);
-
- return implode(' ', $tokens);
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/LICENSE b/core/library/think/console/LICENSE
deleted file mode 100644
index 0abe056e..00000000
--- a/core/library/think/console/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2004-2016 Fabien Potencier
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is furnished
-to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
\ No newline at end of file
diff --git a/core/library/think/console/Output.php b/core/library/think/console/Output.php
deleted file mode 100644
index 44eba7a5..00000000
--- a/core/library/think/console/Output.php
+++ /dev/null
@@ -1,86 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console;
-
-use think\console\output\Formatter;
-use think\console\output\Stream;
-
-class Output extends Stream
-{
-
- /** @var Stream */
- private $stderr;
-
- public function __construct()
- {
- $outputStream = 'php://stdout';
- if (!$this->hasStdoutSupport()) {
- $outputStream = 'php://output';
- }
-
- parent::__construct(fopen($outputStream, 'w'));
-
- $this->stderr = new Stream(fopen('php://stderr', 'w'), $this->getFormatter());
- }
-
- /**
- * {@inheritdoc}
- */
- public function setDecorated($decorated)
- {
- parent::setDecorated($decorated);
- $this->stderr->setDecorated($decorated);
- }
-
- /**
- * {@inheritdoc}
- */
- public function setFormatter(Formatter $formatter)
- {
- parent::setFormatter($formatter);
- $this->stderr->setFormatter($formatter);
- }
-
- /**
- * {@inheritdoc}
- */
- public function setVerbosity($level)
- {
- parent::setVerbosity($level);
- $this->stderr->setVerbosity($level);
- }
-
- /**
- * {@inheritdoc}
- */
- public function getErrorOutput()
- {
- return $this->stderr;
- }
-
- /**
- * {@inheritdoc}
- */
- public function setErrorOutput(Output $error)
- {
- $this->stderr = $error;
- }
-
- /**
- * 检查当前环境是否支持控制台输出写入标准输出。
- * @return bool
- */
- protected function hasStdoutSupport()
- {
- return ('OS400' != php_uname('s'));
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/bin/README.md b/core/library/think/console/bin/README.md
deleted file mode 100644
index 9acc52fb..00000000
--- a/core/library/think/console/bin/README.md
+++ /dev/null
@@ -1 +0,0 @@
-console 工具使用 hiddeninput.exe 在 windows 上隐藏密码输入,该二进制文件由第三方提供,相关源码和其他细节可以在 [Hidden Input](https://github.com/Seldaek/hidden-input) 找到。
diff --git a/core/library/think/console/bin/hiddeninput.exe b/core/library/think/console/bin/hiddeninput.exe
deleted file mode 100644
index c8cf65e8..00000000
Binary files a/core/library/think/console/bin/hiddeninput.exe and /dev/null differ
diff --git a/core/library/think/console/command/Build.php b/core/library/think/console/command/Build.php
deleted file mode 100644
index 9c86060c..00000000
--- a/core/library/think/console/command/Build.php
+++ /dev/null
@@ -1,55 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\command;
-
-use think\console\Input;
-use think\console\input\Option;
-use think\console\Output;
-
-class Build extends Command
-{
-
- /**
- * {@inheritdoc}
- */
- protected function configure()
- {
- $this->setName('build')
- ->setDefinition([
- new Option('config', null, Option::VALUE_OPTIONAL, "build.php path"),
- new Option('module', null, Option::VALUE_OPTIONAL, "module name")
- ])
- ->setDescription('Build Application Dirs');
- }
-
- protected function execute(Input $input, Output $output)
- {
- if ($input->hasOption('module')) {
- \think\Build::module($input->getOption('module'));
- $output->writeln("Successed");
- return;
- }
-
- if ($input->hasOption('config')) {
- $build = include $input->getOption('config');
- } else {
- $build = include APP_PATH . 'build.php';
- }
- if (empty($build)) {
- $output->writeln("Build Config Is Empty");
- return;
- }
- \think\Build::run($build);
- $output->writeln("Successed");
-
- }
-}
diff --git a/core/library/think/console/command/Command.php b/core/library/think/console/command/Command.php
deleted file mode 100644
index 82237593..00000000
--- a/core/library/think/console/command/Command.php
+++ /dev/null
@@ -1,501 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\command;
-
-use think\Console;
-use think\console\Input;
-use think\console\input\Argument;
-use think\console\input\Definition;
-use think\console\helper\Set as HelperSet;
-use think\console\input\Option;
-use think\console\Output;
-
-class Command
-{
-
- /** @var Console */
- private $console;
- private $name;
- private $aliases = [];
- private $definition;
- private $help;
- private $description;
- private $ignoreValidationErrors = false;
- private $consoleDefinitionMerged = false;
- private $consoleDefinitionMergedWithArgs = false;
- private $code;
- private $synopsis = [];
- private $usages = [];
-
- /** @var HelperSet */
- private $helperSet;
-
- /**
- * 构造方法
- * @param string|null $name 命令名称,如果没有设置则比如在 configure() 里设置
- * @throws \LogicException
- * @api
- */
- public function __construct($name = null)
- {
- $this->definition = new Definition();
-
- if (null !== $name) {
- $this->setName($name);
- }
-
- $this->configure();
-
- if (!$this->name) {
- throw new \LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
- }
- }
-
- /**
- * 忽略验证错误
- */
- public function ignoreValidationErrors()
- {
- $this->ignoreValidationErrors = true;
- }
-
- /**
- * 设置控制台
- * @param Console $console
- */
- public function setConsole(Console $console = null)
- {
- $this->console = $console;
- if ($console) {
- $this->setHelperSet($console->getHelperSet());
- } else {
- $this->helperSet = null;
- }
- }
-
- /**
- * 设置帮助集
- * @param HelperSet $helperSet
- */
- public function setHelperSet(HelperSet $helperSet)
- {
- $this->helperSet = $helperSet;
- }
-
- /**
- * 获取帮助集
- * @return HelperSet
- */
- public function getHelperSet()
- {
- return $this->helperSet;
- }
-
- /**
- * 获取控制台
- * @return Console
- * @api
- */
- public function getConsole()
- {
- return $this->console;
- }
-
- /**
- * 是否有效
- * @return bool
- */
- public function isEnabled()
- {
- return true;
- }
-
- /**
- * 配置指令
- */
- protected function configure()
- {
- }
-
- /**
- * 执行指令
- * @param Input $input
- * @param Output $output
- * @return null|int
- * @throws \LogicException
- * @see setCode()
- */
- protected function execute(Input $input, Output $output)
- {
- throw new \LogicException('You must override the execute() method in the concrete command class.');
- }
-
- /**
- * 用户验证
- * @param Input $input
- * @param Output $output
- */
- protected function interact(Input $input, Output $output)
- {
- }
-
- /**
- * 初始化
- * @param Input $input An InputInterface instance
- * @param Output $output An OutputInterface instance
- */
- protected function initialize(Input $input, Output $output)
- {
- }
-
- /**
- * 执行
- * @param Input $input
- * @param Output $output
- * @return int
- * @throws \Exception
- * @see setCode()
- * @see execute()
- */
- public function run(Input $input, Output $output)
- {
- $this->getSynopsis(true);
- $this->getSynopsis(false);
-
- $this->mergeConsoleDefinition();
-
- try {
- $input->bind($this->definition);
- } catch (\Exception $e) {
- if (!$this->ignoreValidationErrors) {
- throw $e;
- }
- }
-
- $this->initialize($input, $output);
-
- if ($input->isInteractive()) {
- $this->interact($input, $output);
- }
-
- $input->validate();
-
- if ($this->code) {
- $statusCode = call_user_func($this->code, $input, $output);
- } else {
- $statusCode = $this->execute($input, $output);
- }
-
- return is_numeric($statusCode) ? (int)$statusCode : 0;
- }
-
- /**
- * 设置执行代码
- * @param callable $code callable(InputInterface $input, OutputInterface $output)
- * @return Command
- * @throws \InvalidArgumentException
- * @see execute()
- */
- public function setCode(callable $code)
- {
- if (!is_callable($code)) {
- throw new \InvalidArgumentException('Invalid callable provided to Command::setCode.');
- }
-
- if (PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
- $r = new \ReflectionFunction($code);
- if (null === $r->getClosureThis()) {
- $code = \Closure::bind($code, $this);
- }
- }
-
- $this->code = $code;
-
- return $this;
- }
-
- /**
- * 合并参数定义
- * @param bool $mergeArgs
- */
- public function mergeConsoleDefinition($mergeArgs = true)
- {
- if (null === $this->console
- || (true === $this->consoleDefinitionMerged
- && ($this->consoleDefinitionMergedWithArgs || !$mergeArgs))
- ) {
- return;
- }
-
- if ($mergeArgs) {
- $currentArguments = $this->definition->getArguments();
- $this->definition->setArguments($this->console->getDefinition()->getArguments());
- $this->definition->addArguments($currentArguments);
- }
-
- $this->definition->addOptions($this->console->getDefinition()->getOptions());
-
- $this->consoleDefinitionMerged = true;
- if ($mergeArgs) {
- $this->consoleDefinitionMergedWithArgs = true;
- }
- }
-
- /**
- * 设置参数定义
- * @param array|Definition $definition
- * @return Command
- * @api
- */
- public function setDefinition($definition)
- {
- if ($definition instanceof Definition) {
- $this->definition = $definition;
- } else {
- $this->definition->setDefinition($definition);
- }
-
- $this->consoleDefinitionMerged = false;
-
- return $this;
- }
-
- /**
- * 获取参数定义
- * @return Definition
- * @api
- */
- public function getDefinition()
- {
- return $this->definition;
- }
-
- /**
- * 获取当前指令的参数定义
- * @return Definition
- */
- public function getNativeDefinition()
- {
- return $this->getDefinition();
- }
-
- /**
- * 添加参数
- * @param string $name 名称
- * @param int $mode 类型
- * @param string $description 描述
- * @param mixed $default 默认值
- * @return Command
- */
- public function addArgument($name, $mode = null, $description = '', $default = null)
- {
- $this->definition->addArgument(new Argument($name, $mode, $description, $default));
-
- return $this;
- }
-
- /**
- * 添加选项
- * @param string $name 选项名称
- * @param string $shortcut 别名
- * @param int $mode 类型
- * @param string $description 描述
- * @param mixed $default 默认值
- * @return Command
- */
- public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
- {
- $this->definition->addOption(new Option($name, $shortcut, $mode, $description, $default));
-
- return $this;
- }
-
- /**
- * 设置指令名称
- * @param string $name
- * @return Command
- * @throws \InvalidArgumentException
- */
- public function setName($name)
- {
- $this->validateName($name);
-
- $this->name = $name;
-
- return $this;
- }
-
- /**
- * 获取指令名称
- * @return string
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * 设置描述
- * @param string $description
- * @return Command
- */
- public function setDescription($description)
- {
- $this->description = $description;
-
- return $this;
- }
-
- /**
- * 获取描述
- * @return string
- */
- public function getDescription()
- {
- return $this->description;
- }
-
- /**
- * 设置帮助信息
- * @param string $help
- * @return Command
- */
- public function setHelp($help)
- {
- $this->help = $help;
-
- return $this;
- }
-
- /**
- * 获取帮助信息
- * @return string
- */
- public function getHelp()
- {
- return $this->help;
- }
-
-
- /**
- * 描述信息
- * @return string
- */
- public function getProcessedHelp()
- {
- $name = $this->name;
-
- $placeholders = [
- '%command.name%',
- '%command.full_name%',
- ];
- $replacements = [
- $name,
- $_SERVER['PHP_SELF'] . ' ' . $name,
- ];
-
- return str_replace($placeholders, $replacements, $this->getHelp());
- }
-
- /**
- * 设置别名
- * @param string[] $aliases
- * @return Command
- * @throws \InvalidArgumentException
- */
- public function setAliases($aliases)
- {
- if (!is_array($aliases) && !$aliases instanceof \Traversable) {
- throw new \InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
- }
-
- foreach ($aliases as $alias) {
- $this->validateName($alias);
- }
-
- $this->aliases = $aliases;
-
- return $this;
- }
-
- /**
- * 获取别名
- * @return array
- */
- public function getAliases()
- {
- return $this->aliases;
- }
-
- /**
- * 获取简介
- * @param bool $short 是否简单的
- * @return string
- */
- public function getSynopsis($short = false)
- {
- $key = $short ? 'short' : 'long';
-
- if (!isset($this->synopsis[$key])) {
- $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
- }
-
- return $this->synopsis[$key];
- }
-
- /**
- * 添加用法介绍
- * @param string $usage
- */
- public function addUsage($usage)
- {
- if (0 !== strpos($usage, $this->name)) {
- $usage = sprintf('%s %s', $this->name, $usage);
- }
-
- $this->usages[] = $usage;
-
- return $this;
- }
-
- /**
- * 获取用法介绍
- * @return array
- */
- public function getUsages()
- {
- return $this->usages;
- }
-
- /**
- * 获取助手
- * @param string $name
- * @return mixed
- * @throws \InvalidArgumentException
- */
- public function getHelper($name)
- {
- return $this->helperSet->get($name);
- }
-
- /**
- * 验证指令名称
- * @param string $name
- * @throws \InvalidArgumentException
- */
- private function validateName($name)
- {
- if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
- throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
- }
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/command/Help.php b/core/library/think/console/command/Help.php
deleted file mode 100644
index a7bcaade..00000000
--- a/core/library/think/console/command/Help.php
+++ /dev/null
@@ -1,71 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\command;
-
-use think\console\Input;
-use think\console\input\Argument as InputArgument;
-use think\console\input\Option as InputOption;
-use think\console\Output;
-use think\console\helper\Descriptor as DescriptorHelper;
-
-class Help extends Command
-{
-
- private $command;
-
- /**
- * {@inheritdoc}
- */
- protected function configure()
- {
- $this->ignoreValidationErrors();
-
- $this->setName('help')->setDefinition([
- new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
- new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
- ])->setDescription('Displays help for a command')->setHelp(<<%command.name% command displays help for a given command:
-
- php %command.full_name% list
-
-To display the list of available commands, please use the list command.
-EOF
- );
- }
-
- /**
- * Sets the command.
- * @param Command $command The command to set
- */
- public function setCommand(Command $command)
- {
- $this->command = $command;
- }
-
- /**
- * {@inheritdoc}
- */
- protected function execute(Input $input, Output $output)
- {
- if (null === $this->command) {
- $this->command = $this->getConsole()->find($input->getArgument('command_name'));
- }
-
-
- $helper = new DescriptorHelper();
- $helper->describe($output, $this->command, [
- 'raw_text' => $input->getOption('raw'),
- ]);
-
- $this->command = null;
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/command/Lists.php b/core/library/think/console/command/Lists.php
deleted file mode 100644
index 0eac10d5..00000000
--- a/core/library/think/console/command/Lists.php
+++ /dev/null
@@ -1,77 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\command;
-
-
-use think\console\Input;
-use think\console\Output;
-use think\console\input\Argument as InputArgument;
-use think\console\input\Option as InputOption;
-use think\console\input\Definition as InputDefinition;
-use think\console\helper\Descriptor as DescriptorHelper;
-
-class Lists extends Command
-{
-
- /**
- * {@inheritdoc}
- */
- protected function configure()
- {
- $this->setName('list')->setDefinition($this->createDefinition())->setDescription('Lists commands')->setHelp(<<%command.name% command lists all commands:
-
- php %command.full_name%
-
-You can also display the commands for a specific namespace:
-
- php %command.full_name% test
-
-It's also possible to get raw list of commands (useful for embedding command runner):
-
- php %command.full_name% --raw
-EOF
- );
- }
-
- /**
- * {@inheritdoc}
- */
- public function getNativeDefinition()
- {
- return $this->createDefinition();
- }
-
- /**
- * {@inheritdoc}
- */
- protected function execute(Input $input, Output $output)
- {
-
- $helper = new DescriptorHelper();
- $helper->describe($output, $this->getConsole(), [
- 'raw_text' => $input->getOption('raw'),
- 'namespace' => $input->getArgument('namespace'),
- ]);
- }
-
- /**
- * {@inheritdoc}
- */
- private function createDefinition()
- {
- return new InputDefinition([
- new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
- new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list')
- ]);
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/command/Make.php b/core/library/think/console/command/Make.php
deleted file mode 100644
index 928976c2..00000000
--- a/core/library/think/console/command/Make.php
+++ /dev/null
@@ -1,47 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\command;
-
-class Make extends Command
-{
- // 创建目录
- protected static function buildDir($dir)
- {
- if (!is_dir(APP_PATH . $dir)) {
- mkdir(APP_PATH . strtolower($dir), 0777, true);
- }
- }
-
- // 创建文件
- protected static function buildFile($file, $content)
- {
- if (is_file(APP_PATH . $file)) {
- exception('file already exists');
- }
- file_put_contents(APP_PATH . $file, $content);
- }
-
- protected static function formatNameSpace($namespace)
- {
- $namespace = explode('\\', $namespace);
-
- foreach ($namespace as $key => $value) {
- if ($key == count($namespace) - 1) {
- $newNameSpace[1] = $value;
- } else {
- $newNameSpace[0][$key] = $value;
- }
- }
-
- return $newNameSpace;
- }
-}
diff --git a/core/library/think/console/command/make/Controller.php b/core/library/think/console/command/make/Controller.php
deleted file mode 100644
index 5f41e171..00000000
--- a/core/library/think/console/command/make/Controller.php
+++ /dev/null
@@ -1,95 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\command\make;
-
-use think\App;
-use think\console\Input;
-use think\console\input\Argument;
-use think\console\input\Option;
-use think\console\Output;
-
-class Controller extends \think\console\command\Make
-{
- /**
- * {@inheritdoc}
- */
- protected function configure()
- {
- $this
- ->setName('make:controller')
- ->setDescription('Create a new controller class')
- ->addArgument('namespace', Argument::OPTIONAL, null)
- ->addOption('module', 'm', Option::VALUE_OPTIONAL, 'Module Name', null)
- ->addOption('extend', 'e', Option::VALUE_OPTIONAL, 'Base on Controller class', null);
- }
-
- protected function execute(Input $input, Output $output)
- {
- $namespace = $input->getArgument('namespace');
- $module = $input->getOption('module');
-
-
- // 处理命名空间
- if (!empty($module)) {
- $namespace = App::$namespace . "\\" . $module . "\\" . 'controller' . "\\" . $namespace;
- }
-
- // 处理继承
- $extend = $input->getOption('extend');
-
- if (empty($extend)) {
- $extend = "\\think\\Controller";
- } else {
- if (!preg_match("/\\\/", $extend)) {
- if (!empty($module)) {
- $extend = "\\" . App::$namespace . "\\" . $module . "\\" . 'controller' . "\\" . $extend;
- }
- }
- }
-
-
- $result = $this->build($namespace, $extend);
- $output->writeln("output:" . $result);
- }
-
- private function build($namespace, $extend)
- {
- $tpl = file_get_contents(THINK_PATH . 'tpl' . DS . 'make_controller.tpl');
-
- // comminute namespace
- $allNamespace = self::formatNameSpace($namespace);
- $namespace = implode('\\', $allNamespace[0]);
- $className = ucwords($allNamespace[1]);
-
- // 处理内容
- $content = str_replace("{%extend%}", $extend,
- str_replace("{%className%}", $className,
- str_replace("{%namespace%}", $namespace, $tpl)
- )
- );
-
- // 处理文件夹
- $path = '';
- foreach ($allNamespace[0] as $key => $value) {
- if ($key >= 1) {
- self::buildDir($path . $value);
- $path .= $value . "\\";
- }
- }
-
- // 处理文件
- $file = $path . $className . '.php';
- self::buildFile($file, $content);
-
- return APP_PATH . $file;
- }
-}
diff --git a/core/library/think/console/command/make/Model.php b/core/library/think/console/command/make/Model.php
deleted file mode 100644
index ef36c18f..00000000
--- a/core/library/think/console/command/make/Model.php
+++ /dev/null
@@ -1,26 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\command\make;
-
-
-use think\console\command\Command;
-
-
-class Model extends Command
-{
-
- public function __construct()
- {
- parent::__construct("make:model");
- }
-
-}
\ No newline at end of file
diff --git a/core/library/think/console/helper/Debug.php b/core/library/think/console/helper/Debug.php
deleted file mode 100644
index 163b86d5..00000000
--- a/core/library/think/console/helper/Debug.php
+++ /dev/null
@@ -1,114 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\helper;
-
-class Debug extends Helper
-{
-
- private $colors = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'];
- private $started = [];
- private $count = -1;
-
- /**
- * 启动调试会话的格式
- * @param string $id 会话的 id
- * @param string $message 要显示的消息
- * @param string $prefix 要使用的前缀
- * @return string
- */
- public function start($id, $message, $prefix = 'RUN')
- {
- $this->started[$id] = ['border' => ++$this->count % count($this->colors)];
-
- return sprintf("%s %s > %s>\n", $this->getBorder($id), $prefix, $message);
- }
-
- /**
- * 添加设置会话的进度条格式
- * @param string $id 会话的 id
- * @param string $buffer 要显示的消息
- * @param bool $error 是否输出错误
- * @param string $prefix 输出的前缀
- * @param string $errorPrefix 输出错误的前缀
- * @return string
- */
- public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
- {
- $message = '';
-
- if ($error) {
- if (isset($this->started[$id]['out'])) {
- $message .= "\n";
- unset($this->started[$id]['out']);
- }
- if (!isset($this->started[$id]['err'])) {
- $message .= sprintf("%s %s > ", $this->getBorder($id), $errorPrefix);
- $this->started[$id]['err'] = true;
- }
-
- $message .= str_replace("\n", sprintf("\n%s %s > ", $this->getBorder($id), $errorPrefix), $buffer);
- } else {
- if (isset($this->started[$id]['err'])) {
- $message .= "\n";
- unset($this->started[$id]['err']);
- }
- if (!isset($this->started[$id]['out'])) {
- $message .= sprintf("%s %s > ", $this->getBorder($id), $prefix);
- $this->started[$id]['out'] = true;
- }
-
- $message .= str_replace("\n", sprintf("\n%s %s > ", $this->getBorder($id), $prefix), $buffer);
- }
-
- return $message;
- }
-
- /**
- * 停止一个会话
- * @param string $id 会话的 id
- * @param string $message 要显示的消息
- * @param bool $successful 是否显示成功消息
- * @param string $prefix 前缀
- * @return string
- */
- public function stop($id, $message, $successful, $prefix = 'RES')
- {
- $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
-
- if ($successful) {
- return sprintf("%s%s %s > %s>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
- }
-
- $message = sprintf("%s%s %s > %s>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
-
- unset($this->started[$id]['out'], $this->started[$id]['err']);
-
- return $message;
- }
-
- /**
- * @param string $id
- * @return string
- */
- private function getBorder($id)
- {
- return sprintf(' >', $this->colors[$this->started[$id]['border']]);
- }
-
- /**
- * {@inheritdoc}
- */
- public function getName()
- {
- return 'debug_formatter';
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/helper/Descriptor.php b/core/library/think/console/helper/Descriptor.php
deleted file mode 100644
index 18c0eab8..00000000
--- a/core/library/think/console/helper/Descriptor.php
+++ /dev/null
@@ -1,54 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\helper;
-
-use think\console\helper\descriptor\Descriptor as OutputDescriptor;
-use think\console\Output;
-
-class Descriptor extends Helper
-{
-
- /**
- * @var OutputDescriptor
- */
- private $descriptor;
-
- /**
- * 构造方法
- */
- public function __construct()
- {
- $this->descriptor = new OutputDescriptor();
- }
-
- /**
- * 描述
- * @param Output $output
- * @param object $object
- * @param array $options
- * @throws \InvalidArgumentException
- */
- public function describe(Output $output, $object, array $options = [])
- {
- $options = array_merge([
- 'raw_text' => false
- ], $options);
-
- $this->descriptor->describe($output, $object, $options);
- }
-
- /**
- * {@inheritdoc}
- */
- public function getName()
- {
- return 'descriptor';
- }
-}
diff --git a/core/library/think/console/helper/Formatter.php b/core/library/think/console/helper/Formatter.php
deleted file mode 100644
index 18ce5742..00000000
--- a/core/library/think/console/helper/Formatter.php
+++ /dev/null
@@ -1,74 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\helper;
-
-use think\console\output\Formatter as OutputFormatter;
-
-class Formatter extends Helper
-{
-
- /**
- * 设置消息在某一节的格式
- * @param string $section 节名称
- * @param string $message 消息
- * @param string $style 样式
- * @return string
- */
- public function formatSection($section, $message, $style = 'info')
- {
- return sprintf('<%s>[%s]%s> %s', $style, $section, $style, $message);
- }
-
- /**
- * 设置消息作为文本块的格式
- * @param string|array $messages 消息
- * @param string $style 样式
- * @param bool $large 是否返回一个大段文本
- * @return string The formatter message
- */
- public function formatBlock($messages, $style, $large = false)
- {
- if (!is_array($messages)) {
- $messages = [$messages];
- }
-
- $len = 0;
- $lines = [];
- foreach ($messages as $message) {
- $message = OutputFormatter::escape($message);
- $lines[] = sprintf($large ? ' %s ' : ' %s ', $message);
- $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
- }
-
- $messages = $large ? [str_repeat(' ', $len)] : [];
- for ($i = 0; isset($lines[$i]); ++$i) {
- $messages[] = $lines[$i] . str_repeat(' ', $len - $this->strlen($lines[$i]));
- }
- if ($large) {
- $messages[] = str_repeat(' ', $len);
- }
-
- for ($i = 0; isset($messages[$i]); ++$i) {
- $messages[$i] = sprintf('<%s>%s%s>', $style, $messages[$i], $style);
- }
-
- return implode("\n", $messages);
- }
-
- /**
- * {@inheritdoc}
- */
- public function getName()
- {
- return 'formatter';
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/helper/Helper.php b/core/library/think/console/helper/Helper.php
deleted file mode 100644
index 7b327bdd..00000000
--- a/core/library/think/console/helper/Helper.php
+++ /dev/null
@@ -1,121 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\helper;
-
-use think\console\helper\Set as HelperSet;
-use think\console\output\Formatter;
-
-abstract class Helper
-{
-
- protected $helperSet = null;
-
- /**
- * 设置与此助手关联的助手集。
- * @param HelperSet $helperSet
- */
- public function setHelperSet(HelperSet $helperSet = null)
- {
- $this->helperSet = $helperSet;
- }
-
- /**
- * 获取与此助手关联的助手集。
- * @return HelperSet
- */
- public function getHelperSet()
- {
- return $this->helperSet;
- }
-
- /**
- * 获取名称
- * @return string
- */
- abstract public function getName();
-
- /**
- * 返回字符串的长度
- * @param string $string
- * @return int
- */
- public static function strlen($string)
- {
- if (!function_exists('mb_strwidth')) {
- return strlen($string);
- }
-
- if (false === $encoding = mb_detect_encoding($string)) {
- return strlen($string);
- }
-
- return mb_strwidth($string, $encoding);
- }
-
- public static function formatTime($secs)
- {
- static $timeFormats = [
- [0, '< 1 sec'],
- [2, '1 sec'],
- [59, 'secs', 1],
- [60, '1 min'],
- [3600, 'mins', 60],
- [5400, '1 hr'],
- [86400, 'hrs', 3600],
- [129600, '1 day'],
- [604800, 'days', 86400],
- ];
-
- foreach ($timeFormats as $format) {
- if ($secs >= $format[0]) {
- continue;
- }
-
- if (2 == count($format)) {
- return $format[1];
- }
-
- return ceil($secs / $format[2]) . ' ' . $format[1];
- }
- return null;
- }
-
- public static function formatMemory($memory)
- {
- if ($memory >= 1024 * 1024 * 1024) {
- return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
- }
-
- if ($memory >= 1024 * 1024) {
- return sprintf('%.1f MiB', $memory / 1024 / 1024);
- }
-
- if ($memory >= 1024) {
- return sprintf('%d KiB', $memory / 1024);
- }
-
- return sprintf('%d B', $memory);
- }
-
- public static function strlenWithoutDecoration(Formatter $formatter, $string)
- {
- $isDecorated = $formatter->isDecorated();
- $formatter->setDecorated(false);
- // remove <...> formatting
- $string = $formatter->format($string);
- // remove already formatted characters
- $string = preg_replace("/\033\[[^m]*m/", '', $string);
- $formatter->setDecorated($isDecorated);
-
- return self::strlen($string);
- }
-}
diff --git a/core/library/think/console/helper/Process.php b/core/library/think/console/helper/Process.php
deleted file mode 100644
index 4252bfe3..00000000
--- a/core/library/think/console/helper/Process.php
+++ /dev/null
@@ -1,118 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\helper;
-
-use think\console\Output;
-use think\Process as ThinkProcess;
-use think\process\Builder as ProcessBuilder;
-use think\process\exception\Failed as ProcessFailedException;
-
-class Process extends Helper
-{
-
- /**
- * 运行一个外部进程。
- * @param Output $output 一个Output实例
- * @param string|array|ThinkProcess $cmd 指令
- * @param string|null $error 错误信息
- * @param callable|null $callback 回调
- * @param int $verbosity
- * @return ThinkProcess
- */
- public function run(Output $output, $cmd, $error = null, $callback = null, $verbosity = Output::VERBOSITY_VERY_VERBOSE)
- {
- /** @var Debug $formatter */
- $formatter = $this->getHelperSet()->get('debug_formatter');
-
- if (is_array($cmd)) {
- $process = ProcessBuilder::create($cmd)->getProcess();
- } elseif ($cmd instanceof ThinkProcess) {
- $process = $cmd;
- } else {
- $process = new ThinkProcess($cmd);
- }
-
- if ($verbosity <= $output->getVerbosity()) {
- $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
- }
-
- if ($output->isDebug()) {
- $callback = $this->wrapCallback($output, $process, $callback);
- }
-
- $process->run($callback);
-
- if ($verbosity <= $output->getVerbosity()) {
- $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
- $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
- }
-
- if (!$process->isSuccessful() && null !== $error) {
- $output->writeln(sprintf('%s', $this->escapeString($error)));
- }
-
- return $process;
- }
-
- /**
- * 运行指令
- * @param Output $output
- * @param string|ThinkProcess $cmd
- * @param string|null $error
- * @param callable|null $callback
- * @return ThinkProcess
- */
- public function mustRun(Output $output, $cmd, $error = null, $callback = null)
- {
- $process = $this->run($output, $cmd, $error, $callback);
-
- if (!$process->isSuccessful()) {
- throw new ProcessFailedException($process);
- }
-
- return $process;
- }
-
- /**
- * 包装过程回调来添加调试输出
- * @param Output $output
- * @param ThinkProcess $process
- * @param callable|null $callback
- * @return callable
- */
- public function wrapCallback(Output $output, ThinkProcess $process, $callback = null)
- {
- /** @var Debug $formatter */
- $formatter = $this->getHelperSet()->get('debug_formatter');
-
- return function ($type, $buffer) use ($output, $process, $callback, $formatter) {
- $output->write($formatter->progress(spl_object_hash($process), $this->escapeString($buffer), ThinkProcess::ERR === $type));
-
- if (null !== $callback) {
- call_user_func($callback, $type, $buffer);
- }
- };
- }
-
- private function escapeString($str)
- {
- return str_replace('<', '\\<', $str);
- }
-
- /**
- * {@inheritdoc}
- */
- public function getName()
- {
- return 'process';
- }
-}
diff --git a/core/library/think/console/helper/Question.php b/core/library/think/console/helper/Question.php
deleted file mode 100644
index e1820834..00000000
--- a/core/library/think/console/helper/Question.php
+++ /dev/null
@@ -1,394 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\helper;
-
-use think\console\helper\question\Choice as ChoiceQuestion;
-use think\console\helper\question\Question as OutputQuestion;
-use think\console\Input;
-use think\console\Output;
-use think\console\output\formatter\Style as OutputFormatterStyle;
-
-class Question extends Helper
-{
-
- private $inputStream;
- private static $shell;
- private static $stty;
-
- /**
- * 向用户提问
- * @param Input $input
- * @param Output $output
- * @param OutputQuestion $question
- * @return string
- */
- public function ask(Input $input, Output $output, OutputQuestion $question)
- {
- if (!$input->isInteractive()) {
- return $question->getDefault();
- }
-
- if (!$question->getValidator()) {
- return $this->doAsk($output, $question);
- }
-
- $interviewer = function () use ($output, $question) {
- return $this->doAsk($output, $question);
- };
-
- return $this->validateAttempts($interviewer, $output, $question);
- }
-
- /**
- * 设置输入流
- * @param resource $stream
- * @throws \InvalidArgumentException
- */
- public function setInputStream($stream)
- {
- if (!is_resource($stream)) {
- throw new \InvalidArgumentException('Input stream must be a valid resource.');
- }
-
- $this->inputStream = $stream;
- }
-
- /**
- * 获取输入流
- * @return resource
- */
- public function getInputStream()
- {
- return $this->inputStream;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getName()
- {
- return 'question';
- }
-
- /**
- * 提问
- * @param Output $output
- * @param OutputQuestion $question
- * @return bool|mixed|null|string
- * @throws \Exception
- * @throws \RuntimeException
- */
- private function doAsk(Output $output, OutputQuestion $question)
- {
- $this->writePrompt($output, $question);
-
- $inputStream = $this->inputStream ?: STDIN;
- $autocomplete = $question->getAutocompleterValues();
-
- if (null === $autocomplete || !$this->hasSttyAvailable()) {
- $ret = false;
- if ($question->isHidden()) {
- try {
- $ret = trim($this->getHiddenResponse($output, $inputStream));
- } catch (\RuntimeException $e) {
- if (!$question->isHiddenFallback()) {
- throw $e;
- }
- }
- }
-
- if (false === $ret) {
- $ret = fgets($inputStream, 4096);
- if (false === $ret) {
- throw new \RuntimeException('Aborted');
- }
- $ret = trim($ret);
- }
- } else {
- $ret = trim($this->autocomplete($output, $question, $inputStream));
- }
-
- $ret = strlen($ret) > 0 ? $ret : $question->getDefault();
-
- if ($normalizer = $question->getNormalizer()) {
- return $normalizer($ret);
- }
-
- return $ret;
- }
-
- /**
- * 显示提示
- * @param Output $output
- * @param OutputQuestion $question
- */
- protected function writePrompt(Output $output, OutputQuestion $question)
- {
- $message = $question->getQuestion();
-
- if ($question instanceof ChoiceQuestion) {
- $width = max(array_map('strlen', array_keys($question->getChoices())));
-
- $messages = (array) $question->getQuestion();
- foreach ($question->getChoices() as $key => $value) {
- $messages[] = sprintf(" [%-${width}s] %s", $key, $value);
- }
-
- $output->writeln($messages);
-
- $message = $question->getPrompt();
- }
-
- $output->write($message);
- }
-
- /**
- * 输出错误
- * @param Output $output
- * @param \Exception $error
- */
- protected function writeError(Output $output, \Exception $error)
- {
- if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
- $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
- } else {
- $message = '' . $error->getMessage() . '';
- }
-
- $output->writeln($message);
- }
-
- /**
- * 自动完成问题
- * @param Output $output
- * @param OutputQuestion $question
- * @param $inputStream
- * @return string
- */
- private function autocomplete(Output $output, OutputQuestion $question, $inputStream)
- {
- $autocomplete = $question->getAutocompleterValues();
- $ret = '';
-
- $i = 0;
- $ofs = -1;
- $matches = $autocomplete;
- $numMatches = count($matches);
-
- $sttyMode = shell_exec('stty -g');
-
- shell_exec('stty -icanon -echo');
-
- $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
-
- while (!feof($inputStream)) {
- $c = fread($inputStream, 1);
-
- if ("\177" === $c) {
- if (0 === $numMatches && 0 !== $i) {
- $i--;
- $output->write("\033[1D");
- }
-
- if (0 === $i) {
- $ofs = -1;
- $matches = $autocomplete;
- $numMatches = count($matches);
- } else {
- $numMatches = 0;
- }
-
- $ret = substr($ret, 0, $i);
- } elseif ("\033" === $c) {
- $c .= fread($inputStream, 2);
-
- if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
- if ('A' === $c[2] && -1 === $ofs) {
- $ofs = 0;
- }
-
- if (0 === $numMatches) {
- continue;
- }
-
- $ofs += ('A' === $c[2]) ? -1 : 1;
- $ofs = ($numMatches + $ofs) % $numMatches;
- }
- } elseif (ord($c) < 32) {
- if ("\t" === $c || "\n" === $c) {
- if ($numMatches > 0 && -1 !== $ofs) {
- $ret = $matches[$ofs];
- $output->write(substr($ret, $i));
- $i = strlen($ret);
- }
-
- if ("\n" === $c) {
- $output->write($c);
- break;
- }
-
- $numMatches = 0;
- }
-
- continue;
- } else {
- $output->write($c);
- $ret .= $c;
- $i++;
-
- $numMatches = 0;
- $ofs = 0;
-
- foreach ($autocomplete as $value) {
- if (0 === strpos($value, $ret) && strlen($value) !== $i) {
- $matches[$numMatches++] = $value;
- }
- }
- }
-
- $output->write("\033[K");
-
- if ($numMatches > 0 && -1 !== $ofs) {
- $output->write("\0337");
- $output->write('' . substr($matches[$ofs], $i) . '');
- $output->write("\0338");
- }
- }
-
- shell_exec(sprintf('stty %s', $sttyMode));
-
- return $ret;
- }
-
- /**
- * 从用户获取隐藏的响应
- * @param Output $output
- * @return string
- * @throws \RuntimeException
- */
- private function getHiddenResponse(Output $output, $inputStream)
- {
- if ('\\' === DS) {
- $exe = __DIR__ . '/../bin/hiddeninput.exe';
-
- if ('phar:' === substr(__FILE__, 0, 5)) {
- $tmpExe = sys_get_temp_dir() . '/hiddeninput.exe';
- copy($exe, $tmpExe);
- $exe = $tmpExe;
- }
-
- $value = rtrim(shell_exec($exe));
- $output->writeln('');
-
- if (isset($tmpExe)) {
- unlink($tmpExe);
- }
-
- return $value;
- }
-
- if ($this->hasSttyAvailable()) {
- $sttyMode = shell_exec('stty -g');
-
- shell_exec('stty -echo');
- $value = fgets($inputStream, 4096);
- shell_exec(sprintf('stty %s', $sttyMode));
-
- if (false === $value) {
- throw new \RuntimeException('Aborted');
- }
-
- $value = trim($value);
- $output->writeln('');
-
- return $value;
- }
-
- if (false !== $shell = $this->getShell()) {
- $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
- $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
- $value = rtrim(shell_exec($command));
- $output->writeln('');
-
- return $value;
- }
-
- throw new \RuntimeException('Unable to hide the response.');
- }
-
- /**
- * 验证重试次数
- * @param callable $interviewer
- * @param Output $output
- * @param OutputQuestion $question
- * @return string
- * @throws null
- */
- private function validateAttempts($interviewer, Output $output, OutputQuestion $question)
- {
- $error = null;
- $attempts = $question->getMaxAttempts();
- while (null === $attempts || $attempts--) {
- if (null !== $error) {
- $this->writeError($output, $error);
- }
-
- try {
- return call_user_func($question->getValidator(), $interviewer());
- } catch (\Exception $error) {
- }
- }
-
- throw $error;
- }
-
- /**
- * 获取一个有效的 unix 终端。
- * @return string|bool
- */
- private function getShell()
- {
- if (null !== self::$shell) {
- return self::$shell;
- }
-
- self::$shell = false;
-
- if (file_exists('/usr/bin/env')) {
- // handle other OSs with bash/zsh/ksh/csh if available to hide the answer
- $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
- foreach (['bash', 'zsh', 'ksh', 'csh'] as $sh) {
- if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
- self::$shell = $sh;
- break;
- }
- }
- }
-
- return self::$shell;
- }
-
- /**
- * 检查有用的stty
- * @return bool
- */
- private function hasSttyAvailable()
- {
- if (null !== self::$stty) {
- return self::$stty;
- }
-
- exec('stty 2>&1', $output, $exitcode);
-
- return self::$stty = 0 === $exitcode;
- }
-}
diff --git a/core/library/think/console/helper/Set.php b/core/library/think/console/helper/Set.php
deleted file mode 100644
index 63ea58e4..00000000
--- a/core/library/think/console/helper/Set.php
+++ /dev/null
@@ -1,99 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\helper;
-
-use think\console\command\Command;
-
-class Set implements \IteratorAggregate
-{
-
- private $helpers = [];
- private $command;
-
- /**
- * 构造方法
- * @param Helper[] $helpers 助手实例数组
- */
- public function __construct(array $helpers = [])
- {
- /**
- * @var int|string $alias
- * @var Helper $helper
- */
- foreach ($helpers as $alias => $helper) {
- $this->set($helper, is_int($alias) ? null : $alias);
- }
- }
-
- /**
- * 添加一个助手
- * @param Helper $helper 助手实例
- * @param string $alias 别名
- */
- public function set(Helper $helper, $alias = null)
- {
- $this->helpers[$helper->getName()] = $helper;
- if (null !== $alias) {
- $this->helpers[$alias] = $helper;
- }
-
- $helper->setHelperSet($this);
- }
-
- /**
- * 是否有某个助手
- * @param string $name 助手名称
- * @return bool
- */
- public function has($name)
- {
- return isset($this->helpers[$name]);
- }
-
- /**
- * 获取助手
- * @param string $name 助手名称
- * @return Helper
- * @throws \InvalidArgumentException
- */
- public function get($name)
- {
- if (!$this->has($name)) {
- throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
- }
-
- return $this->helpers[$name];
- }
-
- /**
- * 设置与这个助手关联的命令集
- * @param Command $command
- */
- public function setCommand(Command $command = null)
- {
- $this->command = $command;
- }
-
- /**
- * 获取与这个助手关联的命令集
- * @return Command
- */
- public function getCommand()
- {
- return $this->command;
- }
-
- public function getIterator()
- {
- return new \ArrayIterator($this->helpers);
- }
-}
diff --git a/core/library/think/console/helper/descriptor/Console.php b/core/library/think/console/helper/descriptor/Console.php
deleted file mode 100644
index 168c31fd..00000000
--- a/core/library/think/console/helper/descriptor/Console.php
+++ /dev/null
@@ -1,150 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\helper\descriptor;
-
-
-use think\console\command\Command;
-use think\Console as ThinkConsole;
-
-class Console
-{
-
- const GLOBAL_NAMESPACE = '_global';
-
- /**
- * @var ThinkConsole
- */
- private $console;
-
- /**
- * @var null|string
- */
- private $namespace;
-
- /**
- * @var array
- */
- private $namespaces;
-
- /**
- * @var Command[]
- */
- private $commands;
-
- /**
- * @var Command[]
- */
- private $aliases;
-
- /**
- * 构造方法
- * @param ThinkConsole $console
- * @param string|null $namespace
- */
- public function __construct(ThinkConsole $console, $namespace = null)
- {
- $this->console = $console;
- $this->namespace = $namespace;
- }
-
- /**
- * @return array
- */
- public function getNamespaces()
- {
- if (null === $this->namespaces) {
- $this->inspectConsole();
- }
-
- return $this->namespaces;
- }
-
- /**
- * @return Command[]
- */
- public function getCommands()
- {
- if (null === $this->commands) {
- $this->inspectConsole();
- }
-
- return $this->commands;
- }
-
- /**
- * @param string $name
- * @return Command
- * @throws \InvalidArgumentException
- */
- public function getCommand($name)
- {
- if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
- throw new \InvalidArgumentException(sprintf('Command %s does not exist.', $name));
- }
-
- return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
- }
-
- private function inspectConsole()
- {
- $this->commands = [];
- $this->namespaces = [];
-
- $all = $this->console->all($this->namespace ? $this->console->findNamespace($this->namespace) : null);
- foreach ($this->sortCommands($all) as $namespace => $commands) {
- $names = [];
-
- /** @var Command $command */
- foreach ($commands as $name => $command) {
- if (!$command->getName()) {
- continue;
- }
-
- if ($command->getName() === $name) {
- $this->commands[$name] = $command;
- } else {
- $this->aliases[$name] = $command;
- }
-
- $names[] = $name;
- }
-
- $this->namespaces[$namespace] = ['id' => $namespace, 'commands' => $names];
- }
- }
-
- /**
- * @param array $commands
- * @return array
- */
- private function sortCommands(array $commands)
- {
- $namespacedCommands = [];
- foreach ($commands as $name => $command) {
- $key = $this->console->extractNamespace($name, 1);
- if (!$key) {
- $key = '_global';
- }
-
- $namespacedCommands[$key][$name] = $command;
- }
- ksort($namespacedCommands);
-
- foreach ($namespacedCommands as &$commandsSet) {
- ksort($commandsSet);
- }
- // unset reference to keep scope clear
- unset($commandsSet);
-
- return $namespacedCommands;
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/helper/descriptor/Descriptor.php b/core/library/think/console/helper/descriptor/Descriptor.php
deleted file mode 100644
index b9a96d87..00000000
--- a/core/library/think/console/helper/descriptor/Descriptor.php
+++ /dev/null
@@ -1,319 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\helper\descriptor;
-
-use think\console\Output;
-use think\console\input\Argument as InputArgument;
-use think\console\input\Option as InputOption;
-use think\console\input\Definition as InputDefinition;
-use think\console\command\Command;
-use think\Console;
-use think\console\helper\descriptor\Console as ConsoleDescription;
-
-class Descriptor
-{
-
- /**
- * @var Output
- */
- protected $output;
-
- /**
- * {@inheritdoc}
- */
- public function describe(Output $output, $object, array $options = [])
- {
- $this->output = $output;
-
- switch (true) {
- case $object instanceof InputArgument:
- $this->describeInputArgument($object, $options);
- break;
- case $object instanceof InputOption:
- $this->describeInputOption($object, $options);
- break;
- case $object instanceof InputDefinition:
- $this->describeInputDefinition($object, $options);
- break;
- case $object instanceof Command:
- $this->describeCommand($object, $options);
- break;
- case $object instanceof Console:
- $this->describeConsole($object, $options);
- break;
- default:
- throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
- }
- }
-
- /**
- * 输出内容
- * @param string $content
- * @param bool $decorated
- */
- protected function write($content, $decorated = false)
- {
- $this->output->write($content, false, $decorated ? Output::OUTPUT_NORMAL : Output::OUTPUT_RAW);
- }
-
- /**
- * 描述参数
- * @param InputArgument $argument
- * @param array $options
- * @return string|mixed
- */
- protected function describeInputArgument(InputArgument $argument, array $options = [])
- {
- if (null !== $argument->getDefault()
- && (!is_array($argument->getDefault())
- || count($argument->getDefault()))
- ) {
- $default = sprintf(' [default: %s]', $this->formatDefaultValue($argument->getDefault()));
- } else {
- $default = '';
- }
-
- $totalWidth = isset($options['total_width']) ? $options['total_width'] : strlen($argument->getName());
- $spacingWidth = $totalWidth - strlen($argument->getName()) + 2;
-
- $this->writeText(sprintf(" %s%s%s%s", $argument->getName(), str_repeat(' ', $spacingWidth), // + 17 = 2 spaces + + + 2 spaces
- preg_replace('/\s*\R\s*/', PHP_EOL . str_repeat(' ', $totalWidth + 17), $argument->getDescription()), $default), $options);
- }
-
- /**
- * 描述选项
- * @param InputOption $option
- * @param array $options
- * @return string|mixed
- */
- protected function describeInputOption(InputOption $option, array $options = [])
- {
- if ($option->acceptValue() && null !== $option->getDefault()
- && (!is_array($option->getDefault())
- || count($option->getDefault()))
- ) {
- $default = sprintf(' [default: %s]', $this->formatDefaultValue($option->getDefault()));
- } else {
- $default = '';
- }
-
- $value = '';
- if ($option->acceptValue()) {
- $value = '=' . strtoupper($option->getName());
-
- if ($option->isValueOptional()) {
- $value = '[' . $value . ']';
- }
- }
-
- $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions([$option]);
- $synopsis = sprintf('%s%s', $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ', sprintf('--%s%s', $option->getName(), $value));
-
- $spacingWidth = $totalWidth - strlen($synopsis) + 2;
-
- $this->writeText(sprintf(" %s%s%s%s%s", $synopsis, str_repeat(' ', $spacingWidth), // + 17 = 2 spaces + + + 2 spaces
- preg_replace('/\s*\R\s*/', "\n" . str_repeat(' ', $totalWidth + 17), $option->getDescription()), $default, $option->isArray() ? ' (multiple values allowed)' : ''), $options);
- }
-
- /**
- * 描述输入
- * @param InputDefinition $definition
- * @param array $options
- * @return string|mixed
- */
- protected function describeInputDefinition(InputDefinition $definition, array $options = [])
- {
- $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
- foreach ($definition->getArguments() as $argument) {
- $totalWidth = max($totalWidth, strlen($argument->getName()));
- }
-
- if ($definition->getArguments()) {
- $this->writeText('Arguments:', $options);
- $this->writeText("\n");
- foreach ($definition->getArguments() as $argument) {
- $this->describeInputArgument($argument, array_merge($options, ['total_width' => $totalWidth]));
- $this->writeText("\n");
- }
- }
-
- if ($definition->getArguments() && $definition->getOptions()) {
- $this->writeText("\n");
- }
-
- if ($definition->getOptions()) {
- $laterOptions = [];
-
- $this->writeText('Options:', $options);
- foreach ($definition->getOptions() as $option) {
- if (strlen($option->getShortcut()) > 1) {
- $laterOptions[] = $option;
- continue;
- }
- $this->writeText("\n");
- $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth]));
- }
- foreach ($laterOptions as $option) {
- $this->writeText("\n");
- $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth]));
- }
- }
- }
-
- /**
- * 描述指令
- * @param Command $command
- * @param array $options
- * @return string|mixed
- */
- protected function describeCommand(Command $command, array $options = [])
- {
- $command->getSynopsis(true);
- $command->getSynopsis(false);
- $command->mergeConsoleDefinition(false);
-
- $this->writeText('Usage:', $options);
- foreach (array_merge([$command->getSynopsis(true)], $command->getAliases(), $command->getUsages()) as $usage) {
- $this->writeText("\n");
- $this->writeText(' ' . $usage, $options);
- }
- $this->writeText("\n");
-
- $definition = $command->getNativeDefinition();
- if ($definition->getOptions() || $definition->getArguments()) {
- $this->writeText("\n");
- $this->describeInputDefinition($definition, $options);
- $this->writeText("\n");
- }
-
- if ($help = $command->getProcessedHelp()) {
- $this->writeText("\n");
- $this->writeText('Help:', $options);
- $this->writeText("\n");
- $this->writeText(' ' . str_replace("\n", "\n ", $help), $options);
- $this->writeText("\n");
- }
- }
-
- /**
- * 描述控制台
- * @param Console $console
- * @param array $options
- * @return string|mixed
- */
- protected function describeConsole(Console $console, array $options = [])
- {
- $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
- $description = new ConsoleDescription($console, $describedNamespace);
-
- if (isset($options['raw_text']) && $options['raw_text']) {
- $width = $this->getColumnWidth($description->getCommands());
-
- foreach ($description->getCommands() as $command) {
- $this->writeText(sprintf("%-${width}s %s", $command->getName(), $command->getDescription()), $options);
- $this->writeText("\n");
- }
- } else {
- if ('' != $help = $console->getHelp()) {
- $this->writeText("$help\n\n", $options);
- }
-
- $this->writeText("Usage:\n", $options);
- $this->writeText(" command [options] [arguments]\n\n", $options);
-
- $this->describeInputDefinition(new InputDefinition($console->getDefinition()->getOptions()), $options);
-
- $this->writeText("\n");
- $this->writeText("\n");
-
- $width = $this->getColumnWidth($description->getCommands());
-
- if ($describedNamespace) {
- $this->writeText(sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options);
- } else {
- $this->writeText('Available commands:', $options);
- }
-
- // add commands by namespace
- foreach ($description->getNamespaces() as $namespace) {
- if (!$describedNamespace && ConsoleDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
- $this->writeText("\n");
- $this->writeText(' ' . $namespace['id'] . '', $options);
- }
-
- foreach ($namespace['commands'] as $name) {
- $this->writeText("\n");
- $spacingWidth = $width - strlen($name);
- $this->writeText(sprintf(" %s%s%s", $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)
- ->getDescription()), $options);
- }
- }
-
- $this->writeText("\n");
- }
- }
-
- /**
- * {@inheritdoc}
- */
- private function writeText($content, array $options = [])
- {
- $this->write(isset($options['raw_text'])
- && $options['raw_text'] ? strip_tags($content) : $content, isset($options['raw_output']) ? !$options['raw_output'] : true);
- }
-
- /**
- * 格式化
- * @param mixed $default
- * @return string
- */
- private function formatDefaultValue($default)
- {
- return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
- }
-
- /**
- * @param Command[] $commands
- * @return int
- */
- private function getColumnWidth(array $commands)
- {
- $width = 0;
- foreach ($commands as $command) {
- $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
- }
-
- return $width + 2;
- }
-
- /**
- * @param InputOption[] $options
- * @return int
- */
- private function calculateTotalWidthForOptions($options)
- {
- $totalWidth = 0;
- foreach ($options as $option) {
- $nameLength = 4 + strlen($option->getName()) + 2; // - + shortcut + , + whitespace + name + --
-
- if ($option->acceptValue()) {
- $valueLength = 1 + strlen($option->getName()); // = + value
- $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ]
-
- $nameLength += $valueLength;
- }
- $totalWidth = max($totalWidth, $nameLength);
- }
-
- return $totalWidth;
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/helper/question/Choice.php b/core/library/think/console/helper/question/Choice.php
deleted file mode 100644
index 8badcd7b..00000000
--- a/core/library/think/console/helper/question/Choice.php
+++ /dev/null
@@ -1,157 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\helper\question;
-
-
-class Choice extends Question
-{
-
- private $choices;
- private $multiselect = false;
- private $prompt = ' > ';
- private $errorMessage = 'Value "%s" is invalid';
-
- /**
- * 构造方法
- * @param string $question 问题
- * @param array $choices 选项
- * @param mixed $default 默认答案
- */
- public function __construct($question, array $choices, $default = null)
- {
- parent::__construct($question, $default);
-
- $this->choices = $choices;
- $this->setValidator($this->getDefaultValidator());
- $this->setAutocompleterValues($choices);
- }
-
- /**
- * 可选项
- * @return array
- */
- public function getChoices()
- {
- return $this->choices;
- }
-
- /**
- * 设置可否多选
- * @param bool $multiselect
- * @return self
- */
- public function setMultiselect($multiselect)
- {
- $this->multiselect = $multiselect;
- $this->setValidator($this->getDefaultValidator());
-
- return $this;
- }
-
- /**
- * 获取提示
- * @return string
- */
- public function getPrompt()
- {
- return $this->prompt;
- }
-
- /**
- * 设置提示
- * @param string $prompt
- * @return self
- */
- public function setPrompt($prompt)
- {
- $this->prompt = $prompt;
-
- return $this;
- }
-
- /**
- * 设置错误提示信息
- * @param string $errorMessage
- * @return self
- */
- public function setErrorMessage($errorMessage)
- {
- $this->errorMessage = $errorMessage;
- $this->setValidator($this->getDefaultValidator());
-
- return $this;
- }
-
- /**
- * 获取默认的验证方法
- * @return callable
- */
- private function getDefaultValidator()
- {
- $choices = $this->choices;
- $errorMessage = $this->errorMessage;
- $multiselect = $this->multiselect;
- $isAssoc = $this->isAssoc($choices);
-
- return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
- // Collapse all spaces.
- $selectedChoices = str_replace(' ', '', $selected);
-
- if ($multiselect) {
- // Check for a separated comma values
- if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
- throw new \InvalidArgumentException(sprintf($errorMessage, $selected));
- }
- $selectedChoices = explode(',', $selectedChoices);
- } else {
- $selectedChoices = [$selected];
- }
-
- $multiselectChoices = [];
- foreach ($selectedChoices as $value) {
- $results = [];
- foreach ($choices as $key => $choice) {
- if ($choice === $value) {
- $results[] = $key;
- }
- }
-
- if (count($results) > 1) {
- throw new \InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
- }
-
- $result = array_search($value, $choices);
-
- if (!$isAssoc) {
- if (!empty($result)) {
- $result = $choices[$result];
- } elseif (isset($choices[$value])) {
- $result = $choices[$value];
- }
- } elseif (empty($result) && array_key_exists($value, $choices)) {
- $result = $value;
- }
-
- if (empty($result)) {
- throw new \InvalidArgumentException(sprintf($errorMessage, $value));
- }
- array_push($multiselectChoices, $result);
- }
-
- if ($multiselect) {
- return $multiselectChoices;
- }
-
- return current($multiselectChoices);
- };
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/helper/question/Confirmation.php b/core/library/think/console/helper/question/Confirmation.php
deleted file mode 100644
index e67fd439..00000000
--- a/core/library/think/console/helper/question/Confirmation.php
+++ /dev/null
@@ -1,56 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\helper\question;
-
-
-class Confirmation extends Question
-{
-
- private $trueAnswerRegex;
-
- /**
- * 构造方法
- * @param string $question 问题
- * @param bool $default 默认答案
- * @param string $trueAnswerRegex 验证正则
- */
- public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
- {
- parent::__construct($question, (bool)$default);
-
- $this->trueAnswerRegex = $trueAnswerRegex;
- $this->setNormalizer($this->getDefaultNormalizer());
- }
-
- /**
- * 获取默认的答案回调
- * @return callable
- */
- private function getDefaultNormalizer()
- {
- $default = $this->getDefault();
- $regex = $this->trueAnswerRegex;
-
- return function ($answer) use ($default, $regex) {
- if (is_bool($answer)) {
- return $answer;
- }
-
- $answerIsTrue = (bool)preg_match($regex, $answer);
- if (false === $default) {
- return $answer && $answerIsTrue;
- }
-
- return !$answer || $answerIsTrue;
- };
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/helper/question/Question.php b/core/library/think/console/helper/question/Question.php
deleted file mode 100644
index 0a0cbce4..00000000
--- a/core/library/think/console/helper/question/Question.php
+++ /dev/null
@@ -1,211 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\helper\question;
-
-class Question
-{
-
- private $question;
- private $attempts;
- private $hidden = false;
- private $hiddenFallback = true;
- private $autocompleterValues;
- private $validator;
- private $default;
- private $normalizer;
-
- /**
- * 构造方法
- * @param string $question 问题
- * @param mixed $default 默认答案
- */
- public function __construct($question, $default = null)
- {
- $this->question = $question;
- $this->default = $default;
- }
-
- /**
- * 获取问题
- * @return string
- */
- public function getQuestion()
- {
- return $this->question;
- }
-
- /**
- * 获取默认答案
- * @return mixed
- */
- public function getDefault()
- {
- return $this->default;
- }
-
- /**
- * 是否隐藏答案
- * @return bool
- */
- public function isHidden()
- {
- return $this->hidden;
- }
-
- /**
- * 隐藏答案
- * @param bool $hidden
- * @return Question
- */
- public function setHidden($hidden)
- {
- if ($this->autocompleterValues) {
- throw new \LogicException('A hidden question cannot use the autocompleter.');
- }
-
- $this->hidden = (bool)$hidden;
-
- return $this;
- }
-
- /**
- * 不能被隐藏是否撤销
- * @return bool
- */
- public function isHiddenFallback()
- {
- return $this->hiddenFallback;
- }
-
- /**
- * 设置不能被隐藏的时候的操作
- * @param bool $fallback
- * @return Question
- */
- public function setHiddenFallback($fallback)
- {
- $this->hiddenFallback = (bool)$fallback;
-
- return $this;
- }
-
- /**
- * 获取自动完成
- * @return null|array|\Traversable
- */
- public function getAutocompleterValues()
- {
- return $this->autocompleterValues;
- }
-
- /**
- * 设置自动完成的值
- * @param null|array|\Traversable $values
- * @return Question
- * @throws \InvalidArgumentException
- * @throws \LogicException
- */
- public function setAutocompleterValues($values)
- {
- if (is_array($values) && $this->isAssoc($values)) {
- $values = array_merge(array_keys($values), array_values($values));
- }
-
- if (null !== $values && !is_array($values)) {
- if (!$values instanceof \Traversable || $values instanceof \Countable) {
- throw new \InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.');
- }
- }
-
- if ($this->hidden) {
- throw new \LogicException('A hidden question cannot use the autocompleter.');
- }
-
- $this->autocompleterValues = $values;
-
- return $this;
- }
-
- /**
- * 设置答案的验证器
- * @param null|callable $validator
- * @return Question The current instance
- */
- public function setValidator($validator)
- {
- $this->validator = $validator;
-
- return $this;
- }
-
- /**
- * 获取验证器
- * @return null|callable
- */
- public function getValidator()
- {
- return $this->validator;
- }
-
- /**
- * 设置最大重试次数
- * @param null|int $attempts
- * @return Question
- * @throws \InvalidArgumentException
- */
- public function setMaxAttempts($attempts)
- {
- if (null !== $attempts && $attempts < 1) {
- throw new \InvalidArgumentException('Maximum number of attempts must be a positive value.');
- }
-
- $this->attempts = $attempts;
-
- return $this;
- }
-
- /**
- * 获取最大重试次数
- * @return null|int
- */
- public function getMaxAttempts()
- {
- return $this->attempts;
- }
-
- /**
- * 设置响应的回调
- * @param string|\Closure $normalizer
- * @return Question
- */
- public function setNormalizer($normalizer)
- {
- $this->normalizer = $normalizer;
-
- return $this;
- }
-
- /**
- * 获取相应回调
- * The normalizer can ba a callable (a string), a closure or a class implementing __invoke.
- * @return string|\Closure
- */
- public function getNormalizer()
- {
- return $this->normalizer;
- }
-
- protected function isAssoc($array)
- {
- return (bool)count(array_filter(array_keys($array), 'is_string'));
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/input/Argument.php b/core/library/think/console/input/Argument.php
deleted file mode 100644
index 843f928c..00000000
--- a/core/library/think/console/input/Argument.php
+++ /dev/null
@@ -1,115 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\input;
-
-class Argument
-{
-
- const REQUIRED = 1;
- const OPTIONAL = 2;
- const IS_ARRAY = 4;
-
- private $name;
- private $mode;
- private $default;
- private $description;
-
- /**
- * 构造方法
- * @param string $name 参数名
- * @param int $mode 参数类型: self::REQUIRED 或者 self::OPTIONAL
- * @param string $description 描述
- * @param mixed $default 默认值 (仅 self::OPTIONAL 类型有效)
- * @throws \InvalidArgumentException
- */
- public function __construct($name, $mode = null, $description = '', $default = null)
- {
- if (null === $mode) {
- $mode = self::OPTIONAL;
- } elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
- throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
- }
-
- $this->name = $name;
- $this->mode = $mode;
- $this->description = $description;
-
- $this->setDefault($default);
- }
-
- /**
- * 获取参数名
- * @return string
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * 是否必须
- * @return bool
- */
- public function isRequired()
- {
- return self::REQUIRED === (self::REQUIRED & $this->mode);
- }
-
- /**
- * 该参数是否接受数组
- * @return bool
- */
- public function isArray()
- {
- return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
- }
-
- /**
- * 设置默认值
- * @param mixed $default 默认值
- * @throws \LogicException
- */
- public function setDefault($default = null)
- {
- if (self::REQUIRED === $this->mode && null !== $default) {
- throw new \LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
- }
-
- if ($this->isArray()) {
- if (null === $default) {
- $default = [];
- } elseif (!is_array($default)) {
- throw new \LogicException('A default value for an array argument must be an array.');
- }
- }
-
- $this->default = $default;
- }
-
- /**
- * 获取默认值
- * @return mixed
- */
- public function getDefault()
- {
- return $this->default;
- }
-
- /**
- * 获取描述
- * @return string
- */
- public function getDescription()
- {
- return $this->description;
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/input/Definition.php b/core/library/think/console/input/Definition.php
deleted file mode 100644
index 4df9389a..00000000
--- a/core/library/think/console/input/Definition.php
+++ /dev/null
@@ -1,375 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\input;
-
-class Definition
-{
-
- /**
- * @var Argument[]
- */
- private $arguments;
-
- private $requiredCount;
- private $hasAnArrayArgument = false;
- private $hasOptional;
-
- /**
- * @var Option[]
- */
- private $options;
- private $shortcuts;
-
- /**
- * 构造方法
- * @param array $definition
- * @api
- */
- public function __construct(array $definition = [])
- {
- $this->setDefinition($definition);
- }
-
- /**
- * 设置指令的定义
- * @param array $definition 定义的数组
- */
- public function setDefinition(array $definition)
- {
- $arguments = [];
- $options = [];
- foreach ($definition as $item) {
- if ($item instanceof Option) {
- $options[] = $item;
- } else {
- $arguments[] = $item;
- }
- }
-
- $this->setArguments($arguments);
- $this->setOptions($options);
- }
-
- /**
- * 设置参数
- * @param Argument[] $arguments 参数数组
- */
- public function setArguments($arguments = [])
- {
- $this->arguments = [];
- $this->requiredCount = 0;
- $this->hasOptional = false;
- $this->hasAnArrayArgument = false;
- $this->addArguments($arguments);
- }
-
- /**
- * 添加参数
- * @param Argument[] $arguments 参数数组
- * @api
- */
- public function addArguments($arguments = [])
- {
- if (null !== $arguments) {
- foreach ($arguments as $argument) {
- $this->addArgument($argument);
- }
- }
- }
-
- /**
- * 添加一个参数
- * @param Argument $argument 参数
- * @throws \LogicException
- */
- public function addArgument(Argument $argument)
- {
- if (isset($this->arguments[$argument->getName()])) {
- throw new \LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
- }
-
- if ($this->hasAnArrayArgument) {
- throw new \LogicException('Cannot add an argument after an array argument.');
- }
-
- if ($argument->isRequired() && $this->hasOptional) {
- throw new \LogicException('Cannot add a required argument after an optional one.');
- }
-
- if ($argument->isArray()) {
- $this->hasAnArrayArgument = true;
- }
-
- if ($argument->isRequired()) {
- ++$this->requiredCount;
- } else {
- $this->hasOptional = true;
- }
-
- $this->arguments[$argument->getName()] = $argument;
- }
-
- /**
- * 根据名称或者位置获取参数
- * @param string|int $name 参数名或者位置
- * @return Argument 参数
- * @throws \InvalidArgumentException
- */
- public function getArgument($name)
- {
- if (!$this->hasArgument($name)) {
- throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
- }
-
- $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
-
- return $arguments[$name];
- }
-
- /**
- * 根据名称或位置检查是否具有某个参数
- * @param string|int $name 参数名或者位置
- * @return bool
- * @api
- */
- public function hasArgument($name)
- {
- $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
-
- return isset($arguments[$name]);
- }
-
- /**
- * 获取所有的参数
- * @return Argument[] 参数数组
- */
- public function getArguments()
- {
- return $this->arguments;
- }
-
- /**
- * 获取参数数量
- * @return int
- */
- public function getArgumentCount()
- {
- return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
- }
-
- /**
- * 获取必填的参数的数量
- * @return int
- */
- public function getArgumentRequiredCount()
- {
- return $this->requiredCount;
- }
-
- /**
- * 获取参数默认值
- * @return array
- */
- public function getArgumentDefaults()
- {
- $values = [];
- foreach ($this->arguments as $argument) {
- $values[$argument->getName()] = $argument->getDefault();
- }
-
- return $values;
- }
-
- /**
- * 设置选项
- * @param Option[] $options 选项数组
- */
- public function setOptions($options = [])
- {
- $this->options = [];
- $this->shortcuts = [];
- $this->addOptions($options);
- }
-
- /**
- * 添加选项
- * @param Option[] $options 选项数组
- * @api
- */
- public function addOptions($options = [])
- {
- foreach ($options as $option) {
- $this->addOption($option);
- }
- }
-
- /**
- * 添加一个选项
- * @param Option $option 选项
- * @throws \LogicException
- * @api
- */
- public function addOption(Option $option)
- {
- if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
- throw new \LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
- }
-
- if ($option->getShortcut()) {
- foreach (explode('|', $option->getShortcut()) as $shortcut) {
- if (isset($this->shortcuts[$shortcut])
- && !$option->equals($this->options[$this->shortcuts[$shortcut]])
- ) {
- throw new \LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
- }
- }
- }
-
- $this->options[$option->getName()] = $option;
- if ($option->getShortcut()) {
- foreach (explode('|', $option->getShortcut()) as $shortcut) {
- $this->shortcuts[$shortcut] = $option->getName();
- }
- }
- }
-
- /**
- * 根据名称获取选项
- * @param string $name 选项名
- * @return Option
- * @throws \InvalidArgumentException
- * @api
- */
- public function getOption($name)
- {
- if (!$this->hasOption($name)) {
- throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
- }
-
- return $this->options[$name];
- }
-
- /**
- * 根据名称检查是否有这个选项
- * @param string $name 选项名
- * @return bool
- * @api
- */
- public function hasOption($name)
- {
- return isset($this->options[$name]);
- }
-
- /**
- * 获取所有选项
- * @return Option[]
- * @api
- */
- public function getOptions()
- {
- return $this->options;
- }
-
- /**
- * 根据名称检查某个选项是否有短名称
- * @param string $name 短名称
- * @return bool
- */
- public function hasShortcut($name)
- {
- return isset($this->shortcuts[$name]);
- }
-
- /**
- * 根据短名称获取选项
- * @param string $shortcut 短名称
- * @return Option
- */
- public function getOptionForShortcut($shortcut)
- {
- return $this->getOption($this->shortcutToName($shortcut));
- }
-
- /**
- * 获取所有选项的默认值
- * @return array
- */
- public function getOptionDefaults()
- {
- $values = [];
- foreach ($this->options as $option) {
- $values[$option->getName()] = $option->getDefault();
- }
-
- return $values;
- }
-
- /**
- * 根据短名称获取选项名
- * @param string $shortcut 短名称
- * @return string
- * @throws \InvalidArgumentException
- */
- private function shortcutToName($shortcut)
- {
- if (!isset($this->shortcuts[$shortcut])) {
- throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
- }
-
- return $this->shortcuts[$shortcut];
- }
-
- /**
- * 获取该指令的介绍
- * @param bool $short 是否简洁介绍
- * @return string
- */
- public function getSynopsis($short = false)
- {
- $elements = [];
-
- if ($short && $this->getOptions()) {
- $elements[] = '[options]';
- } elseif (!$short) {
- foreach ($this->getOptions() as $option) {
- $value = '';
- if ($option->acceptValue()) {
- $value = sprintf(' %s%s%s', $option->isValueOptional() ? '[' : '', strtoupper($option->getName()), $option->isValueOptional() ? ']' : '');
- }
-
- $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
- $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
- }
- }
-
- if (count($elements) && $this->getArguments()) {
- $elements[] = '[--]';
- }
-
- foreach ($this->getArguments() as $argument) {
- $element = '<' . $argument->getName() . '>';
- if (!$argument->isRequired()) {
- $element = '[' . $element . ']';
- } elseif ($argument->isArray()) {
- $element .= ' (' . $element . ')';
- }
-
- if ($argument->isArray()) {
- $element .= '...';
- }
-
- $elements[] = $element;
- }
-
- return implode(' ', $elements);
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/input/Option.php b/core/library/think/console/input/Option.php
deleted file mode 100644
index 4406b278..00000000
--- a/core/library/think/console/input/Option.php
+++ /dev/null
@@ -1,190 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\input;
-
-class Option
-{
-
- const VALUE_NONE = 1;
- const VALUE_REQUIRED = 2;
- const VALUE_OPTIONAL = 4;
- const VALUE_IS_ARRAY = 8;
-
- private $name;
- private $shortcut;
- private $mode;
- private $default;
- private $description;
-
- /**
- * 构造方法
- * @param string $name 选项名
- * @param string|array $shortcut 短名称,多个用|隔开或者使用数组
- * @param int $mode 选项类型(可选类型为 self::VALUE_*)
- * @param string $description 描述
- * @param mixed $default 默认值 (类型为 self::VALUE_REQUIRED 或者 self::VALUE_NONE 的时候必须为null)
- * @throws \InvalidArgumentException
- */
- public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
- {
- if (0 === strpos($name, '--')) {
- $name = substr($name, 2);
- }
-
- if (empty($name)) {
- throw new \InvalidArgumentException('An option name cannot be empty.');
- }
-
- if (empty($shortcut)) {
- $shortcut = null;
- }
-
- if (null !== $shortcut) {
- if (is_array($shortcut)) {
- $shortcut = implode('|', $shortcut);
- }
- $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
- $shortcuts = array_filter($shortcuts);
- $shortcut = implode('|', $shortcuts);
-
- if (empty($shortcut)) {
- throw new \InvalidArgumentException('An option shortcut cannot be empty.');
- }
- }
-
- if (null === $mode) {
- $mode = self::VALUE_NONE;
- } elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
- throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
- }
-
- $this->name = $name;
- $this->shortcut = $shortcut;
- $this->mode = $mode;
- $this->description = $description;
-
- if ($this->isArray() && !$this->acceptValue()) {
- throw new \InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
- }
-
- $this->setDefault($default);
- }
-
- /**
- * 获取短名称
- * @return string
- */
- public function getShortcut()
- {
- return $this->shortcut;
- }
-
- /**
- * 获取选项名
- * @return string
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * 是否可以设置值
- * @return bool 类型不是 self::VALUE_NONE 的时候返回true,其他均返回false
- */
- public function acceptValue()
- {
- return $this->isValueRequired() || $this->isValueOptional();
- }
-
- /**
- * 是否必须
- * @return bool 类型是 self::VALUE_REQUIRED 的时候返回true,其他均返回false
- */
- public function isValueRequired()
- {
- return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
- }
-
- /**
- * 是否可选
- * @return bool 类型是 self::VALUE_OPTIONAL 的时候返回true,其他均返回false
- */
- public function isValueOptional()
- {
- return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
- }
-
- /**
- * 选项值是否接受数组
- * @return bool 类型是 self::VALUE_IS_ARRAY 的时候返回true,其他均返回false
- */
- public function isArray()
- {
- return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
- }
-
- /**
- * 设置默认值
- * @param mixed $default 默认值
- * @throws \LogicException
- */
- public function setDefault($default = null)
- {
- if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
- throw new \LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
- }
-
- if ($this->isArray()) {
- if (null === $default) {
- $default = [];
- } elseif (!is_array($default)) {
- throw new \LogicException('A default value for an array option must be an array.');
- }
- }
-
- $this->default = $this->acceptValue() ? $default : false;
- }
-
- /**
- * 获取默认值
- * @return mixed
- */
- public function getDefault()
- {
- return $this->default;
- }
-
- /**
- * 获取描述文字
- * @return string
- */
- public function getDescription()
- {
- return $this->description;
- }
-
- /**
- * 检查所给选项是否是当前这个
- * @param Option $option
- * @return bool
- */
- public function equals(Option $option)
- {
- return $option->getName() === $this->getName()
- && $option->getShortcut() === $this->getShortcut()
- && $option->getDefault() === $this->getDefault()
- && $option->isArray() === $this->isArray()
- && $option->isValueRequired() === $this->isValueRequired()
- && $option->isValueOptional() === $this->isValueOptional();
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/output/Formatter.php b/core/library/think/console/output/Formatter.php
deleted file mode 100644
index 4179680e..00000000
--- a/core/library/think/console/output/Formatter.php
+++ /dev/null
@@ -1,196 +0,0 @@
-
-// +----------------------------------------------------------------------
-namespace think\console\output;
-
-use think\console\output\formatter\Style;
-use think\console\output\formatter\Stack as StyleStack;
-
-class Formatter
-{
-
- private $decorated = false;
- private $styles = [];
- private $styleStack;
-
- /**
- * 转义
- * @param string $text
- * @return string
- */
- public static function escape($text)
- {
- return preg_replace('/([^\\\\]?)setStyle('error', new Style('white', 'red'));
- $this->setStyle('info', new Style('green'));
- $this->setStyle('comment', new Style('yellow'));
- $this->setStyle('question', new Style('black', 'cyan'));
-
- $this->styleStack = new StyleStack();
- }
-
- /**
- * 设置外观标识
- * @param bool $decorated 是否美化文职
- */
- public function setDecorated($decorated)
- {
- $this->decorated = (bool)$decorated;
- }
-
- /**
- * 获取外观标识
- * @return bool
- */
- public function isDecorated()
- {
- return $this->decorated;
- }
-
- /**
- * 添加一个新样式
- * @param string $name 样式名
- * @param Style $style 样式实例
- */
- public function setStyle($name, Style $style)
- {
- $this->styles[strtolower($name)] = $style;
- }
-
- /**
- * 是否有这个样式
- * @param string $name
- * @return bool
- */
- public function hasStyle($name)
- {
- return isset($this->styles[strtolower($name)]);
- }
-
- /**
- * 获取样式
- * @param string $name
- * @return Style
- * @throws \InvalidArgumentException
- */
- public function getStyle($name)
- {
- if (!$this->hasStyle($name)) {
- throw new \InvalidArgumentException(sprintf('Undefined style: %s', $name));
- }
-
- return $this->styles[strtolower($name)];
- }
-
- /**
- * 使用所给的样式格式化文字
- * @param string $message 文字
- * @return string
- */
- public function format($message)
- {
- $offset = 0;
- $output = '';
- $tagRegex = '[a-z][a-z0-9_=;-]*';
- preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#isx", $message, $matches, PREG_OFFSET_CAPTURE);
- foreach ($matches[0] as $i => $match) {
- $pos = $match[1];
- $text = $match[0];
-
- if (0 != $pos && '\\' == $message[$pos - 1]) {
- continue;
- }
-
- $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
- $offset = $pos + strlen($text);
-
- if ($open = '/' != $text[1]) {
- $tag = $matches[1][$i][0];
- } else {
- $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
- }
-
- if (!$open && !$tag) {
- // >
- $this->styleStack->pop();
- } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
- $output .= $this->applyCurrentStyle($text);
- } elseif ($open) {
- $this->styleStack->push($style);
- } else {
- $this->styleStack->pop($style);
- }
- }
-
- $output .= $this->applyCurrentStyle(substr($message, $offset));
-
- return str_replace('\\<', '<', $output);
- }
-
- /**
- * @return StyleStack
- */
- public function getStyleStack()
- {
- return $this->styleStack;
- }
-
- /**
- * 根据字符串创建新的样式实例
- * @param string $string
- * @return Style|bool
- */
- private function createStyleFromString($string)
- {
- if (isset($this->styles[$string])) {
- return $this->styles[$string];
- }
-
- if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
- return false;
- }
-
- $style = new Style();
- foreach ($matches as $match) {
- array_shift($match);
-
- if ('fg' == $match[0]) {
- $style->setForeground($match[1]);
- } elseif ('bg' == $match[0]) {
- $style->setBackground($match[1]);
- } else {
- try {
- $style->setOption($match[1]);
- } catch (\InvalidArgumentException $e) {
- return false;
- }
- }
- }
-
- return $style;
- }
-
- /**
- * 从堆栈应用样式到文字
- * @param string $text 文字
- * @return string
- */
- private function applyCurrentStyle($text)
- {
- return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/output/Nothing.php b/core/library/think/console/output/Nothing.php
deleted file mode 100644
index c1550270..00000000
--- a/core/library/think/console/output/Nothing.php
+++ /dev/null
@@ -1,108 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\output;
-
-use think\console\Output;
-
-class Nothing extends Output
-{
- /** @noinspection PhpMissingParentConstructorInspection */
- public function __construct()
- {
-
- }
-
- /**
- * {@inheritdoc}
- */
- public function setFormatter(Formatter $formatter)
- {
- // do nothing
- }
-
- /**
- * {@inheritdoc}
- */
- public function getFormatter()
- {
- // to comply with the interface we must return a OutputFormatterInterface
- return new Formatter();
- }
-
- /**
- * {@inheritdoc}
- */
- public function setDecorated($decorated)
- {
- // do nothing
- }
-
- /**
- * {@inheritdoc}
- */
- public function isDecorated()
- {
- return false;
- }
-
- /**
- * {@inheritdoc}
- */
- public function setVerbosity($level)
- {
- // do nothing
- }
-
- /**
- * {@inheritdoc}
- */
- public function getVerbosity()
- {
- return self::VERBOSITY_QUIET;
- }
-
- public function isQuiet()
- {
- return true;
- }
-
- public function isVerbose()
- {
- return false;
- }
-
- public function isVeryVerbose()
- {
- return false;
- }
-
- public function isDebug()
- {
- return false;
- }
-
- /**
- * {@inheritdoc}
- */
- public function writeln($messages, $options = self::OUTPUT_NORMAL)
- {
- // do nothing
- }
-
- /**
- * {@inheritdoc}
- */
- public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
- {
- // do nothing
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/output/Stream.php b/core/library/think/console/output/Stream.php
deleted file mode 100644
index b97b582e..00000000
--- a/core/library/think/console/output/Stream.php
+++ /dev/null
@@ -1,189 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\output;
-
-class Stream
-{
-
- const VERBOSITY_QUIET = 0;
- const VERBOSITY_NORMAL = 1;
- const VERBOSITY_VERBOSE = 2;
- const VERBOSITY_VERY_VERBOSE = 3;
- const VERBOSITY_DEBUG = 4;
-
- const OUTPUT_NORMAL = 0;
- const OUTPUT_RAW = 1;
- const OUTPUT_PLAIN = 2;
-
- private $verbosity = self::VERBOSITY_NORMAL;
- private $formatter;
-
-
- private $stream;
-
- /**
- * 构造方法
- */
- public function __construct($stream, Formatter $formatter = null)
- {
- if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
- throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
- }
-
- $this->stream = $stream;
-
- $decorated = $this->hasColorSupport();
-
- $this->formatter = $formatter ?: new Formatter();
- $this->formatter->setDecorated($decorated);
- }
-
- /**
- * {@inheritdoc}
- */
- public function setFormatter(Formatter $formatter)
- {
- $this->formatter = $formatter;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getFormatter()
- {
- return $this->formatter;
- }
-
- /**
- * {@inheritdoc}
- */
- public function setDecorated($decorated)
- {
- $this->formatter->setDecorated($decorated);
- }
-
- /**
- * {@inheritdoc}
- */
- public function isDecorated()
- {
- return $this->formatter->isDecorated();
- }
-
- /**
- * {@inheritdoc}
- */
- public function setVerbosity($level)
- {
- $this->verbosity = (int)$level;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getVerbosity()
- {
- return $this->verbosity;
- }
-
- public function isQuiet()
- {
- return self::VERBOSITY_QUIET === $this->verbosity;
- }
-
- public function isVerbose()
- {
- return self::VERBOSITY_VERBOSE <= $this->verbosity;
- }
-
- public function isVeryVerbose()
- {
- return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
- }
-
- public function isDebug()
- {
- return self::VERBOSITY_DEBUG <= $this->verbosity;
- }
-
- /**
- * {@inheritdoc}
- */
- public function writeln($messages, $type = self::OUTPUT_NORMAL)
- {
- $this->write($messages, true, $type);
- }
-
- /**
- * {@inheritdoc}
- */
- public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
- {
- if (self::VERBOSITY_QUIET === $this->verbosity) {
- return;
- }
-
- $messages = (array)$messages;
-
- foreach ($messages as $message) {
- switch ($type) {
- case self::OUTPUT_NORMAL:
- $message = $this->formatter->format($message);
- break;
- case self::OUTPUT_RAW:
- break;
- case self::OUTPUT_PLAIN:
- $message = strip_tags($this->formatter->format($message));
- break;
- default:
- throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type));
- }
-
- $this->doWrite($message, $newline);
- }
- }
-
- /**
- * 将消息写入到输出。
- * @param string $message 消息
- * @param bool $newline 是否另起一行
- */
- protected function doWrite($message, $newline)
- {
- if (false === @fwrite($this->stream, $message . ($newline ? PHP_EOL : ''))) {
- throw new \RuntimeException('Unable to write output.');
- }
-
- fflush($this->stream);
- }
-
- /**
- * @return resource
- */
- public function getStream()
- {
- return $this->stream;
- }
-
- /**
- * 是否支持着色
- * @return bool
- */
- protected function hasColorSupport()
- {
- if (DIRECTORY_SEPARATOR == '\\') {
- return false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI');
- }
-
- return function_exists('posix_isatty') && @posix_isatty($this->stream);
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/output/formatter/Stack.php b/core/library/think/console/output/formatter/Stack.php
deleted file mode 100644
index 0335d6c0..00000000
--- a/core/library/think/console/output/formatter/Stack.php
+++ /dev/null
@@ -1,116 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\output\formatter;
-
-class Stack
-{
-
- /**
- * @var Style[]
- */
- private $styles;
-
- /**
- * @var Style
- */
- private $emptyStyle;
-
- /**
- * 构造方法
- * @param Style|null $emptyStyle
- */
- public function __construct(Style $emptyStyle = null)
- {
- $this->emptyStyle = $emptyStyle ?: new Style();
- $this->reset();
- }
-
- /**
- * 重置堆栈
- */
- public function reset()
- {
- $this->styles = [];
- }
-
- /**
- * 推一个样式进入堆栈
- * @param Style $style
- */
- public function push(Style $style)
- {
- $this->styles[] = $style;
- }
-
- /**
- * 从堆栈中弹出一个样式
- * @param Style|null $style
- * @return Style
- * @throws \InvalidArgumentException
- */
- public function pop(Style $style = null)
- {
- if (empty($this->styles)) {
- return $this->emptyStyle;
- }
-
- if (null === $style) {
- return array_pop($this->styles);
- }
-
- /**
- * @var int $index
- * @var Style $stackedStyle
- */
- foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
- if ($style->apply('') === $stackedStyle->apply('')) {
- $this->styles = array_slice($this->styles, 0, $index);
-
- return $stackedStyle;
- }
- }
-
- throw new \InvalidArgumentException('Incorrectly nested style tag found.');
- }
-
- /**
- * 计算堆栈的当前样式。
- * @return Style
- */
- public function getCurrent()
- {
- if (empty($this->styles)) {
- return $this->emptyStyle;
- }
-
- return $this->styles[count($this->styles) - 1];
- }
-
- /**
- * @param Style $emptyStyle
- * @return Stack
- */
- public function setEmptyStyle(Style $emptyStyle)
- {
- $this->emptyStyle = $emptyStyle;
-
- return $this;
- }
-
- /**
- * @return Style
- */
- public function getEmptyStyle()
- {
- return $this->emptyStyle;
- }
-}
\ No newline at end of file
diff --git a/core/library/think/console/output/formatter/Style.php b/core/library/think/console/output/formatter/Style.php
deleted file mode 100644
index 1ffbd811..00000000
--- a/core/library/think/console/output/formatter/Style.php
+++ /dev/null
@@ -1,189 +0,0 @@
-
-// +----------------------------------------------------------------------
-
-namespace think\console\output\formatter;
-
-class Style
-{
-
- private static $availableForegroundColors = [
- 'black' => ['set' => 30, 'unset' => 39],
- 'red' => ['set' => 31, 'unset' => 39],
- 'green' => ['set' => 32, 'unset' => 39],
- 'yellow' => ['set' => 33, 'unset' => 39],
- 'blue' => ['set' => 34, 'unset' => 39],
- 'magenta' => ['set' => 35, 'unset' => 39],
- 'cyan' => ['set' => 36, 'unset' => 39],
- 'white' => ['set' => 37, 'unset' => 39],
- ];
- private static $availableBackgroundColors = [
- 'black' => ['set' => 40, 'unset' => 49],
- 'red' => ['set' => 41, 'unset' => 49],
- 'green' => ['set' => 42, 'unset' => 49],
- 'yellow' => ['set' => 43, 'unset' => 49],
- 'blue' => ['set' => 44, 'unset' => 49],
- 'magenta' => ['set' => 45, 'unset' => 49],
- 'cyan' => ['set' => 46, 'unset' => 49],
- 'white' => ['set' => 47, 'unset' => 49],
- ];
- private static $availableOptions = [
- 'bold' => ['set' => 1, 'unset' => 22],
- 'underscore' => ['set' => 4, 'unset' => 24],
- 'blink' => ['set' => 5, 'unset' => 25],
- 'reverse' => ['set' => 7, 'unset' => 27],
- 'conceal' => ['set' => 8, 'unset' => 28],
- ];
-
- private $foreground;
- private $background;
- private $options = [];
-
- /**
- * 初始化输出的样式
- * @param string|null $foreground 字体颜色
- * @param string|null $background 背景色
- * @param array $options 格式
- * @api
- */
- public function __construct($foreground = null, $background = null, array $options = [])
- {
- if (null !== $foreground) {
- $this->setForeground($foreground);
- }
- if (null !== $background) {
- $this->setBackground($background);
- }
- if (count($options)) {
- $this->setOptions($options);
- }
- }
-
- /**
- * 设置字体颜色
- * @param string|null $color 颜色名
- * @throws \InvalidArgumentException
- * @api
- */
- public function setForeground($color = null)
- {
- if (null === $color) {
- $this->foreground = null;
-
- return;
- }
-
- if (!isset(static::$availableForegroundColors[$color])) {
- throw new \InvalidArgumentException(sprintf('Invalid foreground color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableForegroundColors))));
- }
-
- $this->foreground = static::$availableForegroundColors[$color];
- }
-
- /**
- * 设置背景色
- * @param string|null $color 颜色名
- * @throws \InvalidArgumentException
- * @api
- */
- public function setBackground($color = null)
- {
- if (null === $color) {
- $this->background = null;
-
- return;
- }
-
- if (!isset(static::$availableBackgroundColors[$color])) {
- throw new \InvalidArgumentException(sprintf('Invalid background color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableBackgroundColors))));
- }
-
- $this->background = static::$availableBackgroundColors[$color];
- }
-
- /**
- * 设置字体格式
- * @param string $option 格式名
- * @throws \InvalidArgumentException When the option name isn't defined
- * @api
- */
- public function setOption($option)
- {
- if (!isset(static::$availableOptions[$option])) {
- throw new \InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions))));
- }
-
- if (!in_array(static::$availableOptions[$option], $this->options)) {
- $this->options[] = static::$availableOptions[$option];
- }
- }
-
- /**
- * 重置字体格式
- * @param string $option 格式名
- * @throws \InvalidArgumentException
- */
- public function unsetOption($option)
- {
- if (!isset(static::$availableOptions[$option])) {
- throw new \InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions))));
- }
-
- $pos = array_search(static::$availableOptions[$option], $this->options);
- if (false !== $pos) {
- unset($this->options[$pos]);
- }
- }
-
- /**
- * 批量设置字体格式
- * @param array $options
- */
- public function setOptions(array $options)
- {
- $this->options = [];
-
- foreach ($options as $option) {
- $this->setOption($option);
- }
- }
-
- /**
- * 应用样式到文字
- * @param string $text 文字
- * @return string
- */
- public function apply($text)
- {
- $setCodes = [];
- $unsetCodes = [];
-
- if (null !== $this->foreground) {
- $setCodes[] = $this->foreground['set'];
- $unsetCodes[] = $this->foreground['unset'];
- }
- if (null !== $this->background) {
- $setCodes[] = $this->background['set'];
- $unsetCodes[] = $this->background['unset'];
- }
- if (count($this->options)) {
- foreach ($this->options as $option) {
- $setCodes[] = $option['set'];
- $unsetCodes[] = $option['unset'];
- }
- }
-
- if (0 === count($setCodes)) {
- return $text;
- }
-
- return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
- }
-}
\ No newline at end of file