Passed
Push — master ( 88d9d6...ec4c8d )
by Tom
04:42
created

Args   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 209
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 54
c 1
b 0
f 0
dl 0
loc 209
ccs 62
cts 62
cp 1
rs 10
wmc 21

10 Methods

Rating   Name   Duplication   Size   Complexity  
A mapOption() 0 12 3
A getOptionOptionalArgument() 0 20 3
A getStringOptionArgument() 0 7 2
A __construct() 0 3 1
A getOptionArgument() 0 26 4
A create() 0 11 2
A getUtility() 0 3 1
A hasOption() 0 10 2
A getRemaining() 0 3 1
A getFirstRemainingOption() 0 8 2
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
        $options->seekOption($option);
129 1
        if (!$options->currentMatchesOption($option)) {
130 1
            return $result;
131
        }
132
133 1
        $buffer = $options->current();
134 1
        $equalPos = strpos($buffer, '=');
135 1
        if (false === $equalPos) {
136 1
            $result = $default;
137
        } else {
138 1
            $result = (string)substr($buffer, $equalPos + 1);
139
        }
140 1
        unset($this->arguments[$options->key()]);
141
142 1
        return $result;
143
    }
144
145
    /**
146
     * Get the argument of an option.
147
     *
148
     * NOTE: returns only the first option value if multiple options would match
149
     *
150
     * @param string|string[] $option
151
     * @param null|int|string $default [optional]
152
     * @param bool $required [optional]
153
     *
154
     * @throws InvalidArgumentException
155
     * @throws ArgsException
156
     *
157
     * @return null|bool|string
158
     *
159
     * @psalm-template T as null|string|int
160
     * @psalm-param T $default
161
     * @psalm-return (T is null ? null|string : (T is string ? string : null|int))
162
     */
163 7
    public function getOptionArgument($option, $default = null, $required = false)
164
    {
165 7
        $result = null;
166
167 7
        $options = new OptionFilterIterator($this, $option);
168
        /** @noinspection LoopWhichDoesNotLoopInspection */
169 7
        foreach ($options as $index => $argument) {
170
            /** @scrutinizer ignore-call */
171 3
            $result = $options->getArgument();
172 1
            unset($this->arguments[$index], $this->arguments[$index + 1]);
173
174 1
            break; # first match
175
        }
176
177 5
        if (null === $result) {
178 4
            if ($required) {
179 1
                throw new ArgsException(sprintf(
180 1
                    'option %s is not optional',
181 1
                    $options->getOptionDescription()
182
                ));
183
            }
184
185 3
            $result = $default;
186
        }
187
188 4
        return $result;
189
    }
190
191
    /**
192
     * Get the argument of an option.
193
     *
194
     * NOTE: returns only the first option value if multiple options would match
195
     *
196
     * @param string|string[] $option
197
     * @param string $default
198
     * @param bool $required [optional]
199
     *
200
     * @throws InvalidArgumentException
201
     * @throws ArgsException
202
     *
203
     * @return string
204
     */
205 1
    public function getStringOptionArgument($option, $default, $required = false)
206
    {
207 1
        if (!is_string($default)) {
0 ignored issues
show
introduced by
The condition is_string($default) is always true.
Loading history...
208 1
            throw new InvalidArgumentException(sprintf('default value must be string, %s given', gettype($default)));
209
        }
210
211 1
        return (string)$this->getOptionArgument($option, $default, $required);
212
    }
213
214
    /**
215
     * @return string
216
     */
217 1
    public function getUtility()
218
    {
219 1
        return $this->utility;
220
    }
221
222
    /**
223
     * @return array
224
     */
225 1
    public function getRemaining()
226
    {
227 1
        return $this->arguments;
228
    }
229
}
230