Definition   F
last analyzed

Complexity

Total Complexity 63

Size/Duplication

Total Lines 360
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 103
dl 0
loc 360
ccs 0
cts 124
cp 0
rs 3.36
c 0
b 0
f 0
wmc 63

22 Methods

Rating   Name   Duplication   Size   Complexity  
A setDefinition() 0 14 3
A getArgumentDefaults() 0 8 2
A setOptions() 0 5 1
A setArguments() 0 7 1
A hasShortcut() 0 3 1
A hasArgument() 0 5 2
A getArgumentCount() 0 3 2
B addArgument() 0 25 7
A getArgument() 0 9 3
A hasOption() 0 3 1
A getOptionDefaults() 0 8 2
A getArguments() 0 3 1
A addArguments() 0 5 3
B addOption() 0 20 9
C getSynopsis() 0 38 15
A getOptionForShortcut() 0 3 1
A getOption() 0 7 2
A __construct() 0 3 1
A getArgumentRequiredCount() 0 3 1
A addOptions() 0 4 2
A getOptions() 0 3 1
A shortcutToName() 0 7 2

How to fix   Complexity   

Complex Class

Complex classes like Definition often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Definition, and based on these observations, apply Extract Interface, too.

1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <[email protected]>
10
// +----------------------------------------------------------------------
11
12
namespace think\console\input;
13
14
class Definition
15
{
16
17
    /**
18
     * @var Argument[]
19
     */
20
    private $arguments;
21
22
    private $requiredCount;
23
    private $hasAnArrayArgument = false;
24
    private $hasOptional;
25
26
    /**
27
     * @var Option[]
28
     */
29
    private $options;
30
    private $shortcuts;
31
32
    /**
33
     * 构造方法
34
     * @param array $definition
35
     * @api
36
     */
37
    public function __construct(array $definition = [])
38
    {
39
        $this->setDefinition($definition);
40
    }
41
42
    /**
43
     * 设置指令的定义
44
     * @param array $definition 定义的数组
45
     */
46
    public function setDefinition(array $definition): void
47
    {
48
        $arguments = [];
49
        $options   = [];
50
        foreach ($definition as $item) {
51
            if ($item instanceof Option) {
52
                $options[] = $item;
53
            } else {
54
                $arguments[] = $item;
55
            }
56
        }
57
58
        $this->setArguments($arguments);
59
        $this->setOptions($options);
60
    }
61
62
    /**
63
     * 设置参数
64
     * @param Argument[] $arguments 参数数组
65
     */
66
    public function setArguments(array $arguments = []): void
67
    {
68
        $this->arguments          = [];
69
        $this->requiredCount      = 0;
70
        $this->hasOptional        = false;
71
        $this->hasAnArrayArgument = false;
72
        $this->addArguments($arguments);
73
    }
74
75
    /**
76
     * 添加参数
77
     * @param Argument[] $arguments 参数数组
78
     * @api
79
     */
80
    public function addArguments(array $arguments = []): void
81
    {
82
        if (null !== $arguments) {
0 ignored issues
show
introduced by
The condition null !== $arguments is always true.
Loading history...
83
            foreach ($arguments as $argument) {
84
                $this->addArgument($argument);
85
            }
86
        }
87
    }
88
89
    /**
90
     * 添加一个参数
91
     * @param Argument $argument 参数
92
     * @throws \LogicException
93
     */
94
    public function addArgument(Argument $argument): void
95
    {
96
        if (isset($this->arguments[$argument->getName()])) {
97
            throw new \LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
98
        }
99
100
        if ($this->hasAnArrayArgument) {
101
            throw new \LogicException('Cannot add an argument after an array argument.');
102
        }
103
104
        if ($argument->isRequired() && $this->hasOptional) {
105
            throw new \LogicException('Cannot add a required argument after an optional one.');
106
        }
107
108
        if ($argument->isArray()) {
109
            $this->hasAnArrayArgument = true;
110
        }
111
112
        if ($argument->isRequired()) {
113
            ++$this->requiredCount;
114
        } else {
115
            $this->hasOptional = true;
116
        }
117
118
        $this->arguments[$argument->getName()] = $argument;
119
    }
120
121
    /**
122
     * 根据名称或者位置获取参数
123
     * @param string|int $name 参数名或者位置
124
     * @return Argument 参数
125
     * @throws \InvalidArgumentException
126
     */
127
    public function getArgument($name): Argument
128
    {
129
        if (!$this->hasArgument($name)) {
130
            throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
131
        }
132
133
        $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
134
135
        return $arguments[$name];
136
    }
137
138
    /**
139
     * 根据名称或位置检查是否具有某个参数
140
     * @param string|int $name 参数名或者位置
141
     * @return bool
142
     * @api
143
     */
144
    public function hasArgument($name): bool
145
    {
146
        $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
147
148
        return isset($arguments[$name]);
149
    }
150
151
    /**
152
     * 获取所有的参数
153
     * @return Argument[] 参数数组
154
     */
155
    public function getArguments(): array
156
    {
157
        return $this->arguments;
158
    }
159
160
    /**
161
     * 获取参数数量
162
     * @return int
163
     */
164
    public function getArgumentCount(): int
165
    {
166
        return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
167
    }
168
169
    /**
170
     * 获取必填的参数的数量
171
     * @return int
172
     */
173
    public function getArgumentRequiredCount(): int
174
    {
175
        return $this->requiredCount;
176
    }
177
178
    /**
179
     * 获取参数默认值
180
     * @return array
181
     */
182
    public function getArgumentDefaults(): array
183
    {
184
        $values = [];
185
        foreach ($this->arguments as $argument) {
186
            $values[$argument->getName()] = $argument->getDefault();
187
        }
188
189
        return $values;
190
    }
191
192
    /**
193
     * 设置选项
194
     * @param Option[] $options 选项数组
195
     */
196
    public function setOptions(array $options = []): void
197
    {
198
        $this->options   = [];
199
        $this->shortcuts = [];
200
        $this->addOptions($options);
201
    }
202
203
    /**
204
     * 添加选项
205
     * @param Option[] $options 选项数组
206
     * @api
207
     */
208
    public function addOptions(array $options = []): void
209
    {
210
        foreach ($options as $option) {
211
            $this->addOption($option);
212
        }
213
    }
214
215
    /**
216
     * 添加一个选项
217
     * @param Option $option 选项
218
     * @throws \LogicException
219
     * @api
220
     */
221
    public function addOption(Option $option): void
222
    {
223
        if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
224
            throw new \LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
225
        }
226
227
        if ($option->getShortcut()) {
228
            foreach (explode('|', $option->getShortcut()) as $shortcut) {
229
                if (isset($this->shortcuts[$shortcut])
230
                    && !$option->equals($this->options[$this->shortcuts[$shortcut]])
231
                ) {
232
                    throw new \LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
233
                }
234
            }
235
        }
236
237
        $this->options[$option->getName()] = $option;
238
        if ($option->getShortcut()) {
239
            foreach (explode('|', $option->getShortcut()) as $shortcut) {
240
                $this->shortcuts[$shortcut] = $option->getName();
241
            }
242
        }
243
    }
