|
28 | 28 | private const T_SLASH = 'slash';
|
29 | 29 | private const T_BACKSLASH = 'backslash';
|
30 | 30 | private const T_CHAR = 'char';
|
31 |
| - private const T_GLOBSTAR = 'globstar'; |
| 31 | + private const T_GREEDY_GLOBSTAR = 'greedy_globstar'; |
32 | 32 | private const T_QUERY = 'query';
|
| 33 | + private const T_GLOBSTAR = 'globstar'; |
33 | 34 |
|
34 | 35 |
|
35 | 36 | public static function match(string $path, FileMatcherPattern $pattern): bool
|
@@ -58,18 +59,22 @@ public static function toRegEx($glob, $flags = 0): string
|
58 | 59 | $type = $token[0];
|
59 | 60 | $regex .= match ($type) {
|
60 | 61 | // literal char
|
61 |
| - self::T_CHAR => $token[1] ?? throw new Exception('Expected char token to have a value'), |
| 62 | + self::T_CHAR => preg_quote($token[1]), |
62 | 63 |
|
63 | 64 | // literal directory separator
|
64 | 65 | self::T_SLASH => '/',
|
65 | 66 | self::T_QUERY => '.',
|
66 | 67 |
|
67 | 68 | // match any segment up until the next directory separator
|
68 | 69 | self::T_ASTERIX => '[^/]*',
|
69 |
| - self::T_GLOBSTAR => '.*', |
| 70 | + self::T_GREEDY_GLOBSTAR => '.*', |
| 71 | + self::T_GLOBSTAR => '/([^/]+/)*', |
70 | 72 | default => '',
|
71 | 73 | };
|
72 | 74 | }
|
| 75 | + $regex .= '(/|$)'; |
| 76 | + dump($tokens); |
| 77 | + dump($regex); |
73 | 78 |
|
74 | 79 | return '{^'.$regex.'}';
|
75 | 80 | }
|
@@ -133,9 +138,33 @@ private static function processTokens(array $tokens): array
|
133 | 138 | continue;
|
134 | 139 | }
|
135 | 140 |
|
136 |
| - if ($type === self::T_ASTERIX && ($tokens[$offset + 1] ?? null) === self::T_ASTERIX) { |
137 |
| - $offset++; |
| 141 | + // normal globstar |
| 142 | + if ( |
| 143 | + $type === self::T_SLASH && |
| 144 | + ($tokens[$offset + 1][0] ?? null) === self::T_ASTERIX && ($tokens[$offset + 2][0] ?? null) === self::T_ASTERIX && ($tokens[$offset + 3][0] ?? null) === self::T_SLASH |
| 145 | + ) { |
138 | 146 | $resolved[] = [self::T_GLOBSTAR, '**'];
|
| 147 | + |
| 148 | + // we eat the two `*` in addition to the slash |
| 149 | + $offset += 3; |
| 150 | + continue; |
| 151 | + } |
| 152 | + |
| 153 | + // greedy globstar (trailing?) |
| 154 | + if ( |
| 155 | + $type === self::T_SLASH && |
| 156 | + ($tokens[$offset + 1][0] ?? null) === self::T_ASTERIX && ($tokens[$offset + 2][0] ?? null) === self::T_ASTERIX |
| 157 | + ) { |
| 158 | + $resolved[] = [self::T_GREEDY_GLOBSTAR, '**']; |
| 159 | + |
| 160 | + // we eat the two `*` in addition to the slash |
| 161 | + $offset += 2; |
| 162 | + continue; |
| 163 | + } |
| 164 | + |
| 165 | + if ($type === self::T_ASTERIX && ($tokens[$offset + 1][0] ?? null) === self::T_ASTERIX) { |
| 166 | + $resolved[] = [self::T_CHAR, $char]; |
| 167 | + $resolved[] = [self::T_CHAR, $char]; |
139 | 168 | continue;
|
140 | 169 | }
|
141 | 170 |
|
|
0 commit comments