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 }
|