Skip to content

Commit

Permalink
Fix bug in Preg::replaceCallbackStrictGroups not detecting null value…
Browse files Browse the repository at this point in the history
…s when used with PREG_OFFSET_CAPTURE
  • Loading branch information
Seldaek committed Mar 7, 2024
1 parent 7539e8f commit 4775f35
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 8 deletions.
5 changes: 0 additions & 5 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@ parameters:
count: 1
path: src/Preg.php

-
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\\.$#"
count: 1
path: src/Preg.php

-
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\\.$#"
count: 1
Expand Down
8 changes: 5 additions & 3 deletions src/Preg.php
Original file line number Diff line number Diff line change
Expand Up @@ -391,16 +391,18 @@ private static function checkSetOrder(int $flags): void
}

/**
* @param array<int|string, string|null> $matches
* @param array<int|string, string|null|array{string|null, int}> $matches
* @return array<int|string, string>
* @throws UnexpectedNullMatchException
*/
private static function enforceNonNullMatches(string $pattern, array $matches, string $variantMethod)
{
foreach ($matches as $group => $match) {
if (null === $match) {
throw new UnexpectedNullMatchException('Pattern "'.$pattern.'" had an unexpected unmatched group "'.$group.'", make sure the pattern always matches or use '.$variantMethod.'() instead.');
if (is_string($match) || (is_array($match) && is_string($match[0]))) {
continue;
}

throw new UnexpectedNullMatchException('Pattern "'.$pattern.'" had an unexpected unmatched group "'.$group.'", make sure the pattern always matches or use '.$variantMethod.'() instead.');
}

/** @var array<string> */
Expand Down
20 changes: 20 additions & 0 deletions tests/PregTests/ReplaceCallbackTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,26 @@ public function testFailStrictGroups(): void
}, '123', -1, $count);
}

public function testSuccessStrictGroupsOffsets(): void
{
$result = Preg::replaceCallbackStrictGroups('{(?P<m>\d)(?<matched>a)?}', function ($match) {
return strtoupper($match['matched'][0]);
}, '3a', -1, $count, PREG_OFFSET_CAPTURE);

self::assertSame(1, $count);
self::assertSame('A', $result);
}

public function testFailsStrictGroupsOffsets(): void
{
self::expectException(UnexpectedNullMatchException::class);
self::expectExceptionMessage('Pattern "{(?P<m>\d)(?<unmatched>a)?}" had an unexpected unmatched group "unmatched", make sure the pattern always matches or use replaceCallback() instead.');

$result = Preg::replaceCallbackStrictGroups('{(?P<m>\d)(?<unmatched>a)?}', function ($match) {
return strtoupper($match['unmatched'][0]);
}, '3', -1, $count, PREG_OFFSET_CAPTURE);
}

public function testBadPatternThrowsIfWarningsAreNotThrowing(): void
{
$this->expectPcreException($pattern = '{(?P<m>d)');
Expand Down

0 comments on commit 4775f35

Please sign in to comment.