PluginProbe
TablePress – Tables in WordPress made easy / 3.2.1
TablePress – Tables in WordPress made easy v3.2.1
3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 2.4.4 All 44 releases
tablepress / libraries / vendor / composer / pcre / Preg.php

Preg.php in TablePress – Tables in WordPress made easy 3.2.1, at libraries/vendor/composer/pcre/Preg.php

431 lines 15.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * This file is part of composer/pcre.
5 *
6 * (c) Composer <https://github.com/composer>
7 *
8 * For the full copyright and license information, please view
9 * the LICENSE file that was distributed with this source code.
10 */
11
12 namespace TablePress\Composer\Pcre;
13
14 class Preg
15 {
16 /** @internal */
17 public const ARRAY_MSG = '$subject as an array is not supported. You can use \'foreach\' instead.';
18 /** @internal */
19 public const INVALID_TYPE_MSG = '$subject must be a string, %s given.';
20
21 /**
22 * @param non-empty-string $pattern
23 * @param array<mixed> $matches Set by method
24 * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
25 * @return 0|1
26 *
27 * @param-out array<int|string, string|null> $matches
28 */
29 public static function match(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int
30 {
31 self::checkOffsetCapture($flags, 'matchWithOffsets');
32
33 $result = preg_match($pattern, $subject, $matches, $flags | PREG_UNMATCHED_AS_NULL, $offset);
34 if ($result === false) {
35 throw PcreException::fromFunction('preg_match', $pattern);
36 }
37
38 return $result;
39 }
40
41 /**
42 * Variant of `match()` which outputs non-null matches (or throws)
43 *
44 * @param non-empty-string $pattern
45 * @param array<mixed> $matches Set by method
46 * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
47 * @return 0|1
48 * @throws UnexpectedNullMatchException
49 *
50 * @param-out array<int|string, string> $matches
51 */
52 public static function matchStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int
53 {
54 $result = self::match($pattern, $subject, $matchesInternal, $flags, $offset);
55 $matches = self::enforceNonNullMatches($pattern, $matchesInternal, 'match');
56
57 return $result;
58 }
59
60 /**
61 * Runs preg_match with PREG_OFFSET_CAPTURE
62 *
63 * @param non-empty-string $pattern
64 * @param array<mixed> $matches Set by method
65 * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_UNMATCHED_AS_NULL and PREG_OFFSET_CAPTURE are always set, no other flags are supported
66 * @return 0|1
67 *
68 * @param-out array<int|string, array{string|null, int<-1, max>}> $matches
69 */
70 public static function matchWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0): int
71 {
72 $result = preg_match($pattern, $subject, $matches, $flags | PREG_UNMATCHED_AS_NULL | PREG_OFFSET_CAPTURE, $offset);
73 if ($result === false) {
74 throw PcreException::fromFunction('preg_match', $pattern);
75 }
76
77 return $result;
78 }
79
80 /**
81 * @param non-empty-string $pattern
82 * @param array<mixed> $matches Set by method
83 * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
84 * @return 0|positive-int
85 *
86 * @param-out array<int|string, list<string|null>> $matches
87 */
88 public static function matchAll(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int
89 {
90 self::checkOffsetCapture($flags, 'matchAllWithOffsets');
91 self::checkSetOrder($flags);
92
93 $result = preg_match_all($pattern, $subject, $matches, $flags | PREG_UNMATCHED_AS_NULL, $offset);
94 if (!is_int($result)) { // PHP < 8 may return null, 8+ returns int|false
95 throw PcreException::fromFunction('preg_match_all', $pattern);
96 }
97
98 return $result;
99 }
100
101 /**
102 * Variant of `match()` which outputs non-null matches (or throws)
103 *
104 * @param non-empty-string $pattern
105 * @param array<mixed> $matches Set by method
106 * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
107 * @return 0|positive-int
108 * @throws UnexpectedNullMatchException
109 *
110 * @param-out array<int|string, list<string>> $matches
111 */
112 public static function matchAllStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int
113 {
114 $result = self::matchAll($pattern, $subject, $matchesInternal, $flags, $offset);
115 $matches = self::enforceNonNullMatchAll($pattern, $matchesInternal, 'matchAll');
116
117 return $result;
118 }
119
120 /**
121 * Runs preg_match_all with PREG_OFFSET_CAPTURE
122 *
123 * @param non-empty-string $pattern
124 * @param array<mixed> $matches Set by method
125 * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_UNMATCHED_AS_NULL and PREG_MATCH_OFFSET are always set, no other flags are supported
126 * @return 0|positive-int
127 *
128 * @param-out array<int|string, list<array{string|null, int<-1, max>}>> $matches
129 */
130 public static function matchAllWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0): int
131 {
132 self::checkSetOrder($flags);
133
134 $result = preg_match_all($pattern, $subject, $matches, $flags | PREG_UNMATCHED_AS_NULL | PREG_OFFSET_CAPTURE, $offset);
135 if (!is_int($result)) { // PHP < 8 may return null, 8+ returns int|false
136 throw PcreException::fromFunction('preg_match_all', $pattern);
137 }
138
139 return $result;
140 }
141
142 /**
143 * @param string|string[] $pattern
144 * @param string|string[] $replacement
145 * @param string $subject
146 * @param int $count Set by method
147 *
148 * @param-out int<0, max> $count
149 */
150 public static function replace($pattern, $replacement, $subject, int $limit = -1, ?int &$count = null): string
151 {
152 if (!is_scalar($subject)) {
153 if (is_array($subject)) {
154 throw new \InvalidArgumentException(static::ARRAY_MSG);
155 }
156
157 throw new \TypeError(sprintf(static::INVALID_TYPE_MSG, gettype($subject)));
158 }
159
160 $result = preg_replace($pattern, $replacement, $subject, $limit, $count);
161 if ($result === null) {
162 throw PcreException::fromFunction('preg_replace', $pattern);
163 }
164
165 return $result;
166 }
167
168 /**
169 * @param string|string[] $pattern
170 * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array<int|string, array{string|null, int<-1, max>}>): string) : callable(array<int|string, string|null>): string) $replacement
171 * @param string $subject
172 * @param int $count Set by method
173 * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set
174 *
175 * @param-out int<0, max> $count
176 */
177 public static function replaceCallback($pattern, callable $replacement, $subject, int $limit = -1, ?int &$count = null, int $flags = 0): string
178 {
179 if (!is_scalar($subject)) {
180 if (is_array($subject)) {
181 throw new \InvalidArgumentException(static::ARRAY_MSG);
182 }
183
184 throw new \TypeError(sprintf(static::INVALID_TYPE_MSG, gettype($subject)));
185 }
186
187 $result = preg_replace_callback($pattern, $replacement, $subject, $limit, $count, $flags | PREG_UNMATCHED_AS_NULL);
188 if ($result === null) {
189 throw PcreException::fromFunction('preg_replace_callback', $pattern);
190 }
191
192 return $result;
193 }
194
195 /**
196 * Variant of `replaceCallback()` which outputs non-null matches (or throws)
197 *
198 * @param string $pattern
199 * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array<int|string, array{string, int<0, max>}>): string) : callable(array<int|string, string>): string) $replacement
200 * @param string $subject
201 * @param int $count Set by method
202 * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set
203 *
204 * @param-out int<0, max> $count
205 */
206 public static function replaceCallbackStrictGroups(string $pattern, callable $replacement, $subject, int $limit = -1, ?int &$count = null, int $flags = 0): string
207 {
208 return self::replaceCallback($pattern, function (array $matches) use ($pattern, $replacement) {
209 return $replacement(self::enforceNonNullMatches($pattern, $matches, 'replaceCallback'));
210 }, $subject, $limit, $count, $flags);
211 }
212
213 /**
214 * @param ($flags is PREG_OFFSET_CAPTURE ? (array<string, callable(array<int|string, array{string|null, int<-1, max>}>): string>) : array<string, callable(array<int|string, string|null>): string>) $pattern
215 * @param string $subject
216 * @param int $count Set by method
217 * @param int-mask<PREG_UNMATCHED_AS_NULL|PREG_OFFSET_CAPTURE> $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set
218 *
219 * @param-out int<0, max> $count
220 */
221 public static function replaceCallbackArray(array $pattern, $subject, int $limit = -1, ?int &$count = null, int $flags = 0): string
222 {
223 if (!is_scalar($subject)) {
224 if (is_array($subject)) {
225 throw new \InvalidArgumentException(static::ARRAY_MSG);
226 }
227
228 throw new \TypeError(sprintf(static::INVALID_TYPE_MSG, gettype($subject)));
229 }
230
231 $result = preg_replace_callback_array($pattern, $subject, $limit, $count, $flags | PREG_UNMATCHED_AS_NULL);
232 if ($result === null) {
233 $pattern = array_keys($pattern);
234 throw PcreException::fromFunction('preg_replace_callback_array', $pattern);
235 }
236
237 return $result;
238 }
239
240 /**
241 * @param int-mask<PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_OFFSET_CAPTURE> $flags PREG_SPLIT_NO_EMPTY or PREG_SPLIT_DELIM_CAPTURE
242 * @return list<string>
243 */
244 public static function split(string $pattern, string $subject, int $limit = -1, int $flags = 0): array
245 {
246 if (($flags & PREG_SPLIT_OFFSET_CAPTURE) !== 0) {
247 throw new \InvalidArgumentException('PREG_SPLIT_OFFSET_CAPTURE is not supported as it changes the type of $matches, use splitWithOffsets() instead');
248 }
249
250 $result = preg_split($pattern, $subject, $limit, $flags);
251 if ($result === false) {
252 throw PcreException::fromFunction('preg_split', $pattern);
253 }
254
255 return $result;
256 }
257
258 /**
259 * @param int-mask<PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_OFFSET_CAPTURE> $flags PREG_SPLIT_NO_EMPTY or PREG_SPLIT_DELIM_CAPTURE, PREG_SPLIT_OFFSET_CAPTURE is always set
260 * @return list<array{string, int}>
261 * @phpstan-return list<array{string, int<0, max>}>
262 */
263 public static function splitWithOffsets(string $pattern, string $subject, int $limit = -1, int $flags = 0): array
264 {
265 $result = preg_split($pattern, $subject, $limit, $flags | PREG_SPLIT_OFFSET_CAPTURE);
266 if ($result === false) {
267 throw PcreException::fromFunction('preg_split', $pattern);
268 }
269
270 return $result;
271 }
272
273 /**
274 * @template T of string|\Stringable
275 * @param string $pattern
276 * @param array<T> $array
277 * @param int-mask<PREG_GREP_INVERT> $flags PREG_GREP_INVERT
278 * @return array<T>
279 */
280 public static function grep(string $pattern, array $array, int $flags = 0): array
281 {
282 $result = preg_grep($pattern, $array, $flags);
283 if ($result === false) {
284 throw PcreException::fromFunction('preg_grep', $pattern);
285 }
286
287 return $result;
288 }
289
290 /**
291 * Variant of match() which returns a bool instead of int
292 *
293 * @param non-empty-string $pattern
294 * @param array<mixed> $matches Set by method
295 * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
296 *
297 * @param-out array<int|string, string|null> $matches
298 */
299 public static function isMatch(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool
300 {
301 return (bool) static::match($pattern, $subject, $matches, $flags, $offset);
302 }
303
304 /**
305 * Variant of `isMatch()` which outputs non-null matches (or throws)
306 *
307 * @param non-empty-string $pattern
308 * @param array<mixed> $matches Set by method
309 * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
310 * @throws UnexpectedNullMatchException
311 *
312 * @param-out array<int|string, string> $matches
313 */
314 public static function isMatchStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool
315 {
316 return (bool) self::matchStrictGroups($pattern, $subject, $matches, $flags, $offset);
317 }
318
319 /**
320 * Variant of matchAll() which returns a bool instead of int
321 *
322 * @param non-empty-string $pattern
323 * @param array<mixed> $matches Set by method
324 * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
325 *
326 * @param-out array<int|string, list<string|null>> $matches
327 */
328 public static function isMatchAll(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool
329 {
330 return (bool) static::matchAll($pattern, $subject, $matches, $flags, $offset);
331 }
332
333 /**
334 * Variant of `isMatchAll()` which outputs non-null matches (or throws)
335 *
336 * @param non-empty-string $pattern
337 * @param array<mixed> $matches Set by method
338 * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
339 *
340 * @param-out array<int|string, list<string>> $matches
341 */
342 public static function isMatchAllStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool
343 {
344 return (bool) self::matchAllStrictGroups($pattern, $subject, $matches, $flags, $offset);
345 }
346
347 /**
348 * Variant of matchWithOffsets() which returns a bool instead of int
349 *
350 * Runs preg_match with PREG_OFFSET_CAPTURE
351 *
352 * @param non-empty-string $pattern
353 * @param array<mixed> $matches Set by method
354 * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
355 *
356 * @param-out array<int|string, array{string|null, int<-1, max>}> $matches
357 */
358 public static function isMatchWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0): bool
359 {
360 return (bool) static::matchWithOffsets($pattern, $subject, $matches, $flags, $offset);
361 }
362
363 /**
364 * Variant of matchAllWithOffsets() which returns a bool instead of int
365 *
366 * Runs preg_match_all with PREG_OFFSET_CAPTURE
367 *
368 * @param non-empty-string $pattern
369 * @param array<mixed> $matches Set by method
370 * @param int-mask<PREG_UNMATCHED_AS_NULL> $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported
371 *
372 * @param-out array<int|string, list<array{string|null, int<-1, max>}>> $matches
373 */
374 public static function isMatchAllWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0): bool
375 {
376 return (bool) static::matchAllWithOffsets($pattern, $subject, $matches, $flags, $offset);
377 }
378
379 private static function checkOffsetCapture(int $flags, string $useFunctionName): void
380 {
381 if (($flags & PREG_OFFSET_CAPTURE) !== 0) {
382 throw new \InvalidArgumentException('PREG_OFFSET_CAPTURE is not supported as it changes the type of $matches, use ' . $useFunctionName . '() instead');
383 }
384 }
385
386 private static function checkSetOrder(int $flags): void
387 {
388 if (($flags & PREG_SET_ORDER) !== 0) {
389 throw new \InvalidArgumentException('PREG_SET_ORDER is not supported as it changes the type of $matches');
390 }
391 }
392
393 /**
394 * @param array<int|string, string|null|array{string|null, int}> $matches
395 * @return array<int|string, string>
396 * @throws UnexpectedNullMatchException
397 */
398 private static function enforceNonNullMatches(string $pattern, array $matches, string $variantMethod)
399 {
400 foreach ($matches as $group => $match) {
401 if (is_string($match) || (is_array($match) && is_string($match[0]))) {
402 continue;
403 }
404
405 throw new UnexpectedNullMatchException('Pattern "'.$pattern.'" had an unexpected unmatched group "'.$group.'", make sure the pattern always matches or use '.$variantMethod.'() instead.');
406 }
407
408 /** @var array<string> */
409 return $matches;
410 }
411
412 /**
413 * @param array<int|string, list<string|null>> $matches
414 * @return array<int|string, list<string>>
415 * @throws UnexpectedNullMatchException
416 */
417 private static function enforceNonNullMatchAll(string $pattern, array $matches, string $variantMethod)
418 {
419 foreach ($matches as $group => $groupMatches) {
420 foreach ($groupMatches as $match) {
421 if (null === $match) {
422 throw new UnexpectedNullMatchException('Pattern "'.$pattern.'" had an unexpected unmatched group "'.$group.'", make sure the pattern always matches or use '.$variantMethod.'() instead.');
423 }
424 }
425 }
426
427 /** @var array<int|string, list<string>> */
428 return $matches;
429 }
430 }
431