Passed
Push — nln-php7 ( 12eaac )
by Nicolas
05:28
created

GroupParser::processGroupDefinition()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

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