Passed
Push — master ( 2c1367...72194f )
by Alexey
03:21
created

SignatureParser::parseParameters()   D

Complexity

Conditions 9
Paths 18

Size

Total Lines 34
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 9

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 34
rs 4.909
ccs 20
cts 20
cp 1
cc 9
eloc 22
nc 18
nop 0
crap 9
1
<?php declare(strict_types = 1);
2
3
namespace Venta\Console\Command;
4
5
use Symfony\Component\Console\Input\InputArgument;
6
use Venta\Contracts\Console\SignatureParser as SignatureParserContract;
7
8
/**
9
 * Class SignatureParser
10
 *
11
 * @package Venta\Console
12
 */
13
final class SignatureParser implements SignatureParserContract
14
{
15
    /**
16
     * RegExp to match arguments.
17
     * name[]?:description
18
     *
19
     * @var string
20
     */
21
    private $argumentsMatcher = '/^(?:\-\-)?([a-z]+)?(\[\])?(=)?(.*?)?$/';
22
23
    /**
24
     * Parameters matcher string.
25
     *
26
     * @var string
27
     */
28
    private $parametersMatcher = '/{(.*?)}/';
29
30
    /**
31
     * Full signature string holder.
32
     *
33
     * @var string
34
     */
35
    private $signature;
36
37
    /**
38
     * @throws \Exception
39
     * {@inheritdoc}
40
     */
41 12
    public function parse(string $signature): array
42
    {
43 12
        $signature = explode(' ', $this->signature = $signature);
44
45 12
        return array_merge($this->parseParameters(), [
46 12
            'name' => array_shift($signature),
47
        ]);
48
    }
49
50
    /**
51
     * Defines type of an argument or option based on options
52
     *
53
     * @param bool $array
54
     * @param bool $optional
55
     * @return int
56
     */
57 10
    private function defineType($array = false, $optional = false): int
58
    {
59 10
        $type = ($optional) ? InputArgument::OPTIONAL : InputArgument::REQUIRED;
60
61 10
        if ($array) {
62 5
            $type = InputArgument::IS_ARRAY | $type;
63
        }
64
65 10
        return $type;
66
    }
67
68
    /**
69
     * Returns array of parameters matches
70
     *
71
     * @return array
72
     */
73 12
    private function getParameters(): array
74
    {
75 12
        $matches = [];
76 12
        preg_match_all($this->parametersMatcher, $this->signature, $matches);
77
78 12
        return $matches[1];
79
    }
80
81
    /**
82
     * Parses arguments and options from signature string,
83
     * returns an array with definitions
84
     *
85
     * @return array
86
     */
87 12
    private function parseParameters(): array
88
    {
89 12
        $arguments = [];
90 12
        $options = [];
91 12
        $signatureArguments = $this->getParameters();
92
93 12
        foreach ($signatureArguments as $value) {
94 10
            $item = [];
95 10
            $matches = [];
96 10
            $exploded = explode(':', $value);
97
98 10
            if (count($exploded) > 0 && preg_match($this->argumentsMatcher, $exploded[0], $matches)) {
99 10
                $item['name'] = $matches[1];
100 10
                $item['type'] = $this->defineType($matches[2] === '[]', $matches[3] === '=');
101 10
                $item['default'] = $matches[4] !== '' ? $matches[4] : null;
102 10
                $item['description'] = count($exploded) === 2 ? $exploded[1] : null;
103
104 10
                if ($matches[2] === '[]' && $item['default'] !== null) {
105 3
                    $item['default'] = explode(',', $item['default']);
106
                }
107
108 10
                if (substr($exploded[0], 0, 2) === '--') {
109 3
                    $options[] = $item;
110
                } else {
111 10
                    $arguments[] = $item;
112
                }
113
            }
114
        }
115
116
        return [
117 12
            'arguments' => $arguments,
118 12
            'options' => $options,
119
        ];
120
    }
121
}