Completed
Push — master ( 23bc19...2eec4d )
by Tomáš
11:42
created

RulesetBuilder::buildFromRulesetXml()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 33
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 3.0013

Importance

Changes 0
Metric Value
dl 0
loc 33
ccs 18
cts 19
cp 0.9474
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 19
nc 3
nop 1
crap 3.0013
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\Extractor\CustomPropertyValuesExtractor;
12
use Symplify\PHP7_CodeSniffer\Ruleset\Rule\ReferenceNormalizer;
13
use Symplify\PHP7_CodeSniffer\Sniff\Finder\SniffFinder;
14
use Symplify\PHP7_CodeSniffer\Standard\Finder\StandardFinder;
15
16
final class RulesetBuilder
17
{
18
    /**
19
     * @var SniffFinder
20
     */
21
    private $sniffFinder;
22
23
    /**
24
     * @var ReferenceNormalizer
25
     */
26
    private $ruleReferenceNormalizer;
27
28
    /**
29
     * @var array
30
     */
31
    private $ruleset = [];
32
33
    /**
34
     * @var StandardFinder
35
     */
36
    private $standardFinder;
37
38
    /**
39
     * @var CustomPropertyValuesExtractor
40
     */
41
    private $customPropertyValuesExtractor;
42
43 8
    public function __construct(
44
        SniffFinder $sniffFinder,
45
        StandardFinder $standardFinder,
46
        ReferenceNormalizer $ruleReferenceNormalizer,
47
        CustomPropertyValuesExtractor $customPropertyValuesExtractor
48
    ) {
49 8
        $this->sniffFinder = $sniffFinder;
50 8
        $this->standardFinder = $standardFinder;
51 8
        $this->ruleReferenceNormalizer = $ruleReferenceNormalizer;
52 8
        $this->customPropertyValuesExtractor = $customPropertyValuesExtractor;
53 8
    }
54
55 5
    public function buildFromRulesetXml(string $rulesetXmlFile) : array
56
    {
57 5
        $rulesetXml = simplexml_load_file($rulesetXmlFile);
58
59 5
        $includedSniffs = [];
60 5
        $excludedSniffs = [];
61
62 5
        $this->ruleset = array_merge(
63 5
            $this->ruleset,
64 5
            $this->customPropertyValuesExtractor->extractFromRulesetXmlFile($rulesetXmlFile)
65
        );
66
67 5
        foreach ($rulesetXml->rule as $rule) {
68 5
            if (!isset($rule['ref'])) {
69
                continue;
70
            }
71
72 5
            $expandedSniffs = $this->normalizeReference($rule['ref']);
73 5
            $includedSniffs = array_merge($includedSniffs, $expandedSniffs);
74 5
            $excludedSniffs = $this->processExcludedRules($excludedSniffs, $rule);
75
        }
76
77 5
        $ownSniffs = $this->getOwnSniffsFromRuleset($rulesetXmlFile);
78 5
        $includedSniffs = array_unique(array_merge($ownSniffs, $includedSniffs));
79 5
        $excludedSniffs = array_unique($excludedSniffs);
80
81 5
        $sniffs = $this->filterOutExcludedSniffs($includedSniffs, $excludedSniffs);
82 5
        $sniffs = $this->sortSniffs($sniffs);
83
84
        // todo: decorate with custom rules!
85
86 5
        return $sniffs;
87
    }
88
89 1
    public function getRuleset() : array
90
    {
91 1
        return $this->ruleset;
92
    }
93
94 5
    private function normalizeReference(string $reference)
95
    {
96 5
        if ($this->ruleReferenceNormalizer->isRulesetReference($reference)) {
97
            return $this->buildFromRulesetXml($reference);
98
        }
99
100 5
        if ($this->ruleReferenceNormalizer->isStandardReference($reference)) {
101 5
            $ruleset = $this->standardFinder->getRulesetPathForStandardName($reference);
102 5
            return $this->buildFromRulesetXml($ruleset);
103
        }
104
105 5
        return $this->ruleReferenceNormalizer->normalize($reference);
106
    }
107
108
    /**
109
     * @return string[]
110
     */
111 5
    private function getOwnSniffsFromRuleset(string $rulesetXml) : array
112
    {
113 5
        $rulesetDir = dirname($rulesetXml);
114 5
        $sniffDir = $rulesetDir.DIRECTORY_SEPARATOR.'Sniffs';
115 5
        if (is_dir($sniffDir)) {
116 5
            return $this->sniffFinder->findAllSniffClassesInDirectory($sniffDir);
117
        }
118
119 2
        return [];
120
    }
121
122 5
    private function processExcludedRules($excludedSniffs, SimpleXMLElement $rule) : array
123
    {
124 5
        if (isset($rule->exclude)) {
125
            foreach ($rule->exclude as $exclude) {
126
                $excludedSniffs = array_merge(
127
                    $excludedSniffs,
128
                    $this->normalizeReference($exclude['name'])
129
                );
130
            }
131
        }
132
133 5
        return $excludedSniffs;
134
    }
135
136 5
    private function filterOutExcludedSniffs(array $includedSniffs, array $excludedSniffs) : array
137
    {
138 5
        $sniffs = [];
139 5
        foreach ($includedSniffs as $sniffCode => $sniffClass) {
140 5
            if (!in_array($sniffCode, $excludedSniffs)) {
141 5
                $sniffs[$sniffCode] = $sniffClass;
142
            }
143
        }
144
145 5
        return $sniffs;
146
    }
147
148 5
    private function sortSniffs(array $sniffs) : array
149
    {
150 5
        ksort($sniffs);
151 5
        return $sniffs;
152
    }
153
}
154