Completed
Branch master (c5ceed)
by Tomáš
33:54 queued 13:17
created

RulesetBuilder::processRule()   C

Complexity

Conditions 12
Paths 7

Size

Total Lines 55
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 55
ccs 17
cts 34
cp 0.5
rs 6.8009
c 0
b 0
f 0
cc 12
eloc 35
nc 7
nop 2
crap 30

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of Symplify
5
 * Copyright (c) 2016 Tomas Votruba (http://tomasvotruba.cz).
6
 */
7
8
namespace Symplify\PHP7_CodeSniffer\Ruleset;
9
10
use SimpleXMLElement;
11
use Symplify\PHP7_CodeSniffer\Ruleset\Rule\ReferenceNormalizer;
12
use Symplify\PHP7_CodeSniffer\SniffFinder\SniffFinder;
13
use Symplify\PHP7_CodeSniffer\Standard\StandardFinder;
14
15
final class RulesetBuilder
16
{
17
    /**
18
     * @var SniffFinder
19
     */
20
    private $sniffFinder;
21
22
    /**
23
     * @var ReferenceNormalizer
24
     */
25
    private $ruleReferenceNormalizer;
26
27
    /**
28
     * @var array
29
     */
30
    private $ruleset = [];
31
32
    /**
33
     * @var array
34
     */
35
    private $includedSniffs = [];
36
37
    /**
38
     * @var array
39
     */
40
    private $excludedSniffs = [];
41
42
    /**
43
     * @var StandardFinder
44
     */
45
    private $standardFinder;
46
47 1
    public function __construct(
48
        SniffFinder $sniffFinder,
49
        StandardFinder $standardFinder,
50
        ReferenceNormalizer $ruleReferenceNormalizer
51
    ) {
52 1
        $this->sniffFinder = $sniffFinder;
53 1
        $this->standardFinder = $standardFinder;
54 1
        $this->ruleReferenceNormalizer = $ruleReferenceNormalizer;
55 1
    }
56
57 1
    public function buildFromRulesetXml(string $rulesetXmlFile) : array
58
    {
59 1
        $this->cleanCache();
60
61 1
        $rulesetXml = simplexml_load_file($rulesetXmlFile);
62 1
        foreach ($rulesetXml->rule as $rule) {
63 1
            if (isset($rule['ref']) === false) {
64
                continue;
65
            }
66
67 1
            $expandedSniffs = $this->normalizeReference($rule['ref']);
68 1
            $newSniffs = array_diff($expandedSniffs, $this->includedSniffs);
69
70 1
            $this->includedSniffs = array_merge($this->includedSniffs, $expandedSniffs);
71
72 1
            $this->processExcludedRules($rule);
73
74 1
            $this->processRule($rule, $newSniffs);
75
        }
76
77 1
        $ownSniffs = $this->getOwnSniffsFromRuleset($rulesetXmlFile);
78
79 1
        $this->includedSniffs = array_unique(array_merge($ownSniffs, $this->includedSniffs));
80 1
        $this->excludedSniffs = array_unique($this->excludedSniffs);
81
82 1
        return $this->filterOutExcludedSniffs();
83
    }
84
85
    public function getRuleset() : array
86
    {
87
        return $this->ruleset;
88
    }
89
90
    /**
91
     * Processes a rule from a ruleset XML file, overriding built-in defaults.
92
     */
93 1
    private function processRule(SimpleXMLElement $rule, array $newSniffs)
94
    {
95 1
        $ref  = (string) $rule['ref'];
96 1
        $todo = [$ref];
97
98 1
        $parts = explode('.', $ref);
99 1
        if (count($parts) <= 2) {
100
            // We are processing a standard or a category of sniffs.
101 1
            foreach ($newSniffs as $sniffFile) {
102
                $parts = explode(DIRECTORY_SEPARATOR, $sniffFile);
103
                $sniffName = array_pop($parts);
104
                $sniffCategory = array_pop($parts);
105
                array_pop($parts);
106
                $sniffStandard = array_pop($parts);
107
                $todo[] = $sniffStandard.'.'.$sniffCategory.'.'.substr($sniffName, 0, -9);
108
            }
109
        }
110
111 1
        foreach ($todo as $code) {
112
            // Custom properties.
113 1
            if (isset($rule->properties) === true) {
114 1
                foreach ($rule->properties->property as $prop) {
115 1
                    if (isset($this->ruleset[$code]) === false) {
116 1
                        $this->ruleset[$code] = [
117 1
                            'properties' => [],
118
                        ];
119
                    } else if (isset($this->ruleset[$code]['properties']) === false) {
120
                        $this->ruleset[$code]['properties'] = [];
121
                    }
122
123 1
                    $name = (string) $prop['name'];
124 1
                    if (isset($prop['type']) === true
125 1
                        && (string) $prop['type'] === 'array'
126
                    ) {
127
                        $value  = (string) $prop['value'];
128
                        $values = [];
129
                        foreach (explode(',', $value) as $val) {
130
                            $v = '';
131
132
                            list($k,$v) = explode('=>', $val.'=>');
133
                            if ($v !== '') {
134
                                $values[$k] = $v;
135
                            } else {
136
                                $values[] = $k;
137
                            }
138
                        }
139
140
                        $this->ruleset[$code]['properties'][$name] = $values;
141
                    } else {
142 1
                        $this->ruleset[$code]['properties'][$name] = (string) $prop['value'];
143
                    }
144
                }
145
            }
146
        }
147 1
    }
148
    
149 1
    private function normalizeReference(string $reference)
150
    {
151 1
        if ($this->ruleReferenceNormalizer->isRulesetReference($reference)) {
152
            return $this->buildFromRulesetXml($reference);
153
        }
154
155 1
        if ($this->ruleReferenceNormalizer->isStandardReference($reference)) {
156 1
            $ruleset = $this->standardFinder->getRulesetPathForStandardName($reference);
157 1
            return $this->buildFromRulesetXml($ruleset);
158
        }
159
160 1
        return $this->ruleReferenceNormalizer->normalize($reference);
161
    }
162
163 1
    private function cleanCache()
164
    {
165 1
        $this->includedSniffs = [];
166 1
        $this->excludedSniffs = [];
167 1
    }
168
169
    /**
170
     * @return string[]
171
     */
172 1
    private function getOwnSniffsFromRuleset(string $rulesetXml) : array
173
    {
174 1
        $rulesetDir = dirname($rulesetXml);
175 1
        $sniffDir = $rulesetDir.DIRECTORY_SEPARATOR.'Sniffs';
176 1
        if (is_dir($sniffDir)) {
177 1
            return $this->sniffFinder->findAllSniffClassesInDirectory($sniffDir);
178
        }
179
180 1
        return [];
181
    }
182
183 1
    private function processExcludedRules(SimpleXMLElement $rule)
184
    {
185 1
        if (isset($rule->exclude) === true) {
186
            foreach ($rule->exclude as $exclude) {
187
                $this->excludedSniffs = array_merge(
188
                    $this->excludedSniffs,
189
                    $this->normalizeReference($exclude['name'])
190
                );
191
            }
192
        }
193 1
    }
194
195 1
    private function filterOutExcludedSniffs() : array
196
    {
197 1
        $sniffs = [];
198 1
        foreach ($this->includedSniffs as $sniffCode => $sniffClass) {
199 1
            if (!in_array($sniffCode, $this->excludedSniffs)) {
200 1
                $sniffs[$sniffCode] = $sniffClass;
201
            }
202
        }
203
204 1
        return $sniffs;
205
    }
206
}
207