You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

376 lines
9.7 KiB

<?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\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);
}
}