Input.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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\Exception\InvalidArgumentException;
  12. use Symfony\Component\Console\Exception\RuntimeException;
  13. /**
  14. * Input is the base class for all concrete Input classes.
  15. *
  16. * Three concrete classes are provided by default:
  17. *
  18. * * `ArgvInput`: The input comes from the CLI arguments (argv)
  19. * * `StringInput`: The input is provided as a string
  20. * * `ArrayInput`: The input is provided as an array
  21. *
  22. * @author Fabien Potencier <fabien@symfony.com>
  23. */
  24. abstract class Input implements InputInterface, StreamableInputInterface
  25. {
  26. protected $definition;
  27. protected $stream;
  28. protected $options = [];
  29. protected $arguments = [];
  30. protected $interactive = true;
  31. /**
  32. * @param \Symfony\Component\Console\Input\InputDefinition|null $definition
  33. */
  34. public function __construct($definition = null)
  35. {
  36. if (null === $definition) {
  37. $this->definition = new InputDefinition();
  38. } else {
  39. $this->bind($definition);
  40. $this->validate();
  41. }
  42. }
  43. /**
  44. * @return void
  45. * @param \Symfony\Component\Console\Input\InputDefinition $definition
  46. */
  47. public function bind($definition)
  48. {
  49. $this->arguments = [];
  50. $this->options = [];
  51. $this->definition = $definition;
  52. $this->parse();
  53. }
  54. /**
  55. * Processes command line arguments.
  56. *
  57. * @return void
  58. */
  59. abstract protected function parse();
  60. /**
  61. * @return void
  62. */
  63. public function validate()
  64. {
  65. $definition = $this->definition;
  66. $givenArguments = $this->arguments;
  67. $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($givenArguments, $definition) {
  68. return !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
  69. });
  70. if (\count($missingArguments) > 0) {
  71. throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
  72. }
  73. }
  74. public function isInteractive()
  75. {
  76. return $this->interactive;
  77. }
  78. /**
  79. * @return void
  80. * @param bool $interactive
  81. */
  82. public function setInteractive($interactive)
  83. {
  84. $this->interactive = $interactive;
  85. }
  86. public function getArguments()
  87. {
  88. return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
  89. }
  90. /**
  91. * @return mixed
  92. * @param string $name
  93. */
  94. public function getArgument($name)
  95. {
  96. if (!$this->definition->hasArgument($name)) {
  97. throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
  98. }
  99. return $this->arguments[$name] ?? $this->definition->getArgument($name)->getDefault();
  100. }
  101. /**
  102. * @return void
  103. * @param mixed $value
  104. * @param string $name
  105. */
  106. public function setArgument($name, $value)
  107. {
  108. if (!$this->definition->hasArgument($name)) {
  109. throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
  110. }
  111. $this->arguments[$name] = $value;
  112. }
  113. /**
  114. * @param string $name
  115. */
  116. public function hasArgument($name)
  117. {
  118. return $this->definition->hasArgument($name);
  119. }
  120. public function getOptions()
  121. {
  122. return array_merge($this->definition->getOptionDefaults(), $this->options);
  123. }
  124. /**
  125. * @return mixed
  126. * @param string $name
  127. */
  128. public function getOption($name)
  129. {
  130. if ($this->definition->hasNegation($name)) {
  131. if (null === $value = $this->getOption($this->definition->negationToName($name))) {
  132. return $value;
  133. }
  134. return !$value;
  135. }
  136. if (!$this->definition->hasOption($name)) {
  137. throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
  138. }
  139. return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
  140. }
  141. /**
  142. * @return void
  143. * @param mixed $value
  144. * @param string $name
  145. */
  146. public function setOption($name, $value)
  147. {
  148. if ($this->definition->hasNegation($name)) {
  149. $this->options[$this->definition->negationToName($name)] = !$value;
  150. return;
  151. } elseif (!$this->definition->hasOption($name)) {
  152. throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
  153. }
  154. $this->options[$name] = $value;
  155. }
  156. /**
  157. * @param string $name
  158. */
  159. public function hasOption($name)
  160. {
  161. return $this->definition->hasOption($name) || $this->definition->hasNegation($name);
  162. }
  163. /**
  164. * Escapes a token through escapeshellarg if it contains unsafe chars.
  165. * @param string $token
  166. */
  167. public function escapeToken($token)
  168. {
  169. return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
  170. }
  171. /**
  172. * @param resource $stream
  173. *
  174. * @return void
  175. */
  176. public function setStream($stream)
  177. {
  178. $this->stream = $stream;
  179. }
  180. /**
  181. * @return resource
  182. */
  183. public function getStream()
  184. {
  185. return $this->stream;
  186. }
  187. }