annotate vendor/consolidation/annotated-command/src/CommandData.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@0 1 <?php
Chris@0 2 namespace Consolidation\AnnotatedCommand;
Chris@0 3
Chris@17 4 use Consolidation\OutputFormatters\Options\FormatterOptions;
Chris@0 5 use Symfony\Component\Console\Input\ArgvInput;
Chris@0 6 use Symfony\Component\Console\Input\InputInterface;
Chris@0 7 use Symfony\Component\Console\Output\OutputInterface;
Chris@0 8
Chris@0 9 class CommandData
Chris@0 10 {
Chris@0 11 /** var AnnotationData */
Chris@0 12 protected $annotationData;
Chris@0 13 /** var InputInterface */
Chris@0 14 protected $input;
Chris@0 15 /** var OutputInterface */
Chris@0 16 protected $output;
Chris@0 17 /** var boolean */
Chris@0 18 protected $includeOptionsInArgs;
Chris@0 19 /** var array */
Chris@0 20 protected $specialDefaults = [];
Chris@17 21 /** @var string[] */
Chris@17 22 protected $injectedInstances = [];
Chris@17 23 /** @var FormatterOptions */
Chris@17 24 protected $formatterOptions;
Chris@0 25
Chris@0 26 public function __construct(
Chris@0 27 AnnotationData $annotationData,
Chris@0 28 InputInterface $input,
Chris@17 29 OutputInterface $output
Chris@0 30 ) {
Chris@0 31 $this->annotationData = $annotationData;
Chris@0 32 $this->input = $input;
Chris@0 33 $this->output = $output;
Chris@0 34 $this->includeOptionsInArgs = true;
Chris@0 35 }
Chris@0 36
Chris@0 37 /**
Chris@17 38 * For internal use only; inject an instance to be passed back
Chris@17 39 * to the command callback as a parameter.
Chris@0 40 */
Chris@17 41 public function injectInstance($injectedInstance)
Chris@0 42 {
Chris@17 43 array_unshift($this->injectedInstances, $injectedInstance);
Chris@0 44 return $this;
Chris@0 45 }
Chris@0 46
Chris@0 47 /**
Chris@17 48 * Provide a reference to the instances that will be added to the
Chris@17 49 * beginning of the parameter list when the command callback is invoked.
Chris@17 50 */
Chris@17 51 public function injectedInstances()
Chris@17 52 {
Chris@17 53 return $this->injectedInstances;
Chris@17 54 }
Chris@17 55
Chris@17 56 /**
Chris@0 57 * For backwards-compatibility mode only: disable addition of
Chris@0 58 * options on the end of the arguments list.
Chris@0 59 */
Chris@0 60 public function setIncludeOptionsInArgs($includeOptionsInArgs)
Chris@0 61 {
Chris@0 62 $this->includeOptionsInArgs = $includeOptionsInArgs;
Chris@0 63 return $this;
Chris@0 64 }
Chris@0 65
Chris@0 66 public function annotationData()
Chris@0 67 {
Chris@0 68 return $this->annotationData;
Chris@0 69 }
Chris@0 70
Chris@17 71 public function formatterOptions()
Chris@17 72 {
Chris@17 73 return $this->formatterOptions;
Chris@17 74 }
Chris@17 75
Chris@17 76 public function setFormatterOptions($formatterOptions)
Chris@17 77 {
Chris@17 78 $this->formatterOptions = $formatterOptions;
Chris@17 79 }
Chris@17 80
Chris@0 81 public function input()
Chris@0 82 {
Chris@0 83 return $this->input;
Chris@0 84 }
Chris@0 85
Chris@0 86 public function output()
Chris@0 87 {
Chris@0 88 return $this->output;
Chris@0 89 }
Chris@0 90
Chris@0 91 public function arguments()
Chris@0 92 {
Chris@0 93 return $this->input->getArguments();
Chris@0 94 }
Chris@0 95
Chris@0 96 public function options()
Chris@0 97 {
Chris@0 98 // We cannot tell the difference between '--foo' (an option without
Chris@0 99 // a value) and the absence of '--foo' when the option has an optional
Chris@0 100 // value, and the current vallue of the option is 'null' using only
Chris@0 101 // the public methods of InputInterface. We'll try to figure out
Chris@0 102 // which is which by other means here.
Chris@0 103 $options = $this->getAdjustedOptions();
Chris@0 104
Chris@0 105 // Make two conversions here:
Chris@0 106 // --foo=0 wil convert $value from '0' to 'false' for binary options.
Chris@0 107 // --foo with $value of 'true' will be forced to 'false' if --no-foo exists.
Chris@0 108 foreach ($options as $option => $value) {
Chris@0 109 if ($this->shouldConvertOptionToFalse($options, $option, $value)) {
Chris@0 110 $options[$option] = false;
Chris@0 111 }
Chris@0 112 }
Chris@0 113
Chris@0 114 return $options;
Chris@0 115 }
Chris@0 116
Chris@0 117 /**
Chris@0 118 * Use 'hasParameterOption()' to attempt to disambiguate option states.
Chris@0 119 */
Chris@0 120 protected function getAdjustedOptions()
Chris@0 121 {
Chris@0 122 $options = $this->input->getOptions();
Chris@0 123
Chris@0 124 // If Input isn't an ArgvInput, then return the options as-is.
Chris@0 125 if (!$this->input instanceof ArgvInput) {
Chris@0 126 return $options;
Chris@0 127 }
Chris@0 128
Chris@0 129 // If we have an ArgvInput, then we can determine if options
Chris@0 130 // are missing from the command line. If the option value is
Chris@0 131 // missing from $input, then we will keep the value `null`.
Chris@0 132 // If it is present, but has no explicit value, then change it its
Chris@0 133 // value to `true`.
Chris@0 134 foreach ($options as $option => $value) {
Chris@0 135 if (($value === null) && ($this->input->hasParameterOption("--$option"))) {
Chris@0 136 $options[$option] = true;
Chris@0 137 }
Chris@0 138 }
Chris@0 139
Chris@0 140 return $options;
Chris@0 141 }
Chris@0 142
Chris@0 143 protected function shouldConvertOptionToFalse($options, $option, $value)
Chris@0 144 {
Chris@0 145 // If the value is 'true' (e.g. the option is '--foo'), then convert
Chris@0 146 // it to false if there is also an option '--no-foo'. n.b. if the
Chris@0 147 // commandline has '--foo=bar' then $value will not be 'true', and
Chris@0 148 // --no-foo will be ignored.
Chris@0 149 if ($value === true) {
Chris@0 150 // Check if the --no-* option exists. Note that none of the other
Chris@0 151 // alteration apply in the $value == true case, so we can exit early here.
Chris@0 152 $negation_key = 'no-' . $option;
Chris@0 153 return array_key_exists($negation_key, $options) && $options[$negation_key];
Chris@0 154 }
Chris@0 155
Chris@0 156 // If the option is '--foo=0', convert the '0' to 'false' when appropriate.
Chris@0 157 if ($value !== '0') {
Chris@0 158 return false;
Chris@0 159 }
Chris@0 160
Chris@0 161 // The '--foo=0' convertion is only applicable when the default value
Chris@0 162 // is not in the special defaults list. i.e. you get a literal '0'
Chris@0 163 // when your default is a string.
Chris@0 164 return in_array($option, $this->specialDefaults);
Chris@0 165 }
Chris@0 166
Chris@0 167 public function cacheSpecialDefaults($definition)
Chris@0 168 {
Chris@0 169 foreach ($definition->getOptions() as $option => $inputOption) {
Chris@0 170 $defaultValue = $inputOption->getDefault();
Chris@0 171 if (($defaultValue === null) || ($defaultValue === true)) {
Chris@0 172 $this->specialDefaults[] = $option;
Chris@0 173 }
Chris@0 174 }
Chris@0 175 }
Chris@0 176
Chris@0 177 public function getArgsWithoutAppName()
Chris@0 178 {
Chris@0 179 $args = $this->arguments();
Chris@0 180
Chris@0 181 // When called via the Application, the first argument
Chris@0 182 // will be the command name. The Application alters the
Chris@0 183 // input definition to match, adding a 'command' argument
Chris@0 184 // to the beginning.
Chris@13 185 if ($this->input->hasArgument('command')) {
Chris@13 186 array_shift($args);
Chris@13 187 }
Chris@0 188
Chris@0 189 return $args;
Chris@0 190 }
Chris@0 191
Chris@0 192 public function getArgsAndOptions()
Chris@0 193 {
Chris@0 194 // Get passthrough args, and add the options on the end.
Chris@0 195 $args = $this->getArgsWithoutAppName();
Chris@0 196 if ($this->includeOptionsInArgs) {
Chris@0 197 $args['options'] = $this->options();
Chris@0 198 }
Chris@0 199 return $args;
Chris@0 200 }
Chris@0 201 }