DependencyRuleFactory::verifyDefinition()   B
last analyzed

Complexity

Conditions 8
Paths 5

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 7
nc 5
nop 1
dl 0
loc 9
rs 8.4444
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace DependencyAnalyzer\Inspector\RuleViolationDetector;
5
6
use DependencyAnalyzer\Exceptions\InvalidRuleDefinition;
7
use DependencyAnalyzer\DependencyGraph\StructuralElementPatternMatcher;
8
9
class DependencyRuleFactory
10
{
11
    /**
12
     * @param array $ruleDefinitions
13
     * @return DependencyRule[]
14
     */
15
    public function create(array $ruleDefinitions): array
16
    {
17
        $rules = [];
18
        foreach ($ruleDefinitions as $ruleName => $ruleDefinition) {
19
            $this->verifyDefinition($ruleDefinition);
20
            if (is_int($ruleName)) {
21
                $ruleName = (string)$ruleName;
22
            }
23
            $rules[] = $this->createDependencyRule($ruleName, $ruleDefinition);
24
        }
25
26
        return $rules;
27
    }
28
29
    protected function createDependencyRule(string $ruleName, array $ruleDefinition)
30
    {
31
        $componentDefines = [];
32
        foreach ($ruleDefinition as $componentName => $componentDefinition) {
33
            $componentDefines[$componentName] = $componentDefinition['define'];
34
        }
35
36
        $components = [];
37
        foreach ($ruleDefinition as $componentName => $componentDefinition) {
38
            $depender = isset($componentDefinition['depender']) ? $this->createMatcher($componentDefinition['depender'], $componentDefines) : null;
39
            $dependee = isset($componentDefinition['dependee']) ? $this->createMatcher($componentDefinition['dependee'], $componentDefines) : null;
40
            $public = isset($componentDefinition['public']) ? $this->createMatcher($componentDefinition['public'], $componentDefines) : null;
41
            $extras = [];
42
            if (isset($componentDefinition['extra'])) {
43
                foreach ($componentDefinition['extra'] as $callee => $callerPattern) {
44
                    $extras[$callee] = $this->createMatcher($callerPattern, $componentDefines);
45
                }
46
            }
47
            $components[] = new Component(
48
                $componentName,
49
                new StructuralElementPatternMatcher($componentDefinition['define']),
50
                $depender,
51
                $dependee,
52
                $public,
53
                $extras
54
            );
55
        }
56
        return new DependencyRule($ruleName, $components);
57
    }
58
59
    protected function createMatcher(array $dependPatterns, array $componentDefines): StructuralElementPatternMatcher
60
    {
61
        $patterns = [];
62
        $excludePatterns = [];
63
        foreach ($dependPatterns as $dependPattern) {
64
            if (preg_match('/^\![^\\\@]/', $dependPattern) === 1 && isset($componentDefines[substr($dependPattern, 1)])) {
65
                // ex: '!component_name' -> ['\Component\Define']
66
                $excludePatterns = array_merge($excludePatterns, $componentDefines[substr($dependPattern, 1)]);
67
            } elseif (preg_match('/^[^\\\@]/', $dependPattern) === 1 && isset($componentDefines[$dependPattern])) {
68
                // ex: 'component_name' -> ['\Component\Define']
69
                $patterns = array_merge($patterns, $componentDefines[$dependPattern]);
70
            } else {
71
                $patterns[] = $dependPattern;
72
            }
73
        }
74
75
        // TODO: fix it...
76
        return (new StructuralElementPatternMatcher($patterns))->addExcludePatterns($excludePatterns);
77
    }
78
79
    protected function verifyDefinition(array $ruleDefinition): void
80
    {
81
        foreach ($ruleDefinition as $componentName => $componentDefinition) {
82
            if (!isset($componentDefinition['define']) || !is_array($componentDefinition['define'])) {
83
                throw new InvalidRuleDefinition($ruleDefinition, "component must have 'define'. Invalid your component: {$componentName}");
84
            } elseif (isset($componentDefinition['depender']) && !is_array($componentDefinition['depender'])) {
85
                throw new InvalidRuleDefinition($ruleDefinition, "depenee must be array. Invalid your component: {$componentName}");
86
            } elseif (isset($componentDefinition['dependee']) && !is_array($componentDefinition['dependee'])) {
87
                throw new InvalidRuleDefinition($ruleDefinition, "depenee must be array. Invalid your component: {$componentName}");
88
            }
89
        }
90
    }
91
}
92