Skip to content

Commit 4775f35

Browse files
committed
Fix bug in Preg::replaceCallbackStrictGroups not detecting null values when used with PREG_OFFSET_CAPTURE
1 parent 7539e8f commit 4775f35

File tree

3 files changed

+25
-8
lines changed

3 files changed

+25
-8
lines changed

phpstan-baseline.neon

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@ parameters:
55
count: 1
66
path: src/Preg.php
77

8-
-
9-
message: "#^Parameter \\#2 \\$matches of static method Composer\\\\Pcre\\\\Preg\\:\\:enforceNonNullMatches\\(\\) expects array\\<int\\|string, string\\|null\\>, array\\<int\\|string, array\\<int, int\\|string\\|null\\>\\|string\\|null\\> given\\.$#"
10-
count: 1
11-
path: src/Preg.php
12-
138
-
149
message: "#^Parameter &\\$matches @param\\-out type of method Composer\\\\Pcre\\\\Preg\\:\\:match\\(\\) expects array\\<int\\|string, string\\|null\\>, \\(int is int \\? array\\<array\\<int, int\\<\\-1, max\\>\\|string\\>\\> \\: \\(int is int \\? array\\<string\\|null\\> \\: \\(int is int \\? array\\<array\\<int, int\\|string\\|null\\>\\> \\: array\\<string\\>\\)\\)\\) given\\.$#"
1510
count: 1

src/Preg.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,16 +391,18 @@ private static function checkSetOrder(int $flags): void
391391
}
392392

393393
/**
394-
* @param array<int|string, string|null> $matches
394+
* @param array<int|string, string|null|array{string|null, int}> $matches
395395
* @return array<int|string, string>
396396
* @throws UnexpectedNullMatchException
397397
*/
398398
private static function enforceNonNullMatches(string $pattern, array $matches, string $variantMethod)
399399
{
400400
foreach ($matches as $group => $match) {
401-
if (null === $match) {
402-
throw new UnexpectedNullMatchException('Pattern "'.$pattern.'" had an unexpected unmatched group "'.$group.'", make sure the pattern always matches or use '.$variantMethod.'() instead.');
401+
if (is_string($match) || (is_array($match) && is_string($match[0]))) {
402+
continue;
403403
}
404+
405+
throw new UnexpectedNullMatchException('Pattern "'.$pattern.'" had an unexpected unmatched group "'.$group.'", make sure the pattern always matches or use '.$variantMethod.'() instead.');
404406
}
405407

406408
/** @var array<string> */

tests/PregTests/ReplaceCallbackTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,26 @@ public function testFailStrictGroups(): void
8181
}, '123', -1, $count);
8282
}
8383

84+
public function testSuccessStrictGroupsOffsets(): void
85+
{
86+
$result = Preg::replaceCallbackStrictGroups('{(?P<m>\d)(?<matched>a)?}', function ($match) {
87+
return strtoupper($match['matched'][0]);
88+
}, '3a', -1, $count, PREG_OFFSET_CAPTURE);
89+
90+
self::assertSame(1, $count);
91+
self::assertSame('A', $result);
92+
}
93+
94+
public function testFailsStrictGroupsOffsets(): void
95+
{
96+
self::expectException(UnexpectedNullMatchException::class);
97+
self::expectExceptionMessage('Pattern "{(?P<m>\d)(?<unmatched>a)?}" had an unexpected unmatched group "unmatched", make sure the pattern always matches or use replaceCallback() instead.');
98+
99+
$result = Preg::replaceCallbackStrictGroups('{(?P<m>\d)(?<unmatched>a)?}', function ($match) {
100+
return strtoupper($match['unmatched'][0]);
101+
}, '3', -1, $count, PREG_OFFSET_CAPTURE);
102+
}
103+
84104
public function testBadPatternThrowsIfWarningsAreNotThrowing(): void
85105
{
86106
$this->expectPcreException($pattern = '{(?P<m>d)');

0 commit comments

Comments
 (0)