Skip to content

Commit 3980192

Browse files
authored
Adding preg_replace to special cases functions (#72)
* Adding preg_replace to special cases functions
1 parent 3c9f28a commit 3980192

File tree

8 files changed

+135
-9
lines changed

8 files changed

+135
-9
lines changed

generated/Exceptions/PcreException.php

Lines changed: 0 additions & 6 deletions
This file was deleted.

generated/functionsList.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,4 +1074,5 @@
10741074
'json_decode',
10751075
'apc_fetch',
10761076
'apcu_fetch',
1077+
'preg_replace',
10771078
];

generator/config/specialCasesFunctions.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
return [
77
'json_decode',
88
'apc_fetch',
9-
'apcu_fetch'
9+
'apcu_fetch',
10+
'preg_replace',
1011
];

generator/tests/GeneratedFilesTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function testPregMatch()
3737
require_once __DIR__.'/../../generated/pcre.php';
3838
require_once __DIR__.'/../../lib/Exceptions/SafeExceptionInterface.php';
3939
require_once __DIR__.'/../../lib/Exceptions/AbstractSafeException.php';
40-
require_once __DIR__.'/../../generated/Exceptions/PcreException.php';
40+
require_once __DIR__.'/../../lib/Exceptions/PcreException.php';
4141

4242

4343
$url = 'https://open.spotify.com/track/0nCqpKBrvDchO1BIvt7DTR?si=iLUKDfkLSy-IpnLA7qImnw';
@@ -83,7 +83,7 @@ public function testPregSplit()
8383
require_once __DIR__.'/../../generated/pcre.php';
8484
require_once __DIR__.'/../../lib/Exceptions/SafeExceptionInterface.php';
8585
require_once __DIR__.'/../../lib/Exceptions/AbstractSafeException.php';
86-
require_once __DIR__.'/../../generated/Exceptions/PcreException.php';
86+
require_once __DIR__.'/../../lib/Exceptions/PcreException.php';
8787

8888
$keywords = preg_split("/[\s,]+/", "hypertext language, programming", null);
8989
$this->assertSame(['hypertext', 'language', 'programming'], $keywords);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Safe;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Safe\Exceptions\PcreException;
7+
8+
class SpecialCasesTest extends TestCase
9+
{
10+
public function testPregReplace()
11+
{
12+
require_once __DIR__.'/../../lib/special_cases.php';
13+
require_once __DIR__.'/../../lib/Exceptions/SafeExceptionInterface.php';
14+
require_once __DIR__.'/../../lib/Exceptions/AbstractSafeException.php';
15+
require_once __DIR__.'/../../lib/Exceptions/PcreException.php';
16+
17+
$this->expectException(PcreException::class);
18+
$this->expectExceptionMessage('PREG_BAD_UTF8_ERROR: Invalid UTF8 character');
19+
preg_replace("/([\s,]+)/u", "foo", "\xc3\x28");
20+
}
21+
}

lib/Exceptions/PcreException.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
4+
namespace Safe\Exceptions;
5+
6+
class PcreException extends \Exception implements SafeExceptionInterface
7+
{
8+
public static function createFromPhpError(): self
9+
{
10+
$errorMap = [
11+
PREG_INTERNAL_ERROR => 'PREG_INTERNAL_ERROR: Internal error',
12+
PREG_BACKTRACK_LIMIT_ERROR => 'PREG_BACKTRACK_LIMIT_ERROR: Backtrack limit reached',
13+
PREG_RECURSION_LIMIT_ERROR => 'PREG_RECURSION_LIMIT_ERROR: Recursion limit reached',
14+
PREG_BAD_UTF8_ERROR => 'PREG_BAD_UTF8_ERROR: Invalid UTF8 character',
15+
PREG_BAD_UTF8_OFFSET_ERROR => 'PREG_BAD_UTF8_OFFSET_ERROR',
16+
PREG_JIT_STACKLIMIT_ERROR => 'PREG_JIT_STACKLIMIT_ERROR',
17+
];
18+
$errMsg = $errorMap[preg_last_error()] ?? 'Unknown PCRE error: '.preg_last_error();
19+
return new static($errMsg, \preg_last_error());
20+
}
21+
}

lib/special_cases.php

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
namespace Safe;
99

