Passed
Pull Request — master (#22)
by Sergei
13:31
created

PathMatcher::callback()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Files\PathMatch;
6
7
final class PathMatcher implements PathMatcherInterface
8
{
9
    /**
10
     * @var PathPattern[]|null
11
     */
12
    private ?array $only = null;
13
14
    /**
15
     * @var PathPattern[]|null
16
     */
17
    private ?array $except = null;
18
19
    /**
20
     * @var PathPattern[]|null
21
     */
22
    private ?array $callbacks = null;
23
24
    private bool $caseSensitive = false;
25
    private bool $matchFullPath = false;
26
    private bool $matchSlashesExactly = true;
27
28
    /**
29
     * Make string patterns case sensitive.
30
     * @return self
31
     */
32
    public function caseSensitive(): self
33
    {
34
        $new = clone $this;
35
        $new->caseSensitive = true;
36
        return $new;
37
    }
38
39
    /**
40
     * Match string patterns as full path, not just ending of path.
41
     * @return self
42
     */
43
    public function withFullPath(): self
44
    {
45
        $new = clone $this;
46
        $new->matchFullPath = true;
47
        return $new;
48
    }
49
50
    /**
51
     * Match `/` character with wildcards in string patterns.
52
     * @return self
53
     */
54
    public function withNotExactSlashes(): self
55
    {
56
        $new = clone $this;
57
        $new->matchSlashesExactly = false;
58
        return $new;
59
    }
60
61
    /**
62
     * Set list of patterns that the files or directories should match.
63
     * @param string|PathPattern ...$patterns
64
     * @return self
65
     */
66
    public function only(...$patterns): self
67
    {
68
        $new = clone $this;
69
        $new->only = $this->makePathPatterns($patterns);
70
        return $new;
71
    }
72
73
    /**
74
     * Set list of patterns that the files or directories should not match.
75
     * @param string|PathPattern ...$patterns
76
     * @return self
77
     */
78
    public function except(string ...$patterns): self
79
    {
80
        $new = clone $this;
81
        $new->except = $this->makePathPatterns($patterns);
82
        return $new;
83
    }
84
85
    /**
86
     * Set list of PHP callback that is called for each path.
87
     *
88
     * The signature of the callback should be: `function ($path)`, where `$path` refers the full path to be filtered.
89
     * The callback should return `true` if the passed path would match and `false` if it doesn't.
90
     *
91
     * @param callable ...$callbacks
92
     * @return self
93
     */
94
    public function callback(callable ...$callbacks): self
95
    {
96
        $new = clone $this;
97
        $new->callbacks = $callbacks;
0 ignored issues
show
Documentation Bug introduced by
It seems like $callbacks of type array<integer,callable> is incompatible with the declared type Yiisoft\Files\PathMatch\PathPattern[]|null of property $callbacks.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
98
        return $new;
99
    }
100
101
    /**
102
     * Checks if the passed path would match specified conditions.
103
     *
104
     * @param string $path The tested path.
105
     * @return bool Whether the path matches conditions or not.
106
     */
107
    public function match(string $path): bool
108
    {
109
        $path = str_replace('\\', '/', $path);
110
111
        if ($this->only !== null) {
112
            if (!$this->matchPathPatterns($path, $this->only)) {
113
                return false;
114
            }
115
        }
116
117
        if ($this->except !== null) {
118
            if ($this->matchPathPatterns($path, $this->except)) {
119
                return false;
120
            }
121
        }
122
123
        if ($this->callbacks !== null) {
124
            foreach ($this->callbacks as $callback) {
125
                if (!$callback($path)) {
126
                    return false;
127
                }
128
            }
129
        }
130
131
        return true;
132
    }
133
134
    /**
135
     * @param string $path
136
     * @param PathPattern[] $patterns
137
     * @return bool
138
     */
139
    private function matchPathPatterns(string $path, array $patterns): bool
140
    {
141
        foreach ($patterns as $pattern) {
142
            if ($pattern->match($path)) {
143
                return true;
144
            }
145
        }
146
147
        return false;
148
    }
149
150
    /**
151
     * @param string[]|PathPattern[] $patterns
152
     * @return PathPattern[]
153
     */
154
    private function makePathPatterns(array $patterns): array
155
    {
156
        $pathPatterns = [];
157
        foreach ($patterns as $pattern) {
158
            if ($pattern instanceof PathPattern) {
159
                $pathPatterns[] = $pattern;
160
                continue;
161
            }
162
163
            $pathPattern = new PathPattern($pattern);
164
165
            if ($this->caseSensitive) {
166
                $pathPattern = $pathPattern->caseSensitive();
167
            }
168
169
            if ($this->matchFullPath) {
170
                $pathPattern = $pathPattern->withFullPath();
171
            }
172
173
            if (!$this->matchSlashesExactly) {
174
                $pathPattern = $pathPattern->withNotExactSlashes();
175
            }
176
177
            $pathPatterns[] = $pathPattern;
178
        }
179
        return $pathPatterns;
180
    }
181
}
182