244
245
    /**
246
     * 根据名称获取选项
247
     * @param string $name 选项名
248
     * @return Option
249
     * @throws \InvalidArgumentException
250
     * @api
251
     */
252
    public function getOption(string $name): Option
253
    {
254
        if (!$this->hasOption($name)) {
255
            throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
256
        }
257
258
        return $this->options[$name];
259
    }
260
261
    /**
262
     * 根据名称检查是否有这个选项
263
     * @param string $name 选项名
264
     * @return bool
265
     * @api
266
     */
267
    public function hasOption(string $name): bool
268
    {
269
        return isset($this->options[$name]);
270
    }
271
272
    /**
273
     * 获取所有选项
274
     * @return Option[]
275
     * @api
276
     */
277
    public function getOptions(): array
278
    {
279
        return $this->options;
280
    }
281
282
    /**
283
     * 根据名称检查某个选项是否有短名称
284
     * @param string $name 短名称
285
     * @return bool
286
     */
287
    public function hasShortcut(string $name): bool
288
    {
289
        return isset($this->shortcuts[$name]);
290
    }
291
292
    /**
293
     * 根据短名称获取选项
294
     * @param string $shortcut 短名称
295
     * @return Option
296
     */
297
    public function getOptionForShortcut(string $shortcut): Option
298
    {
299
        return $this->getOption($this->shortcutToName($shortcut));
300
    }
301
302
    /**
303
     * 获取所有选项的默认值
304
     * @return array
305
     */
306
    public function getOptionDefaults(): array
307
    {
308
        $values = [];
309
        foreach ($this->options as $option) {
310
            $values[$option->getName()] = $option->getDefault();
311
        }
312
313
        return $values;
314
    }
315
316
    /**
317
     * 根据短名称获取选项名
318
     * @param string $shortcut 短名称
319
     * @return string
320
     * @throws \InvalidArgumentException
321
     */
322
    private function shortcutToName(string $shortcut): string
323
    {
324
        if (!isset($this->shortcuts[$shortcut])) {
325
            throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
326
        }
327
328
        return $this->shortcuts[$shortcut];
329
    }
330
331
    /**
332
     * 获取该指令的介绍
333
     * @param bool $short 是否简洁介绍
334
     * @return string
335
     */
336
    public function getSynopsis(bool $short = false): string
337
    {
338
        $elements = [];
339
340
        if ($short && $this->getOptions()) {
341
            $elements[] = '[options]';
342
        } elseif (!$short) {
343
            foreach ($this->getOptions() as $option) {
344
                $value = '';
345
                if ($option->acceptValue()) {
346
                    $value = sprintf(' %s%s%s', $option->isValueOptional() ? '[' : '', strtoupper($option->getName()), $option->isValueOptional() ? ']' : '');
347
                }
348
349
                $shortcut   = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
350
                $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
351
            }
352
        }
353
354
        if (count($elements) && $this->getArguments()) {
355
            $elements[] = '[--]';
356
        }
357
358
        foreach ($this->getArguments() as $argument) {
359
            $element = '<' . $argument->getName() . '>';
360
            if (!$argument->isRequired()) {
361
                $element = '[' . $element . ']';
362
            } elseif ($argument->isArray()) {
363
                $element .= ' (' . $element . ')';
364
            }
365
366
            if ($argument->isArray()) {
367
                $element .= '...';
368
            }
369
370
            $elements[] = $element;
371
        }
372
373
        return implode(' ', $elements);
374
    }
375
}
376