vendor/symfony/src/Symfony/Component/Console/Input/InputDefinition.php
changeset 0 7f95f8617b0b
equal deleted inserted replaced
-1:000000000000 0:7f95f8617b0b
       
     1 <?php
       
     2 
       
     3 /*
       
     4  * This file is part of the Symfony package.
       
     5  *
       
     6  * (c) Fabien Potencier <fabien@symfony.com>
       
     7  *
       
     8  * For the full copyright and license information, please view the LICENSE
       
     9  * file that was distributed with this source code.
       
    10  */
       
    11 
       
    12 namespace Symfony\Component\Console\Input;
       
    13 
       
    14 /**
       
    15  * A InputDefinition represents a set of valid command line arguments and options.
       
    16  *
       
    17  * Usage:
       
    18  *
       
    19  *     $definition = new InputDefinition(array(
       
    20  *       new InputArgument('name', InputArgument::REQUIRED),
       
    21  *       new InputOption('foo', 'f', InputOption::VALUE_REQUIRED),
       
    22  *     ));
       
    23  *
       
    24  * @author Fabien Potencier <fabien@symfony.com>
       
    25  *
       
    26  * @api
       
    27  */
       
    28 class InputDefinition
       
    29 {
       
    30     private $arguments;
       
    31     private $requiredCount;
       
    32     private $hasAnArrayArgument = false;
       
    33     private $hasOptional;
       
    34     private $options;
       
    35     private $shortcuts;
       
    36 
       
    37     /**
       
    38      * Constructor.
       
    39      *
       
    40      * @param array $definition An array of InputArgument and InputOption instance
       
    41      *
       
    42      * @api
       
    43      */
       
    44     public function __construct(array $definition = array())
       
    45     {
       
    46         $this->setDefinition($definition);
       
    47     }
       
    48 
       
    49     /**
       
    50      * Sets the definition of the input.
       
    51      *
       
    52      * @param array $definition The definition array
       
    53      *
       
    54      * @api
       
    55      */
       
    56     public function setDefinition(array $definition)
       
    57     {
       
    58         $arguments = array();
       
    59         $options = array();
       
    60         foreach ($definition as $item) {
       
    61             if ($item instanceof InputOption) {
       
    62                 $options[] = $item;
       
    63             } else {
       
    64                 $arguments[] = $item;
       
    65             }
       
    66         }
       
    67 
       
    68         $this->setArguments($arguments);
       
    69         $this->setOptions($options);
       
    70     }
       
    71 
       
    72     /**
       
    73      * Sets the InputArgument objects.
       
    74      *
       
    75      * @param array $arguments An array of InputArgument objects
       
    76      *
       
    77      * @api
       
    78      */
       
    79     public function setArguments($arguments = array())
       
    80     {
       
    81         $this->arguments          = array();
       
    82         $this->requiredCount      = 0;
       
    83         $this->hasOptional        = false;
       
    84         $this->hasAnArrayArgument = false;
       
    85         $this->addArguments($arguments);
       
    86     }
       
    87 
       
    88     /**
       
    89      * Add an array of InputArgument objects.
       
    90      *
       
    91      * @param InputArgument[] $arguments An array of InputArgument objects
       
    92      *
       
    93      * @api
       
    94      */
       
    95     public function addArguments($arguments = array())
       
    96     {
       
    97         if (null !== $arguments) {
       
    98             foreach ($arguments as $argument) {
       
    99                 $this->addArgument($argument);
       
   100             }
       
   101         }
       
   102     }
       
   103 
       
   104     /**
       
   105      * Add an InputArgument object.
       
   106      *
       
   107      * @param InputArgument $argument An InputArgument object
       
   108      *
       
   109      * @throws \LogicException When incorrect argument is given
       
   110      *
       
   111      * @api
       
   112      */
       
   113     public function addArgument(InputArgument $argument)
       
   114     {
       
   115         if (isset($this->arguments[$argument->getName()])) {
       
   116             throw new \LogicException(sprintf('An argument with name "%s" already exist.', $argument->getName()));
       
   117         }
       
   118 
       
   119         if ($this->hasAnArrayArgument) {
       
   120             throw new \LogicException('Cannot add an argument after an array argument.');
       
   121         }
       
   122 
       
   123         if ($argument->isRequired() && $this->hasOptional) {
       
   124             throw new \LogicException('Cannot add a required argument after an optional one.');
       
   125         }
       
   126 
       
   127         if ($argument->isArray()) {
       
   128             $this->hasAnArrayArgument = true;
       
   129         }
       
   130 
       
   131         if ($argument->isRequired()) {
       
   132             ++$this->requiredCount;
       
   133         } else {
       
   134             $this->hasOptional = true;
       
   135         }
       
   136 
       
   137         $this->arguments[$argument->getName()] = $argument;
       
   138     }
       
   139 
       
   140     /**
       
   141      * Returns an InputArgument by name or by position.
       
   142      *
       
   143      * @param string|integer $name The InputArgument name or position
       
   144      *
       
   145      * @return InputArgument An InputArgument object
       
   146      *
       
   147      * @throws \InvalidArgumentException When argument given doesn't exist
       
   148      *
       
   149      * @api
       
   150      */
       
   151     public function getArgument($name)
       
   152     {
       
   153         $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
       
   154 
       
   155         if (!$this->hasArgument($name)) {
       
   156             throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
       
   157         }
       
   158 
       
   159         return $arguments[$name];
       
   160     }
       
   161 
       
   162     /**
       
   163      * Returns true if an InputArgument object exists by name or position.
       
   164      *
       
   165      * @param string|integer $name The InputArgument name or position
       
   166      *
       
   167      * @return Boolean true if the InputArgument object exists, false otherwise
       
   168      *
       
   169      * @api
       
   170      */
       
   171     public function hasArgument($name)
       
   172     {
       
   173         $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
       
   174 
       
   175         return isset($arguments[$name]);
       
   176     }
       
   177 
       
   178     /**
       
   179      * Gets the array of InputArgument objects.
       
   180      *
       
   181      * @return array An array of InputArgument objects
       
   182      *
       
   183      * @api
       
   184      */
       
   185     public function getArguments()
       
   186     {
       
   187         return $this->arguments;
       
   188     }
       
   189 
       
   190     /**
       
   191      * Returns the number of InputArguments.
       
   192      *
       
   193      * @return integer The number of InputArguments
       
   194      */
       
   195     public function getArgumentCount()
       
   196     {
       
   197         return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
       
   198     }
       
   199 
       
   200     /**
       
   201      * Returns the number of required InputArguments.
       
   202      *
       
   203      * @return integer The number of required InputArguments
       
   204      */
       
   205     public function getArgumentRequiredCount()
       
   206     {
       
   207         return $this->requiredCount;
       
   208     }
       
   209 
       
   210     /**
       
   211      * Gets the default values.
       
   212      *
       
   213      * @return array An array of default values
       
   214      */
       
   215     public function getArgumentDefaults()
       
   216     {
       
   217         $values = array();
       
   218         foreach ($this->arguments as $argument) {
       
   219             $values[$argument->getName()] = $argument->getDefault();
       
   220         }
       
   221 
       
   222         return $values;
       
   223     }
       
   224 
       
   225     /**
       
   226      * Sets the InputOption objects.
       
   227      *
       
   228      * @param array $options An array of InputOption objects
       
   229      *
       
   230      * @api
       
   231      */
       
   232     public function setOptions($options = array())
       
   233     {
       
   234         $this->options = array();
       
   235         $this->shortcuts = array();
       
   236         $this->addOptions($options);
       
   237     }
       
   238 
       
   239     /**
       
   240      * Add an array of InputOption objects.
       
   241      *
       
   242      * @param InputOption[] $options An array of InputOption objects
       
   243      *
       
   244      * @api
       
   245      */
       
   246     public function addOptions($options = array())
       
   247     {
       
   248         foreach ($options as $option) {
       
   249             $this->addOption($option);
       
   250         }
       
   251     }
       
   252 
       
   253     /**
       
   254      * Add an InputOption object.
       
   255      *
       
   256      * @param InputOption $option An InputOption object
       
   257      *
       
   258      * @throws \LogicException When option given already exist
       
   259      *
       
   260      * @api
       
   261      */
       
   262     public function addOption(InputOption $option)
       
   263     {
       
   264         if (isset($this->options[$option->getName()])) {
       
   265             throw new \LogicException(sprintf('An option named "%s" already exist.', $option->getName()));
       
   266         } else if (isset($this->shortcuts[$option->getShortcut()])) {
       
   267             throw new \LogicException(sprintf('An option with shortcut "%s" already exist.', $option->getShortcut()));
       
   268         }
       
   269 
       
   270         $this->options[$option->getName()] = $option;
       
   271         if ($option->getShortcut()) {
       
   272             $this->shortcuts[$option->getShortcut()] = $option->getName();
       
   273         }
       
   274     }
       
   275 
       
   276     /**
       
   277      * Returns an InputOption by name.
       
   278      *
       
   279      * @param string $name The InputOption name
       
   280      *
       
   281      * @return InputOption A InputOption object
       
   282      *
       
   283      * @api
       
   284      */
       
   285     public function getOption($name)
       
   286     {
       
   287         if (!$this->hasOption($name)) {
       
   288             throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
       
   289         }
       
   290 
       
   291         return $this->options[$name];
       
   292     }
       
   293 
       
   294     /**
       
   295      * Returns true if an InputOption object exists by name.
       
   296      *
       
   297      * @param string $name The InputOption name
       
   298      *
       
   299      * @return Boolean true if the InputOption object exists, false otherwise
       
   300      *
       
   301      * @api
       
   302      */
       
   303     public function hasOption($name)
       
   304     {
       
   305         return isset($this->options[$name]);
       
   306     }
       
   307 
       
   308     /**
       
   309      * Gets the array of InputOption objects.
       
   310      *
       
   311      * @return array An array of InputOption objects
       
   312      *
       
   313      * @api
       
   314      */
       
   315     public function getOptions()
       
   316     {
       
   317         return $this->options;
       
   318     }
       
   319 
       
   320     /**
       
   321      * Returns true if an InputOption object exists by shortcut.
       
   322      *
       
   323      * @param string $name The InputOption shortcut
       
   324      *
       
   325      * @return Boolean true if the InputOption object exists, false otherwise
       
   326      */
       
   327     public function hasShortcut($name)
       
   328     {
       
   329         return isset($this->shortcuts[$name]);
       
   330     }
       
   331 
       
   332     /**
       
   333      * Gets an InputOption by shortcut.
       
   334      *
       
   335      * @param string $shortcut the Shortcut name
       
   336      *
       
   337      * @return InputOption An InputOption object
       
   338      */
       
   339     public function getOptionForShortcut($shortcut)
       
   340     {
       
   341         return $this->getOption($this->shortcutToName($shortcut));
       
   342     }
       
   343 
       
   344     /**
       
   345      * Gets an array of default values.
       
   346      *
       
   347      * @return array An array of all default values
       
   348      */
       
   349     public function getOptionDefaults()
       
   350     {
       
   351         $values = array();
       
   352         foreach ($this->options as $option) {
       
   353             $values[$option->getName()] = $option->getDefault();
       
   354         }
       
   355 
       
   356         return $values;
       
   357     }
       
   358 
       
   359     /**
       
   360      * Returns the InputOption name given a shortcut.
       
   361      *
       
   362      * @param string $shortcut The shortcut
       
   363      *
       
   364      * @return string The InputOption name
       
   365      *
       
   366      * @throws \InvalidArgumentException When option given does not exist
       
   367      */
       
   368     private function shortcutToName($shortcut)
       
   369     {
       
   370         if (!isset($this->shortcuts[$shortcut])) {
       
   371             throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
       
   372         }
       
   373 
       
   374         return $this->shortcuts[$shortcut];
       
   375     }
       
   376 
       
   377     /**
       
   378      * Gets the synopsis.
       
   379      *
       
   380      * @return string The synopsis
       
   381      */
       
   382     public function getSynopsis()
       
   383     {
       
   384         $elements = array();
       
   385         foreach ($this->getOptions() as $option) {
       
   386             $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
       
   387             $elements[] = sprintf('['.($option->isValueRequired() ? '%s--%s="..."' : ($option->isValueOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName());
       
   388         }
       
   389 
       
   390         foreach ($this->getArguments() as $argument) {
       
   391             $elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : ''));
       
   392 
       
   393             if ($argument->isArray()) {
       
   394                 $elements[] = sprintf('... [%sN]', $argument->getName());
       
   395             }
       
   396         }
       
   397 
       
   398         return implode(' ', $elements);
       
   399     }
       
   400 
       
   401     /**
       
   402      * Returns a textual representation of the InputDefinition.
       
   403      *
       
   404      * @return string A string representing the InputDefinition
       
   405      */
       
   406     public function asText()
       
   407     {
       
   408         // find the largest option or argument name
       
   409         $max = 0;
       
   410         foreach ($this->getOptions() as $option) {
       
   411             $nameLength = strlen($option->getName()) + 2;
       
   412             if ($option->getShortcut()) {
       
   413                 $nameLength += strlen($option->getShortcut()) + 3;
       
   414             }
       
   415 
       
   416             $max = max($max, $nameLength);
       
   417         }
       
   418         foreach ($this->getArguments() as $argument) {
       
   419             $max = max($max, strlen($argument->getName()));
       
   420         }
       
   421         ++$max;
       
   422 
       
   423         $text = array();
       
   424 
       
   425         if ($this->getArguments()) {
       
   426             $text[] = '<comment>Arguments:</comment>';
       
   427             foreach ($this->getArguments() as $argument) {
       
   428                 if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
       
   429                     $default = sprintf('<comment> (default: %s)</comment>', is_array($argument->getDefault()) ? str_replace("\n", '', var_export($argument->getDefault(), true)): $argument->getDefault());
       
   430                 } else {
       
   431                     $default = '';
       
   432                 }
       
   433 
       
   434                 $description = str_replace("\n", "\n".str_pad('', $max + 2, ' '), $argument->getDescription());
       
   435 
       
   436                 $text[] = sprintf(" <info>%-${max}s</info> %s%s", $argument->getName(), $description, $default);
       
   437             }
       
   438 
       
   439             $text[] = '';
       
   440         }
       
   441 
       
   442         if ($this->getOptions()) {
       
   443             $text[] = '<comment>Options:</comment>';
       
   444 
       
   445             foreach ($this->getOptions() as $option) {
       
   446                 if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
       
   447                     $default = sprintf('<comment> (default: %s)</comment>', is_array($option->getDefault()) ? str_replace("\n", '', print_r($option->getDefault(), true)): $option->getDefault());
       
   448                 } else {
       
   449                     $default = '';
       
   450                 }
       
   451 
       
   452                 $multiple = $option->isArray() ? '<comment> (multiple values allowed)</comment>' : '';
       
   453                 $description = str_replace("\n", "\n".str_pad('', $max + 2, ' '), $option->getDescription());
       
   454 
       
   455                 $optionMax = $max - strlen($option->getName()) - 2;
       
   456                 $text[] = sprintf(" <info>%s</info> %-${optionMax}s%s%s%s",
       
   457                     '--'.$option->getName(),
       
   458                     $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '',
       
   459                     $description,
       
   460                     $default,
       
   461                     $multiple
       
   462                 );
       
   463             }
       
   464 
       
   465             $text[] = '';
       
   466         }
       
   467 
       
   468         return implode("\n", $text);
       
   469     }
       
   470 
       
   471     /**
       
   472      * Returns an XML representation of the InputDefinition.
       
   473      *
       
   474      * @param Boolean $asDom Whether to return a DOM or an XML string
       
   475      *
       
   476      * @return string|DOMDocument An XML string representing the InputDefinition
       
   477      */
       
   478     public function asXml($asDom = false)
       
   479     {
       
   480         $dom = new \DOMDocument('1.0', 'UTF-8');
       
   481         $dom->formatOutput = true;
       
   482         $dom->appendChild($definitionXML = $dom->createElement('definition'));
       
   483 
       
   484         $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
       
   485         foreach ($this->getArguments() as $argument) {
       
   486             $argumentsXML->appendChild($argumentXML = $dom->createElement('argument'));
       
   487             $argumentXML->setAttribute('name', $argument->getName());
       
   488             $argumentXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
       
   489             $argumentXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
       
   490             $argumentXML->appendChild($descriptionXML = $dom->createElement('description'));
       
   491             $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
       
   492 
       
   493             $argumentXML->appendChild($defaultsXML = $dom->createElement('defaults'));
       
   494             $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : ($argument->getDefault() ? array($argument->getDefault()) : array());
       
   495             foreach ($defaults as $default) {
       
   496                 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
       
   497                 $defaultXML->appendChild($dom->createTextNode($default));
       
   498             }
       
   499         }
       
   500 
       
   501         $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
       
   502         foreach ($this->getOptions() as $option) {
       
   503             $optionsXML->appendChild($optionXML = $dom->createElement('option'));
       
   504             $optionXML->setAttribute('name', '--'.$option->getName());
       
   505             $optionXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
       
   506             $optionXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
       
   507             $optionXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
       
   508             $optionXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
       
   509             $optionXML->appendChild($descriptionXML = $dom->createElement('description'));
       
   510             $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
       
   511 
       
   512             if ($option->acceptValue()) {
       
   513                 $optionXML->appendChild($defaultsXML = $dom->createElement('defaults'));
       
   514                 $defaults = is_array($option->getDefault()) ? $option->getDefault() : ($option->getDefault() ? array($option->getDefault()) : array());
       
   515                 foreach ($defaults as $default) {
       
   516                     $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
       
   517                     $defaultXML->appendChild($dom->createTextNode($default));
       
   518                 }
       
   519             }
       
   520         }
       
   521 
       
   522         return $asDom ? $dom : $dom->saveXml();
       
   523     }
       
   524 }