Passed
Push — master ( 176455...e166a4 )
by Satoshi
02:24
created

QualifiedNamePattern::classNameBelongToPattern()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 12
nc 6
nop 2
dl 0
loc 24
rs 8.8333
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace DependencyAnalyzer\Patterns;
5
6
use DependencyAnalyzer\Exceptions\InvalidQualifiedNamePatternException;
7
8
class QualifiedNamePattern
9
{
10
    const PHP_NATIVE_CLASSES = '@php_native';
11
    protected static $nativeClasses = [];
12
13
    protected $patterns = [];
14
    protected $excludePatterns = [];
15
16
    public function __construct(array $patterns)
17
    {
18
        foreach ($patterns as $pattern) {
19
            if (!$this->verifyPattern($pattern)) {
20
                throw new InvalidQualifiedNamePatternException($pattern);
21
            }
22
23
            $this->addPattern($pattern);
24
        }
25
    }
26
27
    protected function verifyPattern(string $pattern)
28
    {
29
        return (
30
            preg_match('/^!?' . preg_quote('\\', '/') . '(.*)$/', $pattern, $matches) === 1 ||
31
            $this->isMagicWordPattern($pattern)
32
        );
33
    }
34
35
    protected function addPattern(string $pattern)
36
    {
37
        if ($this->isExcludePattern($pattern)) {
38
            $this->excludePatterns[] = $this->isMagicWordPattern($pattern) ? substr($pattern, 1) : rtrim(substr($pattern, 2), '\\');
39
        } else {
40
            $this->patterns[] = $this->isMagicWordPattern($pattern) ? $pattern : rtrim(substr($pattern, 1), '\\');
41
        }
42
    }
43
44
    protected function isExcludePattern(string $pattern)
45
    {
46
        return preg_match('/^!/', $pattern) === 1;
47
    }
48
49
    protected function isMagicWordPattern(string $pattern)
50
    {
51
        return in_array($pattern, [
52
            self::PHP_NATIVE_CLASSES,
53
            '!' . self::PHP_NATIVE_CLASSES,
54
        ]);
55
    }
56
57
    public function isMatch(string $className)
58
    {
59
        foreach ($this->excludePatterns as $excludePattern) {
60
            if ($this->classNameBelongToPattern($className, $excludePattern)) {
61
                return false;
62
            }
63
        }
64
65
        if (count($this->patterns) === 0) {
66
            return true;
67
        } else {
68
            foreach ($this->patterns as $pattern) {
69
                if ($this->classNameBelongToPattern($className, $pattern)) {
70
                    return true;
71
                }
72
            }
73
        }
74
75
        return false;
76
    }
77
78
    protected function classNameBelongToPattern(string $className, string $pattern)
79
    {
80
        if ($this->isMagicWordPattern($pattern)) {
81
            return in_array($className, self::$nativeClasses);
82
        }
83
84
        $separatedClassName = $this->explodeName($className);
85
        $separatedPattern = $this->explodeName($pattern);
86
87
        if (count($separatedPattern) === 1 && $separatedPattern[0] === '') {
88
            // Pattern likely '\\' will match with all className.
89
            return true;
90
        }
91
        if (count($separatedClassName) < count($separatedPattern)) {
92
            return false;
93
        }
94
95
        foreach ($separatedPattern as $index => $pattern) {
96
            if ($separatedClassName[$index] !== $pattern) {
97
                return false;
98
            }
99
        }
100
101
        return true;
102
    }
103
104
    protected function explodeName(string $qualifiedName)
105
    {
106
        return explode('\\', $qualifiedName);
107
    }
108
109
    public static function setPhpNativeClasses(array $nativeClasses)
110
    {
111
        self::$nativeClasses = $nativeClasses;
112
    }
113
}
114