InputArgument.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Console\Input;
  11. use Symfony\Component\Console\Command\Command;
  12. use Symfony\Component\Console\Completion\CompletionInput;
  13. use Symfony\Component\Console\Completion\CompletionSuggestions;
  14. use Symfony\Component\Console\Completion\Suggestion;
  15. use Symfony\Component\Console\Exception\InvalidArgumentException;
  16. use Symfony\Component\Console\Exception\LogicException;
  17. /**
  18. * Represents a command line argument.
  19. *
  20. * @author Fabien Potencier <fabien@symfony.com>
  21. */
  22. class InputArgument
  23. {
  24. /**
  25. * Providing an argument is required (e.g. just 'app:foo' is not allowed).
  26. */
  27. public const REQUIRED = 1;
  28. /**
  29. * Providing an argument is optional (e.g. 'app:foo' and 'app:foo bar' are both allowed). This is the default behavior of arguments.
  30. */
  31. public const OPTIONAL = 2;
  32. /**
  33. * The argument accepts multiple values and turn them into an array (e.g. 'app:foo bar baz' will result in value ['bar', 'baz']).
  34. */
  35. public const IS_ARRAY = 4;
  36. private int $mode;
  37. private string|int|bool|array|float|null $default;
  38. /**
  39. * @param string $name The argument name
  40. * @param int-mask-of<InputArgument::*>|null $mode The argument mode: a bit mask of self::REQUIRED, self::OPTIONAL and self::IS_ARRAY
  41. * @param string $description A description text
  42. * @param string|bool|int|float|array|null $default The default value (for self::OPTIONAL mode only)
  43. * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
  44. *
  45. * @throws InvalidArgumentException When argument mode is not valid
  46. */
  47. public function __construct(
  48. private string $name,
  49. ?int $mode = null,
  50. private string $description = '',
  51. string|bool|int|float|array|null $default = null,
  52. private \Closure|array $suggestedValues = [],
  53. ) {
  54. if (null === $mode) {
  55. $mode = self::OPTIONAL;
  56. } elseif ($mode >= (self::IS_ARRAY << 1) || $mode < 1) {
  57. throw new InvalidArgumentException(\sprintf('Argument mode "%s" is not valid.', $mode));
  58. }
  59. $this->mode = $mode;
  60. $this->setDefault($default);
  61. }
  62. /**
  63. * Returns the argument name.
  64. */
  65. public function getName(): string
  66. {
  67. return $this->name;
  68. }
  69. /**
  70. * Returns true if the argument is required.
  71. *
  72. * @return bool true if parameter mode is self::REQUIRED, false otherwise
  73. */
  74. public function isRequired(): bool
  75. {
  76. return self::REQUIRED === (self::REQUIRED & $this->mode);
  77. }
  78. /**
  79. * Returns true if the argument can take multiple values.
  80. *
  81. * @return bool true if mode is self::IS_ARRAY, false otherwise
  82. */
  83. public function isArray(): bool
  84. {
  85. return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
  86. }
  87. /**
  88. * Sets the default value.
  89. */
  90. public function setDefault(string|bool|int|float|array|null $default): void
  91. {
  92. if ($this->isRequired() && null !== $default) {
  93. throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
  94. }
  95. if ($this->isArray()) {
  96. if (null === $default) {
  97. $default = [];
  98. } elseif (!\is_array($default)) {
  99. throw new LogicException('A default value for an array argument must be an array.');
  100. }
  101. }
  102. $this->default = $default;
  103. }
  104. /**
  105. * Returns the default value.
  106. */
  107. public function getDefault(): string|bool|int|float|array|null
  108. {
  109. return $this->default;
  110. }
  111. /**
  112. * Returns true if the argument has values for input completion.
  113. */
  114. public function hasCompletion(): bool
  115. {
  116. return [] !== $this->suggestedValues;
  117. }
  118. /**
  119. * Supplies suggestions when command resolves possible completion options for input.
  120. *
  121. * @see Command::complete()
  122. */
  123. public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
  124. {
  125. $values = $this->suggestedValues;
  126. if ($values instanceof \Closure && !\is_array($values = $values($input))) {
  127. throw new LogicException(\sprintf('Closure for argument "%s" must return an array. Got "%s".', $this->name, get_debug_type($values)));
  128. }
  129. if ($values) {
  130. $suggestions->suggestValues($values);
  131. }
  132. }
  133. /**
  134. * Returns the description text.
  135. */
  136. public function getDescription(): string
  137. {
  138. return $this->description;
  139. }
  140. }