1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* this file is part of pipelines */ |
4
|
|
|
|
5
|
|
|
namespace Ktomk\Pipelines\Cli; |
6
|
|
|
|
7
|
|
|
use InvalidArgumentException; |
8
|
|
|
use Ktomk\Pipelines\Cli\Args\Args as ArgsArgs; |
9
|
|
|
use Ktomk\Pipelines\Cli\Args\OptionFilterIterator; |
10
|
|
|
use Ktomk\Pipelines\Cli\Args\OptionIterator; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Class Args |
14
|
|
|
* |
15
|
|
|
* Facade class to access arguments related functionality |
16
|
|
|
* |
17
|
|
|
* @package Ktomk\Pipelines\Cli |
18
|
|
|
*/ |
19
|
|
|
class Args extends ArgsArgs |
20
|
|
|
{ |
21
|
|
|
/** |
22
|
|
|
* @var string $utility name |
23
|
|
|
*/ |
24
|
|
|
private $utility = ''; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* create from $argv |
28
|
|
|
* |
29
|
|
|
* @param array $argv |
30
|
|
|
* |
31
|
|
|
* @throws InvalidArgumentException |
32
|
|
|
* |
33
|
|
|
* @return Args |
34
|
|
|
*/ |
35
|
5 |
|
public static function create(array $argv) |
36
|
|
|
{ |
37
|
5 |
|
if (0 === count($argv)) { |
38
|
1 |
|
throw new InvalidArgumentException('There must be at least one argument (the command name)'); |
39
|
|
|
} |
40
|
|
|
|
41
|
4 |
|
$command = (string)array_shift($argv); |
42
|
4 |
|
$args = new self($argv); |
43
|
4 |
|
$args->utility = $command; |
44
|
|
|
|
45
|
4 |
|
return $args; |
46
|
|
|
} |
47
|
|
|
|
48
|
21 |
|
public function __construct(array $arguments) |
49
|
|
|
{ |
50
|
21 |
|
$this->arguments = $arguments; |
51
|
21 |
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* test for option and consume any of them. these options |
55
|
|
|
* are all w/o option argument. e.g. check for -v/--verbose. |
56
|
|
|
* |
57
|
|
|
* @param string|string[] $option |
58
|
|
|
* |
59
|
|
|
* @throws InvalidArgumentException |
60
|
|
|
* |
61
|
|
|
* @return bool |
62
|
|
|
*/ |
63
|
3 |
|
public function hasOption($option) |
64
|
|
|
{ |
65
|
3 |
|
$options = new OptionFilterIterator($this, $option); |
66
|
|
|
|
67
|
|
|
# consume arguments |
68
|
3 |
|
foreach ($options as $index => $argument) { |
69
|
3 |
|
unset($this->arguments[$index]); |
70
|
|
|
} |
71
|
|
|
|
72
|
3 |
|
return isset($index); |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* map options on array keyed with options to parameters |
77
|
|
|
* |
78
|
|
|
* both provided to callback, options as first, parameter as |
79
|
|
|
* second parameter. |
80
|
|
|
* |
81
|
|
|
* @param array $map |
82
|
|
|
* @param callable $callback |
83
|
|
|
* |
84
|
|
|
* @return array results |
85
|
|
|
*/ |
86
|
1 |
|
public function mapOption(array $map, $callback) |
87
|
|
|
{ |
88
|
1 |
|
$results = array(); |
89
|
1 |
|
foreach ($map as $option => $parameter) { |
90
|
1 |
|
$result = array(false, null); |
91
|
1 |
|
if ($this->hasOption($option)) { |
92
|
1 |
|
$result = array(true, call_user_func($callback, $option, $parameter)); |
93
|
|
|
} |
94
|
1 |
|
$results[$option] = $result; |
95
|
|
|
} |
96
|
|
|
|
97
|
1 |
|
return $results; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* @return null|string |
102
|
|
|
*/ |
103
|
8 |
|
public function getFirstRemainingOption() |
104
|
|
|
{ |
105
|
|
|
/** @noinspection LoopWhichDoesNotLoopInspection */ |
106
|
8 |
|
foreach (new OptionIterator($this) as $option) { |
107
|
3 |
|
return $option; |
108
|
|
|
} |
109
|
|
|
|
110
|
5 |
|
return null; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* get option w/ optional argument |
115
|
|
|
* |
116
|
|
|
* optional by equal sign (--option=argument) |
117
|
|
|
* |
118
|
|
|
* @param string|string[] $option |
119
|
|
|
* @param null|bool|string $default [optional] argument |
120
|
|
|
* |
121
|
|
|
* @return null|bool|string null when not found, default when found with no argument or the argument |
122
|
|
|
*/ |
123
|
1 |
|
public function getOptionOptionalArgument($option, $default = null) |
124
|
|
|
{ |
125
|
1 |
|
$result = null; |
126
|
|
|
|
127
|
1 |
|
$options = new OptionIterator($this); |
128
|
1 |
|
if ($options->seekOption($option) || $options->currentMatchesOption($option)) { |
|
|
|
|
129
|
1 |
|
$buffer = $options->current(); |
130
|
1 |
|
$equalPos = strpos($buffer, '='); |
131
|
1 |
|
if (false === $equalPos) { |
132
|
1 |
|
$result = $default; |
133
|
|
|
} else { |
134
|
1 |
|
$result = (string)substr($buffer, $equalPos + 1); |
135
|
|
|
} |
136
|
1 |
|
unset($this->arguments[$options->key()]); |
137
|
|
|
} |
138
|
|
|
|
139
|
1 |
|
return $result; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* Get the argument of an option. |
144
|
|
|
* |
145
|
|
|
* NOTE: returns only the first option value if multiple options would match |
146
|
|
|
* |
147
|
|
|
* @param string|string[] $option |
148
|
|
|
* @param null|bool|string $default [optional] |
149
|
|
|
* @param bool $required [optional] |
150
|
|
|
* |
151
|
|
|
* @throws InvalidArgumentException |
152
|
|
|
* @throws ArgsException |
153
|
|
|
* |
154
|
|
|
* @return null|bool|string |
155
|
|
|
*/ |
156
|
7 |
|
public function getOptionArgument($option, $default = null, $required = false) |
157
|
|
|
{ |
158
|
7 |
|
$result = null; |
159
|
|
|
|
160
|
|
|
/** @var OptionFilterIterator|OptionIterator $options */ |
161
|
7 |
|
$options = new OptionFilterIterator($this, $option); |
162
|
|
|
/** @noinspection LoopWhichDoesNotLoopInspection */ |
163
|
7 |
|
foreach ($options as $index => $argument) { |
164
|
|
|
/** @scrutinizer ignore-call */ |
165
|
3 |
|
$result = $options->getArgument(); |
166
|
1 |
|
unset($this->arguments[$index], $this->arguments[$index + 1]); |
167
|
|
|
|
168
|
1 |
|
break; # first match |
169
|
|
|
} |
170
|
|
|
|
171
|
5 |
|
if (null === $result) { |
172
|
4 |
|
if ($required) { |
173
|
1 |
|
throw new ArgsException(sprintf( |
174
|
1 |
|
'option %s is not optional', |
175
|
|
|
$options->/** @scrutinizer ignore-call */ |
176
|
1 |
|
getOptionDescription() |
177
|
|
|
)); |
178
|
|
|
} |
179
|
|
|
|
180
|
3 |
|
$result = $default; |
181
|
|
|
} |
182
|
|
|
|
183
|
4 |
|
return $result; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* Get the argument of an option. |
188
|
|
|
* |
189
|
|
|
* NOTE: returns only the first option value if multiple options would match |
190
|
|
|
* |
191
|
|
|
* @param string|string[] $option |
192
|
|
|
* @param string $default |
193
|
|
|
* @param bool $required [optional] |
194
|
|
|
* |
195
|
|
|
* @throws InvalidArgumentException |
196
|
|
|
* @throws ArgsException |
197
|
|
|
* |
198
|
|
|
* @return string |
199
|
|
|
*/ |
200
|
1 |
|
public function getStringOptionArgument($option, $default, $required = false) |
201
|
|
|
{ |
202
|
1 |
|
if (!is_string($default)) { |
|
|
|
|
203
|
1 |
|
throw new InvalidArgumentException(sprintf('default value must be string, %s given', gettype($default))); |
204
|
|
|
} |
205
|
|
|
|
206
|
1 |
|
return (string)$this->getOptionArgument($option, $default, $required); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* @return string |
211
|
|
|
*/ |
212
|
1 |
|
public function getUtility() |
213
|
|
|
{ |
214
|
1 |
|
return $this->utility; |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* @return array |
219
|
|
|
*/ |
220
|
1 |
|
public function getRemaining() |
221
|
|
|
{ |
222
|
1 |
|
return $this->arguments; |
223
|
|
|
} |
224
|
|
|
} |
225
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.