", $info);
- $info = \str_ireplace(self::REDACTED, '' . self::REDACTED . '', $info);
+ $info = \str_ireplace(self::REDACTED, \sprintf('%s', self::REDACTED), $info);
foreach (['Directive', 'Local Value', 'Master Value'] as $value) {
- $info = \str_replace($value, '' . $value . '', $info);
+ $info = \str_replace($value, \sprintf('%s', $value), $info);
}
- foreach (['on', 'yes', 'enabled'] as $value) {
- $search = '/' . $value . '\s?<\/td>/mi';
- $replace = ' | ' . StringUtils::capitalize($value) . ' | ';
- $info = (string) \preg_replace($search, $replace, $info);
+ foreach (self::ENABLED as $value) {
+ $search = \sprintf('/%s\s?<\/td>/mi', $value);
+ $replace = \sprintf(' | %s | ', StringUtils::capitalize($value));
+ $info = $this->pregReplace($search, $replace, $info);
- $search = '/' . $value . '\s?<\/th>/mi';
- $replace = ' | ' . StringUtils::capitalize($value) . ' | ';
- $info = (string) \preg_replace($search, $replace, $info);
+ $search = \sprintf('/%s\s?<\/th>/mi', $value);
+ $replace = \sprintf(' | %s | ', StringUtils::capitalize($value));
+ $info = $this->pregReplace($search, $replace, $info);
}
- foreach (['off', 'no', 'disabled'] as $value) {
- $search = '/' . $value . '\s?<\/td>/mi';
- $replace = ' | ' . StringUtils::capitalize($value) . ' | ';
- $info = (string) \preg_replace($search, $replace, $info);
+ foreach (self::DISABLED as $value) {
+ $search = \sprintf('/%s\s?<\/td>/mi', $value);
+ $replace = \sprintf(' | %s | ', StringUtils::capitalize($value));
+ $info = $this->pregReplace($search, $replace, $info);
- $search = '/' . $value . '\s?<\/th>/mi';
- $replace = ' | ' . StringUtils::capitalize($value) . ' | ';
- $info = (string) \preg_replace($search, $replace, $info);
+ $search = \sprintf('/%s\s?<\/th>/mi', $value);
+ $replace = \sprintf(' | %s | ', StringUtils::capitalize($value));
+ $info = $this->pregReplace($search, $replace, $info);
}
- return (string) \preg_replace('/(.+?)<\/table>/is', '', $info, 1);
+ return $this->pregReplace('/(.+?)<\/table>/is', '', $info, 1);
}
/**
@@ -158,13 +163,13 @@ public function getVersion(): string
private function convert(string $var): string|int|float
{
- if (\in_array(\strtolower($var), ['yes', 'no', 'enabled', 'disabled', 'on', 'off', 'no value'], true)) {
+ if (\in_array(\strtolower($var), self::CONVERT, true)) {
return StringUtils::capitalize($var);
}
- if (1 === \preg_match('/^-?\d+$/', $var)) {
+ if (StringUtils::pregMatch('/^-?\d+$/', $var)) {
return (int) $var;
}
- if (1 === \preg_match('/^-?\d+\.\d+$/', $var)) {
+ if (StringUtils::pregMatch('/^-?\d+\.\d+$/', $var)) {
$pos = (int) \strrpos($var, '.');
$decimals = \strlen($var) - $pos - 1;
@@ -174,13 +179,21 @@ private function convert(string $var): string|int|float
return \str_replace('\\', '/', $var);
}
+ /**
+ * @param non-empty-string $pattern
+ */
+ private function pregReplace(string $pattern, string $replacement, string $subject, int $limit = -1): string
+ {
+ return (string) \preg_replace($pattern, $replacement, $subject, $limit);
+ }
+
private function updateContent(string $content): string
{
- $subst = '$1' . self::REDACTED . '$3';
+ $subst = \sprintf('$1%s$3', self::REDACTED);
$keys = ['_KEY', '_USER_NAME', 'APP_SECRET', '_PASSWORD', 'MAILER_DSN', 'DATABASE_URL'];
foreach ($keys as $key) {
- $regex = "/()(.*)(<.*<\/tr>)/mi";
- $content = (string) \preg_replace($regex, $subst, $content);
+ $regex = \sprintf("/()(.*)(<.*<\/tr>)/mi", $key);
+ $content = $this->pregReplace($regex, $subst, $content);
}
$content = \str_replace(['✘ ', '✔ ', '⊕'], '', $content);
diff --git a/src/Spreadsheet/PhpIniDocument.php b/src/Spreadsheet/PhpIniDocument.php
index 810c4f3b4..6dfeeb79d 100644
--- a/src/Spreadsheet/PhpIniDocument.php
+++ b/src/Spreadsheet/PhpIniDocument.php
@@ -79,7 +79,7 @@ public function render(): bool
private function applyStyle(Worksheet $sheet, int $column, int $row, string $var): self
{
$color = null;
- if (1 === \preg_match('/#[\dA-Fa-f]{6}/i', $var)) {
+ if (StringUtils::pregMatch('/#[\dA-Fa-f]{6}/i', $var)) {
$color = \substr($var, 1);
} elseif (\in_array(
\strtolower($var),
diff --git a/src/Twig/PregExtension.php b/src/Twig/PregExtension.php
deleted file mode 100644
index b77f259aa..000000000
--- a/src/Twig/PregExtension.php
+++ /dev/null
@@ -1,147 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-declare(strict_types=1);
-
-namespace App\Twig;
-
-use App\Utils\StringUtils;
-use Twig\Extension\AbstractExtension;
-use Twig\TwigFilter;
-
-/**
- * Twig extension for preg_** functions.
- */
-class PregExtension extends AbstractExtension
-{
- public function getFilters(): array
- {
- return [
- new TwigFilter('preg_filter', $this->pregFilter(...)),
- new TwigFilter('preg_grep', $this->pregGrep(...)),
- new TwigFilter('preg_match', $this->pregMatch(...)),
- new TwigFilter('preg_quote', $this->pregQuote(...)),
- new TwigFilter('preg_replace', $this->pregReplace(...)),
- new TwigFilter('preg_split', $this->pregSplit(...)),
- ];
- }
-
- /**
- * Perform a regular expression search and replace, returning only matched subjects.
- *
- * @param string|string[]|null $subject
- * @param string|string[] $pattern
- * @param string|string[] $replacement
- *
- * @return string|string[]|null
- *
- * @psalm-param array|non-empty-string $pattern
- */
- protected function pregFilter(
- string|array|null $subject,
- string|array $pattern,
- string|array $replacement,
- int $limit = -1
- ): string|array|null {
- if (null === $subject) {
- return null;
- }
-
- return \preg_filter($pattern, $replacement, $subject, $limit);
- }
-
- /**
- * Perform a regular expression match and return an array of entries that match the pattern.
- *
- * @param string[]|null $subject
- *
- * @psalm-param int<0,1> $flags
- * @psalm-param non-empty-string $pattern
- */
- protected function pregGrep(?array $subject, string $pattern, int $flags = 0): array|false
- {
- if (null === $subject) {
- return false;
- }
-
- return \preg_grep($pattern, $subject, $flags);
- }
-
- /**
- * Perform a regular expression match.
- *
- * @psalm-param int-mask<256, 512, 768> $flags
- * @psalm-param int $offset
- * @psalm-param non-empty-string $pattern
- */
- protected function pregMatch(?string $subject, string $pattern, int $flags = 0, int $offset = 0): array|false
- {
- if (!StringUtils::isString($subject)) {
- return false;
- }
- if (1 === \preg_match($pattern, $subject, $matches, $flags, $offset)) {
- return $matches;
- }
-
- return false;
- }
-
- /**
- * Quote regular expression characters.
- */
- protected function pregQuote(?string $subject, ?string $delimiter = null): ?string
- {
- if (null === $subject) {
- return null;
- }
-
- return \preg_quote($subject, $delimiter);
- }
-
- /**
- * Perform a regular expression search and replace.
- *
- * @param string[]|string|null $subject
- * @param string[]|string $pattern
- * @param string[]|string $replacement
- *
- * @return string[]|string|null
- *
- * @psalm-param array|non-empty-string $pattern
- */
- protected function pregReplace(
- array|string|null $subject,
- array|string $pattern,
- array|string $replacement,
- int $limit = -1
- ): array|string|null {
- if (null === $subject) {
- return null;
- }
-
- return \preg_replace($pattern, $replacement, $subject, $limit);
- }
-
- /**
- * Split text into an array using a regular expression.
- *
- * @return string[]|false
- *
- * @psalm-param non-empty-string $pattern
- */
- protected function pregSplit(?string $subject, string $pattern): array|false
- {
- if (null === $subject) {
- return false;
- }
-
- return \preg_split($pattern, $subject);
- }
-}
diff --git a/src/Utils/StringUtils.php b/src/Utils/StringUtils.php
index 030c1d1cf..7aec95d00 100644
--- a/src/Utils/StringUtils.php
+++ b/src/Utils/StringUtils.php
@@ -175,11 +175,60 @@ public static function isString(?string $str): bool
return null !== $str && '' !== $str;
}
+ /**
+ * Perform a regular expression match.
+ *
+ * @param string $pattern the pattern to search for
+ * @param string $subject the input string
+ *
+ * @param-out string[] $matches if matches is provided, then it is filled with the results of search.
+ *
+ * @param int $flags can be a combination of flags
+ * @param int $offset to specify the place from which to start the search
+ *
+ * @return bool true
if the pattern matches the given subject
+ *
+ * @psalm-pure
+ *
+ * @psalm-param non-empty-string $pattern
+ *
+ * @phpstan-param int-mask<256, 512> $flags
+ */
+ public static function pregMatch(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool
+ {
+ return 1 === \preg_match($pattern, $subject, $matches, $flags, $offset);
+ }
+
+ /**
+ * Perform a global regular expression match.
+ *
+ * @param string $pattern the pattern to search for
+ * @param string $subject the input string
+ *
+ * @param-out string[] $matches if matches is provided, then it is filled with the results of search.
+ *
+ * @param int $flags can be a combination of flags
+ * @param int $offset to specify the place from which to start the search
+ *
+ * @return bool true
if the pattern matches the given subject
+ *
+ * @psalm-pure
+ *
+ * @psalm-param non-empty-string $pattern
+ */
+ public static function pregMatchAll(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool
+ {
+ $result = \preg_match_all($pattern, $subject, $matches, $flags, $offset);
+
+ return \is_int($result) && $result > 0;
+ }
+
/**
* Replace all occurrences of the pattern string with the replacement string.
*
* @param array $values an array where key is the pattern, and value is the replacement term
* @param string|string[] $subject the string or array being searched and replaced on
+ * @param int $limit the maximum possible replacements for each pattern in each subject string
*
* @return string|string[] returns a string or an array with the replaced values
*
@@ -187,10 +236,10 @@ public static function isString(?string $str): bool
*
* @psalm-return ($subject is string ? string : string[])
*/
- public static function pregReplace(array $values, string|array $subject): string|array
+ public static function pregReplace(array $values, string|array $subject, int $limit = -1): string|array
{
/** @psalm-var string|string[] */
- return \preg_replace(\array_keys($values), \array_values($values), $subject);
+ return \preg_replace(\array_keys($values), \array_values($values), $subject, $limit);
}
/**
diff --git a/src/Word/HtmlWordParser.php b/src/Word/HtmlWordParser.php
index 0079fdec0..2f4163584 100644
--- a/src/Word/HtmlWordParser.php
+++ b/src/Word/HtmlWordParser.php
@@ -183,8 +183,9 @@ private function parseBorders(string $class): string
*/
private function parseMargins(string $class): string
{
- if (1 === \preg_match_all(self::MARGINS_PATTERN, $class, $matches, \PREG_SET_ORDER)) {
- $value = match ((int) $matches[0][3]) {
+ if (StringUtils::pregMatchAll(self::MARGINS_PATTERN, $class, $matches, \PREG_SET_ORDER)) {
+ $match = $matches[0];
+ $value = match ((int) $match[3]) {
1 => '4px', // 0.25rem
2 => '8px', // 0.5rem
3 => '16px', // 1.0rem
@@ -193,7 +194,7 @@ private function parseMargins(string $class): string
default => '0',
};
- return match ($matches[0][1]) {
+ return match ($match[1]) {
't' => \sprintf('margin-top:%s;', $value),
'b' => \sprintf('margin-bottom:%s;', $value),
's' => \sprintf('margin-left:%s;', $value),
diff --git a/tests/Controller/AjaxControllerTest.php b/tests/Controller/AjaxControllerTest.php
index 21ab11c7f..906119f35 100644
--- a/tests/Controller/AjaxControllerTest.php
+++ b/tests/Controller/AjaxControllerTest.php
@@ -79,6 +79,16 @@ public function testComputeTaskNegativeItems(): void
$this->checkTaskRequest($parameters, Response::HTTP_BAD_REQUEST);
}
+ public function testComputeTaskNoFound(): void
+ {
+ $parameters = [
+ 'id' => 1_000_000,
+ 'quantity' => 1.0,
+ 'items' => [1],
+ ];
+ $this->checkTaskRequest($parameters, Response::HTTP_OK);
+ }
+
public function testComputeTaskQuantityEqualZero(): void
{
$parameters = [
diff --git a/tests/Twig/Fixtures/PregExtension/preg_function.test b/tests/Twig/Fixtures/PregExtension/preg_function.test
deleted file mode 100644
index e4e60e4c1..000000000
--- a/tests/Twig/Fixtures/PregExtension/preg_function.test
+++ /dev/null
@@ -1,30 +0,0 @@
---TEST--
-"preg_extension" function test
---TEMPLATE--
-{{ array_values|preg_filter('/\\d/', 'A:$0')|length }}
-{{ array_values|preg_grep('/\\d/')|length }}
-{{ '1'|preg_match('/\\d/') ? 'ok' : 'ko' }}
-{{ 'A'|preg_match('/\\d/') ? 'ok' : 'ko' }}
-{{ null_values|preg_match('/\\d/') ? 'ok' : 'ko' }}
-{{ '$40'|preg_quote() }}
-{{ '1'|preg_replace('/\\d/', '2') }}
-{{ 'hypertext language, programming'|preg_split('/[\\s,]+/')|length }}
-{{ null_values|preg_grep('/\\d/') }}
-{{ null_values|preg_filter('/\\d/', 'A:$0') }}
-{{ null_values|preg_replace('/\\d/', '2') }}
-{{ null_values|preg_split('/[\\s,]+/') }}
-{{ null_values|preg_quote() }}
---DATA--
-return [
- 'array_values' => ['1', '2', '3', '4', 'a', 'b', 'A', 'B'],
- 'null_values' => null,
-]
---EXPECT--
-4
-4
-ok
-ko
-ko
-\$40
-2
-3
diff --git a/tests/Twig/PhpExtensionTest.php b/tests/Twig/PhpExtensionTest.php
deleted file mode 100644
index 6ac19681a..000000000
--- a/tests/Twig/PhpExtensionTest.php
+++ /dev/null
@@ -1,28 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-declare(strict_types=1);
-
-namespace App\Tests\Twig;
-
-use App\Twig\PhpExtension;
-
-class PhpExtensionTest extends IntegrationTestCase
-{
- protected function getExtensions(): array
- {
- return [new PhpExtension()];
- }
-
- protected function getFixturesDir(): string
- {
- return __DIR__ . '/Fixtures/PhpExtension';
- }
-}
diff --git a/tests/Twig/PregExtensionTest.php b/tests/Twig/PregExtensionTest.php
deleted file mode 100644
index d3691baff..000000000
--- a/tests/Twig/PregExtensionTest.php
+++ /dev/null
@@ -1,28 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-declare(strict_types=1);
-
-namespace App\Tests\Twig;
-
-use App\Twig\PregExtension;
-
-class PregExtensionTest extends IntegrationTestCase
-{
- protected function getExtensions(): array
- {
- return [new PregExtension()];
- }
-
- protected function getFixturesDir(): string
- {
- return __DIR__ . '/Fixtures/PregExtension';
- }
-}
diff --git a/tests/Utils/StringUtilsTest.php b/tests/Utils/StringUtilsTest.php
index d4d84e620..c301bc1dc 100644
--- a/tests/Utils/StringUtilsTest.php
+++ b/tests/Utils/StringUtilsTest.php
@@ -63,6 +63,31 @@ public static function getIsString(): \Iterator
yield ['my home', true];
}
+ public static function getPregMatch(): \Iterator
+ {
+ yield ['/\d+/', '1234', true];
+ yield ['/\d+/', 'FAKE', false];
+ yield ['/(?J)(?foo)|(?bar)/', 'foo bar', true];
+ yield ['/(foo)(bar)(baz)/', 'foobarbaz', true];
+ yield ['/(foo)(bar)(baz)/', 'foobaz', false];
+ }
+
+ public static function getPregMatchAll(): \Iterator
+ {
+ yield ['/\d+/', '1234', true];
+ yield ['/\d+/', 'FAKE', false];
+
+ yield ['/(?J)(?foo)|(?bar)/', 'foo bar', true];
+ yield ['/(foo)(bar)(baz)/', 'foobarbaz', true];
+ yield ['/(foo)(bar)(baz)/', 'foobaz', false];
+ }
+
+ public static function getPregReplace(): \Iterator
+ {
+ yield [['/\d+/' => ''], '1234', ''];
+ yield [['/\d+/' => ''], 'FAKE', 'FAKE'];
+ }
+
public static function getShortName(): \Iterator
{
yield [null, null, true];
@@ -184,6 +209,36 @@ public function testNewLine(): void
self::assertSame("\n", StringUtils::NEW_LINE);
}
+ /**
+ * @psalm-param non-empty-string $pattern
+ */
+ #[DataProvider('getPregMatch')]
+ public function testPregMatch(string $pattern, string $subject, bool $expected): void
+ {
+ $actual = StringUtils::pregMatch($pattern, $subject);
+ self::assertSame($expected, $actual);
+ }
+
+ /**
+ * @psalm-param non-empty-string $pattern
+ */
+ #[DataProvider('getPregMatchAll')]
+ public function testPregMatchAll(string $pattern, string $subject, bool $expected): void
+ {
+ $actual = StringUtils::pregMatchAll($pattern, $subject);
+ self::assertSame($expected, $actual);
+ }
+
+ /**
+ * @psalm-param non-empty-array $values
+ */
+ #[DataProvider('getPregReplace')]
+ public function testPregReplace(array $values, string $subject, string $expected): void
+ {
+ $actual = StringUtils::pregReplace($values, $subject);
+ self::assertSame($expected, $actual);
+ }
+
public function testSlug(): void
{
$actual = StringUtils::slug('Wôrķšƥáçè ~~sèťtïñğš~~');
@@ -197,6 +252,15 @@ public function testStartWith(string $haystack, string $needle, bool $ignore_cas
self::assertSame($expected, $actual);
}
+ public function testUnicode(): void
+ {
+ $actual = StringUtils::unicode('fake')->toString();
+ self::assertSame('fake', $actual);
+
+ $actual = StringUtils::unicode('fake', true)->toString();
+ self::assertSame('fake', $actual);
+ }
+
private static function getVarArray(): string
{
return <<