10+
use const PREG_NO_ERROR;
1011
use Safe\Exceptions\ApcException;
1112
use Safe\Exceptions\ApcuException;
1213
use Safe\Exceptions\JsonException;
14+
use Safe\Exceptions\PcreException;
1315

1416
/**
1517
* Wrapper for json_decode that throws when an error occurs.
@@ -73,3 +75,88 @@ function apcu_fetch($key)
7375
}
7476
return $result;
7577
}
78+
79+
/**
80+
* Searches subject for matches to
81+
* pattern and replaces them with
82+
* replacement.
83+
*
84+
* @param mixed $pattern The pattern to search for. It can be either a string or an array with
85+
* strings.
86+
*
87+
* Several PCRE modifiers
88+
* are also available.
89+
* @param mixed $replacement The string or an array with strings to replace. If this parameter is a
90+
* string and the pattern parameter is an array,
91+
* all patterns will be replaced by that string. If both
92+
* pattern and replacement
93+
* parameters are arrays, each pattern will be
94+
* replaced by the replacement counterpart. If
95+
* there are fewer elements in the replacement
96+
* array than in the pattern array, any extra
97+
* patterns will be replaced by an empty string.
98+
*
99+
* replacement may contain references of the form
100+
* \\n or
101+
* $n, with the latter form
102+
* being the preferred one. Every such reference will be replaced by the text
103+
* captured by the n'th parenthesized pattern.
104+
* n can be from 0 to 99, and
105+
* \\0 or $0 refers to the text matched
106+
* by the whole pattern. Opening parentheses are counted from left to right
107+
* (starting from 1) to obtain the number of the capturing subpattern.
108+
* To use backslash in replacement, it must be doubled
109+
* ("\\\\" PHP string).
110+
*
111+
* When working with a replacement pattern where a backreference is
112+
* immediately followed by another number (i.e.: placing a literal number
113+
* immediately after a matched pattern), you cannot use the familiar
114+
* \\1 notation for your backreference.
115+
* \\11, for example, would confuse
116+
* preg_replace since it does not know whether you
117+
* want the \\1 backreference followed by a literal
118+
* 1, or the \\11 backreference
119+
* followed by nothing. In this case the solution is to use
120+
* ${1}1. This creates an isolated
121+
* $1 backreference, leaving the 1
122+
* as a literal.
123+
*
124+
* When using the deprecated e modifier, this function escapes
125+
* some characters (namely ', ",
126+
* \ and NULL) in the strings that replace the
127+
* backreferences. This is done to ensure that no syntax errors arise
128+
* from backreference usage with either single or double quotes (e.g.
129+
* 'strlen(\'$1\')+strlen("$2")'). Make sure you are
130+
* aware of PHP's string
131+
* syntax to know exactly how the interpreted string will look.
132+
* @param string|array $subject The string or an array with strings to search and replace.
133+
*
134+
* If subject is an array, then the search and
135+
* replace is performed on every entry of subject,
136+
* and the return value is an array as well.
137+
* @param int $limit The maximum possible replacements for each pattern in each
138+
* subject string. Defaults to
139+
* -1 (no limit).
140+
* @param int $count If specified, this variable will be filled with the number of
141+
* replacements done.
142+
* @return string|array|null preg_replace returns an array if the
143+
* subject parameter is an array, or a string
144+
* otherwise.
145+
*
146+
* If matches are found, the new subject will
147+
* be returned, otherwise subject will be
148+
* returned unchanged.
149+
*
150+
* Returns a file pointer resource on success, .
151+
* @throws PcreException
152+
*
153+
*/
154+
function preg_replace($pattern, $replacement, $subject, int $limit = -1, int &$count = null)
155+
{
156+
error_clear_last();
157+
$result = \preg_replace($pattern, $replacement, $subject, $limit, $count);
158+
if (preg_last_error() !== PREG_NO_ERROR) {
159+
throw PcreException::createFromPhpError();
160+
}
161+
return $result;
162+
}

rector-migrate.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,3 +1075,4 @@ services:
10751075
json_decode: 'Safe\json_decode'
10761076
apc_fetch: 'Safe\apc_fetch'
10771077
apcu_fetch: 'Safe\apcu_fetch'
1078+
preg_replace: 'Safe\preg_replace'

0 commit comments

Comments
 (0)