Test Failed
Push — master ( 73c405...d57cd2 )
by Konstantins
03:14
created

SignatureParser::parseParameters()   D

Complexity

Conditions 9
Paths 18

Size

Total Lines 34
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 9.0101

Importance

Changes 0
Metric Value
dl 0
loc 34
ccs 19
cts 20
cp 0.95
rs 4.909
c 0
b 0
f 0
cc 9
eloc 22
nc 18
nop 0
crap 9.0101
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 2
    public function parse(string $signature): array
42
    {
43 2
        $signature = explode(' ', $this->signature = $signature);
44
45 2
        return array_merge($this->parseParameters(), [
46 2
            '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 2
    private function defineType($array = false, $optional = false): int
58
    {
59 2
        $type = ($optional) ? InputArgument::OPTIONAL : InputArgument::REQUIRED;
60
61 2
        if ($array) {
62
            $type = InputArgument::IS_ARRAY | $type;
63
        }
64
65 2
        return $type;
66
    }
67
68
    /**
69
     * Returns array of parameters matches
70
     *
71
     * @return array
72
     */
73 2
    private function getParameters(): array
74
    {
75 2
        $matches = [];
76 2
        preg_match_all($this->parametersMatcher, $this->signature, $matches);
77
78 2
        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 2
    private function parseParameters(): array
88
    {
89 2
        $arguments = [];
90 2
        $options = [];
91 2
        $signatureArguments = $this->getParameters();
92
93 2
        foreach ($signatureArguments as $value) {
94 2
            $item = [];
95 2
            $matches = [];
96 2
            $exploded = explode(':', $value);
97
98 2
            if (count($exploded) > 0 && preg_match($this->argumentsMatcher, $exploded[0], $matches)) {
99 2
                $item['name'] = $matches[1];
100 2
                $item['type'] = $this->defineType($matches[2] === '[]', $matches[3] === '=');
101 2
                $item['default'] = $matches[4] !== '' ? $matches[4] : null;
102 2
                $item['description'] = count($exploded) === 2 ? $exploded[1] : null;
103
104 2
                if ($matches[2] === '[]' && $item['default'] !== null) {
105
                    $item['default'] = explode(',', $item['default']);
106
                }
107
108 2
                if (substr($exploded[0], 0, 2) === '--') {
109 2
                    $options[] = $item;
110
                } else {
111 2
                    $arguments[] = $item;
112
                }
113
            }
114
        }
115
116
        return [
117 2
            'arguments' => $arguments,
118 2
            'options' => $options,
119
        ];
120
    }
121
}