Chris@0: annotationData = $annotationData; Chris@0: $this->input = $input; Chris@0: $this->output = $output; Chris@0: $this->includeOptionsInArgs = true; Chris@0: } Chris@0: Chris@0: /** Chris@17: * For internal use only; inject an instance to be passed back Chris@17: * to the command callback as a parameter. Chris@0: */ Chris@17: public function injectInstance($injectedInstance) Chris@0: { Chris@17: array_unshift($this->injectedInstances, $injectedInstance); Chris@0: return $this; Chris@0: } Chris@0: Chris@0: /** Chris@17: * Provide a reference to the instances that will be added to the Chris@17: * beginning of the parameter list when the command callback is invoked. Chris@17: */ Chris@17: public function injectedInstances() Chris@17: { Chris@17: return $this->injectedInstances; Chris@17: } Chris@17: Chris@17: /** Chris@0: * For backwards-compatibility mode only: disable addition of Chris@0: * options on the end of the arguments list. Chris@0: */ Chris@0: public function setIncludeOptionsInArgs($includeOptionsInArgs) Chris@0: { Chris@0: $this->includeOptionsInArgs = $includeOptionsInArgs; Chris@0: return $this; Chris@0: } Chris@0: Chris@0: public function annotationData() Chris@0: { Chris@0: return $this->annotationData; Chris@0: } Chris@0: Chris@17: public function formatterOptions() Chris@17: { Chris@17: return $this->formatterOptions; Chris@17: } Chris@17: Chris@17: public function setFormatterOptions($formatterOptions) Chris@17: { Chris@17: $this->formatterOptions = $formatterOptions; Chris@17: } Chris@17: Chris@0: public function input() Chris@0: { Chris@0: return $this->input; Chris@0: } Chris@0: Chris@0: public function output() Chris@0: { Chris@0: return $this->output; Chris@0: } Chris@0: Chris@0: public function arguments() Chris@0: { Chris@0: return $this->input->getArguments(); Chris@0: } Chris@0: Chris@0: public function options() Chris@0: { Chris@0: // We cannot tell the difference between '--foo' (an option without Chris@0: // a value) and the absence of '--foo' when the option has an optional Chris@0: // value, and the current vallue of the option is 'null' using only Chris@0: // the public methods of InputInterface. We'll try to figure out Chris@0: // which is which by other means here. Chris@0: $options = $this->getAdjustedOptions(); Chris@0: Chris@0: // Make two conversions here: Chris@0: // --foo=0 wil convert $value from '0' to 'false' for binary options. Chris@0: // --foo with $value of 'true' will be forced to 'false' if --no-foo exists. Chris@0: foreach ($options as $option => $value) { Chris@0: if ($this->shouldConvertOptionToFalse($options, $option, $value)) { Chris@0: $options[$option] = false; Chris@0: } Chris@0: } Chris@0: Chris@0: return $options; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Use 'hasParameterOption()' to attempt to disambiguate option states. Chris@0: */ Chris@0: protected function getAdjustedOptions() Chris@0: { Chris@0: $options = $this->input->getOptions(); Chris@0: Chris@0: // If Input isn't an ArgvInput, then return the options as-is. Chris@0: if (!$this->input instanceof ArgvInput) { Chris@0: return $options; Chris@0: } Chris@0: Chris@0: // If we have an ArgvInput, then we can determine if options Chris@0: // are missing from the command line. If the option value is Chris@0: // missing from $input, then we will keep the value `null`. Chris@0: // If it is present, but has no explicit value, then change it its Chris@0: // value to `true`. Chris@0: foreach ($options as $option => $value) { Chris@0: if (($value === null) && ($this->input->hasParameterOption("--$option"))) { Chris@0: $options[$option] = true; Chris@0: } Chris@0: } Chris@0: Chris@0: return $options; Chris@0: } Chris@0: Chris@0: protected function shouldConvertOptionToFalse($options, $option, $value) Chris@0: { Chris@0: // If the value is 'true' (e.g. the option is '--foo'), then convert Chris@0: // it to false if there is also an option '--no-foo'. n.b. if the Chris@0: // commandline has '--foo=bar' then $value will not be 'true', and Chris@0: // --no-foo will be ignored. Chris@0: if ($value === true) { Chris@0: // Check if the --no-* option exists. Note that none of the other Chris@0: // alteration apply in the $value == true case, so we can exit early here. Chris@0: $negation_key = 'no-' . $option; Chris@0: return array_key_exists($negation_key, $options) && $options[$negation_key]; Chris@0: } Chris@0: Chris@0: // If the option is '--foo=0', convert the '0' to 'false' when appropriate. Chris@0: if ($value !== '0') { Chris@0: return false; Chris@0: } Chris@0: Chris@0: // The '--foo=0' convertion is only applicable when the default value Chris@0: // is not in the special defaults list. i.e. you get a literal '0' Chris@0: // when your default is a string. Chris@0: return in_array($option, $this->specialDefaults); Chris@0: } Chris@0: Chris@0: public function cacheSpecialDefaults($definition) Chris@0: { Chris@0: foreach ($definition->getOptions() as $option => $inputOption) { Chris@0: $defaultValue = $inputOption->getDefault(); Chris@0: if (($defaultValue === null) || ($defaultValue === true)) { Chris@0: $this->specialDefaults[] = $option; Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: public function getArgsWithoutAppName() Chris@0: { Chris@0: $args = $this->arguments(); Chris@0: Chris@0: // When called via the Application, the first argument Chris@0: // will be the command name. The Application alters the Chris@0: // input definition to match, adding a 'command' argument Chris@0: // to the beginning. Chris@13: if ($this->input->hasArgument('command')) { Chris@13: array_shift($args); Chris@13: } Chris@0: Chris@0: return $args; Chris@0: } Chris@0: Chris@0: public function getArgsAndOptions() Chris@0: { Chris@0: // Get passthrough args, and add the options on the end. Chris@0: $args = $this->getArgsWithoutAppName(); Chris@0: if ($this->includeOptionsInArgs) { Chris@0: $args['options'] = $this->options(); Chris@0: } Chris@0: return $args; Chris@0: } Chris@0: }