Completed
Push — commands ( 7b5fcb )
by Craig
06:02
created

Command::defined()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.2
c 0
b 0
f 0
cc 4
eloc 9
nc 4
nop 2
1
<?php
2
3
namespace League\CLImate;
4
5
use League\CLImate\Argument\Argument;
6
use League\CLImate\Argument\Filter;
7
use League\CLImate\Argument\Parser;
8
use League\CLImate\Argument\Summary;
9
10
class Command
11
{
12
    /**
13
     * @var string $name The name of the command.
14
     */
15
    private $name;
16
17
    /**
18
     * @var CLImate $climate The parent instance to handle output.
19
     */
20
    private $climate;
21
22
    /**
23
     * An array of arguments passed to the program.
24
     *
25
     * @var Argument[] $arguments
26
     */
27
    private $arguments = [];
28
29
    /**
30
     * A program's description.
31
     *
32
     * @var string $description
33
     */
34
    private $description;
35
36
    /**
37
     * Filter class to find various types of arguments
38
     *
39
     * @var \League\CLImate\Argument\Filter $filter
40
     */
41
    private $filter;
42
43
    /**
44
     * Summary builder class
45
     *
46
     * @var \League\CLImate\Argument\Summary $summary
47
     */
48
    private $summary;
49
50
    /**
51
     * Argument parser class
52
     *
53
     * @var \League\CLImate\Argument\Parser $parser
54
     */
55
    private $parser;
56
57
    public function __construct($name, CLImate $climate)
58
    {
59
        $this->name = $name;
60
        $this->climate = $climate;
61
62
        $this->filter  = new Filter;
63
        $this->summary = new Summary;
64
        $this->parser  = new Parser;
65
    }
66
67
    /**
68
     * Add an argument.
69
     *
70
     * @throws \Exception if $argument isn't an array or Argument object.
71
     * @param Argument|string $argument
72
     * @param $options
73
     */
74
    public function add($argument, array $options = [])
75
    {
76
        if (is_string($argument)) {
77
            $argument = Argument::createFromArray($argument, $options);
78
        }
79
80
        if (!($argument instanceof Argument)) {
81
            throw new \Exception('Please provide an argument name or object.');
82
        }
83
84
        $this->arguments[$argument->name()] = $argument;
85
    }
86
87
88
    /**
89
     * Determine if an argument exists.
90
     *
91
     * @param string $name
92
     * @return bool
93
     */
94
    public function exists($name)
95
    {
96
        return isset($this->arguments[$name]);
97
    }
98
99
100
    /**
101
     * Retrieve an argument's value.
102
     *
103
     * @param string $name
104
     * @return string|int|float|bool|null
105
     */
106
    public function get($name)
107
    {
108
        return isset($this->arguments[$name]) ? $this->arguments[$name]->value() : null;
109
    }
110
111
112
    /**
113
     * Retrieve all arguments.
114
     *
115
     * @return Argument[]
116
     */
117
    public function all()
118
    {
119
        return $this->arguments;
120
    }
121
122
123
    /**
124
     * Determine if an argument has been defined on the command line.
125
     *
126
     * This can be useful for making sure an argument is present on the command
127
     * line before parse()'ing them into argument objects.
128
     *
129
     * @param string $name
130
     * @param array $argv
131
     *
132
     * @return bool
133
     */
134
    public function defined($name, array $argv = null)
135
    {
136
        // The argument isn't defined if it's not defined by the calling code.
137
        if (!$this->exists($name)) {
138
            return false;
139
        }
140
141
        $argument = $this->arguments[$name];
142
        $command_arguments = $this->parser->arguments($argv);
143
144
        foreach ($command_arguments as $command_argument) {
145
            if ($this->isArgument($argument, $command_argument)) {
146
                return true;
147
            }
148
        }
149
150
        return false;
151
    }
152
153
154
    /**
155
     * Check if the defined argument matches the command argument.
156
     *
157
     * @param Argument $argument
158
     * @param string $command_argument
159
     *
160
     * @return bool
161
     */
162
    private function isArgument($argument, $command_argument)
163
    {
164
        $possibilities = [
165
            $argument->prefix()     => "-{$argument->prefix()}",
166
            $argument->longPrefix() => "--{$argument->longPrefix()}",
167
        ];
168
169
        foreach ($possibilities as $key => $search) {
170
            if ($key && strpos($command_argument, $search) === 0) {
171
                return true;
172
            }
173
        }
174
175
        return false;
176
    }
177
178
179
    /**
180
     * Retrieve all arguments as key/value pairs.
181
     *
182
     * @return array
183
     */
184
    public function toArray()
185
    {
186
        $return = [];
187
188
        foreach ($this->all() as $name => $argument) {
189
            $return[$name] = $argument->value();
190
        }
191
192
        return $return;
193
    }
194
195
196
    /**
197
     * Set a program's description.
198
     *
199
     * @param string $description
200
     */
201
    public function description($description)
202
    {
203
        $this->description = trim($description);
204
    }
205
206
207
    /**
208
     * Output a script's usage statement.
209
     *
210
     * @param CLImate $climate
211
     * @param array $argv
212
     */
213
    public function usage(CLImate $climate, array $argv = null)
214
    {
215
        $this->summary
216
                ->setClimate($climate)
217
                ->setDescription($this->description)
218
                ->setCommand($this->parser->command($argv))
219
                ->setFilter($this->filter, $this->all())
220
                ->output();
221
    }
222
223
224
    /**
225
     * Parse command line arguments into CLImate arguments.
226
     *
227
     * @throws \Exception if required arguments aren't defined.
228
     * @param array $argv
229
     */
230
    public function parse(array $argv = null)
231
    {
232
        $this->parser->setFilter($this->filter, $this->all());
233
234
        $this->parser->parse($argv);
235
    }
236
237
238
    /**
239
     * Get the trailing arguments
240
     *
241
     * @return string|null
242
     */
243
    public function trailing()
244
    {
245
        return $this->parser->trailing();
246
    }
247
}
248