Completed
Push — nln-php7 ( 12eaac...5c4f20 )
by Nicolas
05:37
created

GroupParser::checkForDefaultMarker()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 16
cts 16
cp 1
rs 9.424
c 0
b 0
f 0
cc 4
nc 4
nop 2
crap 4
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Karma\Configuration\Parser;
6
7
class GroupParser extends AbstractSectionParser
8
{
9
    private
10
        $groups,
0 ignored issues
show
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
11
        $defaultEnvironments;
12
13 269
    public function __construct()
14
    {
15 269
        parent::__construct();
16
17 269
        $this->groups = [];
18 269
        $this->defaultEnvironments = [];
19 269
    }
20
21 23
    protected function parseLine(string $line): void
22
    {
23 23
        if($this->isACommentLine($line))
24
        {
25 2
            return;
26
        }
27
28 23
        $line = trim($line);
29
30 23
        if(preg_match('~(?P<groupName>[^=]+)\s*=\s*\[(?P<envList>[^\[\]]+)\]$~', $line, $matches))
31
        {
32 15
            $this->processGroupDefinition($matches['groupName'], $matches['envList']);
33
34 10
            return;
35
        }
36
37 8
        $this->triggerError($line);
38
    }
39
40 15
    private function processGroupDefinition(string $groupName, string $envList): void
41
    {
42 15
        $groupName = trim($groupName);
43
44 15
        $this->checkGroupStillNotExists($groupName);
45
46 15
        $environments = array_map('trim', explode(',', $envList));
47 15
        $environments = $this->checkForDefaultMarker($groupName, $environments);
48 14
        $this->checkEnvironmentAreUnique($groupName, $environments);
49
50 13
        $this->groups[$groupName] = array();
51
52 13
        foreach($environments as $env)
53
        {
54 13
            if(empty($env))
55
            {
56 3
                $this->triggerError("empty environment in declaration of group $groupName");
57
            }
58
59 12
            $this->groups[$groupName][] = $env;
60
        }
61 10
    }
62
63 15
    private function checkForDefaultMarker(string $groupName, array $environments): array
64
    {
65 15
        $environmentNames = [];
66 15
        $this->defaultEnvironments[$groupName] = null;
67
68 15
        foreach($environments as $envString)
69
        {
70 15
            $name = $envString;
71
72 15
            if(preg_match('~\*\s*(?P<envName>.*)~', $envString, $matches))
73
            {
74 3
                $name = $matches['envName'];
75
76 3
                if(isset($this->defaultEnvironments[$groupName]))
77
                {
78 1
                    throw new \RuntimeException(sprintf(
79 1
                        'Group %s must have only one default environment : %s and %s are declared as default',
80 1
                        $groupName,
81 1
                        $this->defaultEnvironments[$groupName],
82 1
                        $name
83
                    ));
84
                }
85
86 3
                $this->defaultEnvironments[$groupName] = $name;
87
            }
88
89 15
            $environmentNames[] = $name;
90
        }
91
92 14
        return $environmentNames;
93
    }
94
95 15
    private function checkGroupStillNotExists(string $groupName): void
96
    {
97 15
        if(isset($this->groups[$groupName]))
98
        {
99 1
            $this->triggerError("group $groupName has already been declared");
100
        }
101 15
    }
102
103 14
    private function checkEnvironmentAreUnique(string $groupName, array $environments): void
104
    {
105 14
        if($this->hasDuplicatedValues($environments))
106
        {
107 1
            $this->triggerError("duplicated environment in group $groupName");
108
        }
109 13
    }
110
111 240
    private function hasDuplicatedValues(array $values): bool
112
    {
113
        $duplicatedValues = array_filter(array_count_values($values), function ($counter) {
114 14
            return $counter !== 1;
115 240
        });
116
117 240
        return empty($duplicatedValues) === false;
118
    }
119
120 38
    public function getCollectedGroups(): array
121
    {
122 38
        return $this->groups;
123
    }
124
125 235
    public function postParse(): void
126
    {
127 235
        $this->checkEnvironmentsBelongToOnlyOneGroup();
128 234
        $this->checkGroupsAreNotPartsOfAnotherGroups();
129 233
    }
130
131 235
    private function checkEnvironmentsBelongToOnlyOneGroup(): void
132
    {
133 235
        $allEnvironments = $this->getAllEnvironmentsBelongingToGroups();
134
135 235
        if($this->hasDuplicatedValues($allEnvironments))
136
        {
137 1
            throw new \RuntimeException('Error : some environments are in various groups');
138
        }
139 234
    }
140
141 235
    private function getAllEnvironmentsBelongingToGroups(): array
142
    {
143 235
        $allEnvironments = [];
144
145 235
        foreach($this->groups as $group)
146
        {
147 9
            $allEnvironments = array_merge($allEnvironments, $group);
148
        }
149
150 235
        return $allEnvironments;
151
    }
152
153 234
    private function checkGroupsAreNotPartsOfAnotherGroups(): void
154
    {
155 234
        $allEnvironments = $this->getAllEnvironmentsBelongingToGroups();
156
157 234
        $errors = array_intersect($allEnvironments, array_keys($this->groups));
158
159 234
        if(! empty($errors))
160
        {
161 1
            throw new \RuntimeException(sprintf(
162 1
               'Error : a group can not be part of another group (%s)',
163 1
                implode(', ', $errors)
164
            ));
165
        }
166 233
    }
167
168 33
    public function getDefaultEnvironmentsForGroups(): array
169
    {
170 33
        return $this->defaultEnvironments;
171
    }
172
}
173