| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470 | <?php// +----------------------------------------------------------------------// | ThinkPHP [ WE CAN DO IT JUST THINK ]// +----------------------------------------------------------------------// | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.// +----------------------------------------------------------------------// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )// +----------------------------------------------------------------------// | Author: yunwuxin <448901948@qq.com>// +----------------------------------------------------------------------namespace think\console;use think\Console;use think\console\input\Argument;use think\console\input\Definition;use think\console\input\Option;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  Input */    protected $input;    /** @var  Output */    protected $output;    /**     * 构造方法     * @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;    }    /**     * 获取控制台     * @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->input  = $input;        $this->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     * @return $this     */    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     * @throws \InvalidArgumentException     */    private function validateName($name)    {        if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {            throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));        }    }}
 |