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