$fields
*/
public function __construct(array $fields = [])
{
@@ -55,14 +54,14 @@ private function prepareFields(array $fields): array
$prepare = function ($item, $key, $root = null) use (&$values, &$prepare) {
if (null === $root && \is_int($key) && \is_array($item)) {
if (1 !== \count($item)) {
- throw new InvalidArgumentException(sprintf('Form field values with integer keys can only have one array element, the key being the field name and the value being the field value, %d provided.', \count($item)));
+ throw new InvalidArgumentException(\sprintf('Form field values with integer keys can only have one array element, the key being the field name and the value being the field value, %d provided.', \count($item)));
}
$key = key($item);
$item = $item[$key];
}
- $fieldName = null !== $root ? sprintf('%s[%s]', $root, $key) : $key;
+ $fieldName = null !== $root ? \sprintf('%s[%s]', $root, $key) : $key;
if (\is_array($item)) {
array_walk($item, $prepare, $fieldName);
@@ -71,7 +70,7 @@ private function prepareFields(array $fields): array
}
if (!\is_string($item) && !$item instanceof TextPart) {
- throw new InvalidArgumentException(sprintf('The value of the form field "%s" can only be a string, an array, or an instance of TextPart, "%s" given.', $fieldName, get_debug_type($item)));
+ throw new InvalidArgumentException(\sprintf('The value of the form field "%s" can only be a string, an array, or an instance of TextPart, "%s" given.', $fieldName, get_debug_type($item)));
}
$values[] = $this->preparePart($fieldName, $item);
diff --git a/symfony/mime/Part/TextPart.php b/symfony/mime/Part/TextPart.php
index 2a8dd5852..30e3005ff 100644
--- a/symfony/mime/Part/TextPart.php
+++ b/symfony/mime/Part/TextPart.php
@@ -45,13 +45,13 @@ public function __construct($body, ?string $charset = 'utf-8', string $subtype =
parent::__construct();
if (!\is_string($body) && !\is_resource($body) && !$body instanceof File) {
- throw new \TypeError(sprintf('The body of "%s" must be a string, a resource, or an instance of "%s" (got "%s").', self::class, File::class, get_debug_type($body)));
+ throw new \TypeError(\sprintf('The body of "%s" must be a string, a resource, or an instance of "%s" (got "%s").', self::class, File::class, get_debug_type($body)));
}
if ($body instanceof File) {
$path = $body->getPath();
if ((is_file($path) && !is_readable($path)) || is_dir($path)) {
- throw new InvalidArgumentException(sprintf('Path "%s" is not readable.', $path));
+ throw new InvalidArgumentException(\sprintf('Path "%s" is not readable.', $path));
}
}
@@ -64,7 +64,7 @@ public function __construct($body, ?string $charset = 'utf-8', string $subtype =
$this->encoding = $this->chooseEncoding();
} else {
if ('quoted-printable' !== $encoding && 'base64' !== $encoding && '8bit' !== $encoding) {
- throw new InvalidArgumentException(sprintf('The encoding must be one of "quoted-printable", "base64", or "8bit" ("%s" given).', $encoding));
+ throw new InvalidArgumentException(\sprintf('The encoding must be one of "quoted-printable", "base64", or "8bit" ("%s" given).', $encoding));
}
$this->encoding = $encoding;
}
@@ -151,7 +151,7 @@ public function bodyToIterable(): iterable
if ($this->body instanceof File) {
$path = $this->body->getPath();
if (false === $handle = @fopen($path, 'r', false)) {
- throw new InvalidArgumentException(sprintf('Unable to open path "%s".', $path));
+ throw new InvalidArgumentException(\sprintf('Unable to open path "%s".', $path));
}
yield from $this->getEncoder()->encodeByteStream($handle);
diff --git a/symfony/polyfill-intl-grapheme/Grapheme.php b/symfony/polyfill-intl-grapheme/Grapheme.php
index 5373f1685..f9e9e5741 100644
--- a/symfony/polyfill-intl-grapheme/Grapheme.php
+++ b/symfony/polyfill-intl-grapheme/Grapheme.php
@@ -26,6 +26,7 @@
* - grapheme_strrpos - Find position (in grapheme units) of last occurrence of a string
* - grapheme_strstr - Returns part of haystack string from the first occurrence of needle to the end of haystack
* - grapheme_substr - Return part of a string
+ * - grapheme_str_split - Splits a string into an array of individual or chunks of graphemes
*
* @author Nicolas Grekas
*
@@ -191,6 +192,37 @@ public static function grapheme_strstr($s, $needle, $beforeNeedle = false)
return mb_strstr($s, $needle, $beforeNeedle, 'UTF-8');
}
+ public static function grapheme_str_split($s, $len = 1)
+ {
+ if (0 > $len || 1073741823 < $len) {
+ if (80000 > \PHP_VERSION_ID) {
+ return false;
+ }
+
+ throw new \ValueError('grapheme_str_split(): Argument #2 ($length) must be greater than 0 and less than or equal to 1073741823.');
+ }
+
+ if ('' === $s) {
+ return [];
+ }
+
+ if (!preg_match_all('/('.SYMFONY_GRAPHEME_CLUSTER_RX.')/u', $s, $matches)) {
+ return false;
+ }
+
+ if (1 === $len) {
+ return $matches[0];
+ }
+
+ $chunks = array_chunk($matches[0], $len);
+
+ foreach ($chunks as &$chunk) {
+ $chunk = implode('', $chunk);
+ }
+
+ return $chunks;
+ }
+
private static function grapheme_position($s, $needle, $offset, $mode)
{
$needle = (string) $needle;
diff --git a/symfony/polyfill-intl-grapheme/bootstrap.php b/symfony/polyfill-intl-grapheme/bootstrap.php
index a9ea03c7e..374dbd3a7 100644
--- a/symfony/polyfill-intl-grapheme/bootstrap.php
+++ b/symfony/polyfill-intl-grapheme/bootstrap.php
@@ -11,10 +11,6 @@
use Symfony\Polyfill\Intl\Grapheme as p;
-if (extension_loaded('intl')) {
- return;
-}
-
if (\PHP_VERSION_ID >= 80000) {
return require __DIR__.'/bootstrap80.php';
}
@@ -56,3 +52,6 @@ function grapheme_strstr($haystack, $needle, $beforeNeedle = false) { return p\G
if (!function_exists('grapheme_substr')) {
function grapheme_substr($string, $offset, $length = null) { return p\Grapheme::grapheme_substr($string, $offset, $length); }
}
+if (!function_exists('grapheme_str_split')) {
+ function grapheme_str_split($string, $length = 1) { return p\Grapheme::grapheme_str_split($string, $length); }
+}
diff --git a/symfony/polyfill-intl-grapheme/bootstrap80.php b/symfony/polyfill-intl-grapheme/bootstrap80.php
index b8c078677..d71175530 100644
--- a/symfony/polyfill-intl-grapheme/bootstrap80.php
+++ b/symfony/polyfill-intl-grapheme/bootstrap80.php
@@ -11,6 +11,14 @@
use Symfony\Polyfill\Intl\Grapheme as p;
+if (!function_exists('grapheme_str_split')) {
+ function grapheme_str_split(string $string, int $length = 1): array|false { return p\Grapheme::grapheme_str_split($string, $length); }
+}
+
+if (extension_loaded('intl')) {
+ return;
+}
+
if (!defined('GRAPHEME_EXTR_COUNT')) {
define('GRAPHEME_EXTR_COUNT', 0);
}
diff --git a/symfony/polyfill-php83/Php83.php b/symfony/polyfill-php83/Php83.php
index 3d94b6c32..8b7ee4c70 100644
--- a/symfony/polyfill-php83/Php83.php
+++ b/symfony/polyfill-php83/Php83.php
@@ -35,7 +35,7 @@ public static function json_validate(string $json, int $depth = 512, int $flags
throw new \ValueError(sprintf('json_validate(): Argument #2 ($depth) must be less than %d', self::JSON_MAX_DEPTH));
}
- json_decode($json, null, $depth, $flags);
+ json_decode($json, true, $depth, $flags);
return \JSON_ERROR_NONE === json_last_error();
}
diff --git a/symfony/process/Exception/ProcessFailedException.php b/symfony/process/Exception/ProcessFailedException.php
index 19b40570c..29cd386bb 100644
--- a/symfony/process/Exception/ProcessFailedException.php
+++ b/symfony/process/Exception/ProcessFailedException.php
@@ -28,7 +28,7 @@ public function __construct(Process $process)
throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
}
- $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
+ $error = \sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
$process->getCommandLine(),
$process->getExitCode(),
$process->getExitCodeText(),
@@ -36,7 +36,7 @@ public function __construct(Process $process)
);
if (!$process->isOutputDisabled()) {
- $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
+ $error .= \sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
$process->getOutput(),
$process->getErrorOutput()
);
diff --git a/symfony/process/Exception/ProcessSignaledException.php b/symfony/process/Exception/ProcessSignaledException.php
index 0fed8ac30..12eb4b3b8 100644
--- a/symfony/process/Exception/ProcessSignaledException.php
+++ b/symfony/process/Exception/ProcessSignaledException.php
@@ -26,7 +26,7 @@ public function __construct(Process $process)
{
$this->process = $process;
- parent::__construct(sprintf('The process has been signaled with signal "%s".', $process->getTermSignal()));
+ parent::__construct(\sprintf('The process has been signaled with signal "%s".', $process->getTermSignal()));
}
public function getProcess(): Process
diff --git a/symfony/process/Exception/ProcessTimedOutException.php b/symfony/process/Exception/ProcessTimedOutException.php
index 1cecdae75..94c1a33af 100644
--- a/symfony/process/Exception/ProcessTimedOutException.php
+++ b/symfony/process/Exception/ProcessTimedOutException.php
@@ -31,7 +31,7 @@ public function __construct(Process $process, int $timeoutType)
$this->process = $process;
$this->timeoutType = $timeoutType;
- parent::__construct(sprintf(
+ parent::__construct(\sprintf(
'The process "%s" exceeded the timeout of %s seconds.',
$process->getCommandLine(),
$this->getExceededTimeout()
@@ -67,7 +67,7 @@ public function getExceededTimeout(): ?float
return match ($this->timeoutType) {
self::TYPE_GENERAL => $this->process->getTimeout(),
self::TYPE_IDLE => $this->process->getIdleTimeout(),
- default => throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType)),
+ default => throw new \LogicException(\sprintf('Unknown timeout type "%d".', $this->timeoutType)),
};
}
}
diff --git a/symfony/process/ExecutableFinder.php b/symfony/process/ExecutableFinder.php
index 1838d54ba..4d8202621 100644
--- a/symfony/process/ExecutableFinder.php
+++ b/symfony/process/ExecutableFinder.php
@@ -74,7 +74,7 @@ public function find(string $name, ?string $default = null, array $extraDirs = [
$suffixes = $this->suffixes;
$suffixes = array_merge($suffixes, $pathExt ? explode(\PATH_SEPARATOR, $pathExt) : ['.exe', '.bat', '.cmd', '.com']);
}
- $suffixes = '' !== pathinfo($name, PATHINFO_EXTENSION) ? array_merge([''], $suffixes) : array_merge($suffixes, ['']);
+ $suffixes = '' !== pathinfo($name, \PATHINFO_EXTENSION) ? array_merge([''], $suffixes) : array_merge($suffixes, ['']);
foreach ($suffixes as $suffix) {
foreach ($dirs as $dir) {
if ('' === $dir) {
diff --git a/symfony/process/InputStream.php b/symfony/process/InputStream.php
index 931217c85..3bcbfe84d 100644
--- a/symfony/process/InputStream.php
+++ b/symfony/process/InputStream.php
@@ -50,7 +50,7 @@ public function write(mixed $input)
return;
}
if ($this->isClosed()) {
- throw new RuntimeException(sprintf('"%s" is closed.', static::class));
+ throw new RuntimeException(\sprintf('"%s" is closed.', static::class));
}
$this->input[] = ProcessUtils::validateInput(__METHOD__, $input);
}
diff --git a/symfony/process/PhpProcess.php b/symfony/process/PhpProcess.php
index 6e2ab59fb..db6ebf2a2 100644
--- a/symfony/process/PhpProcess.php
+++ b/symfony/process/PhpProcess.php
@@ -52,7 +52,7 @@ public function __construct(string $script, ?string $cwd = null, ?array $env = n
public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, mixed $input = null, ?float $timeout = 60): static
{
- throw new LogicException(sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class));
+ throw new LogicException(\sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class));
}
/**
diff --git a/symfony/process/PhpSubprocess.php b/symfony/process/PhpSubprocess.php
index 04fd8ea87..bdd4173c2 100644
--- a/symfony/process/PhpSubprocess.php
+++ b/symfony/process/PhpSubprocess.php
@@ -75,7 +75,7 @@ public function __construct(array $command, ?string $cwd = null, ?array $env = n
public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, mixed $input = null, ?float $timeout = 60): static
{
- throw new LogicException(sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class));
+ throw new LogicException(\sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class));
}
public function start(?callable $callback = null, array $env = []): void
diff --git a/symfony/process/Pipes/AbstractPipes.php b/symfony/process/Pipes/AbstractPipes.php
index cbbb72770..158f0487f 100644
--- a/symfony/process/Pipes/AbstractPipes.php
+++ b/symfony/process/Pipes/AbstractPipes.php
@@ -52,14 +52,26 @@ public function close(): void
/**
* Returns true if a system call has been interrupted.
+ *
+ * stream_select() returns false when the `select` system call is interrupted by an incoming signal.
*/
protected function hasSystemCallBeenInterrupted(): bool
{
$lastError = $this->lastError;
$this->lastError = null;
- // stream_select returns false when the `select` system call is interrupted by an incoming signal
- return null !== $lastError && false !== stripos($lastError, 'interrupted system call');
+ if (null === $lastError) {
+ return false;
+ }
+
+ if (false !== stripos($lastError, 'interrupted system call')) {
+ return true;
+ }
+
+ // on applications with a different locale than english, the message above is not found because
+ // it's translated. So we also check for the SOCKET_EINTR constant which is defined under
+ // Windows and UNIX-like platforms (if available on the platform).
+ return \defined('SOCKET_EINTR') && str_starts_with($lastError, 'stream_select(): Unable to select ['.\SOCKET_EINTR.']');
}
/**
@@ -72,10 +84,10 @@ protected function unblock(): void
}
foreach ($this->pipes as $pipe) {
- stream_set_blocking($pipe, 0);
+ stream_set_blocking($pipe, false);
}
if (\is_resource($this->input)) {
- stream_set_blocking($this->input, 0);
+ stream_set_blocking($this->input, false);
}
$this->blocked = false;
@@ -97,11 +109,11 @@ protected function write(): ?array
if (!$input->valid()) {
$input = null;
} elseif (\is_resource($input = $input->current())) {
- stream_set_blocking($input, 0);
+ stream_set_blocking($input, false);
} elseif (!isset($this->inputBuffer[0])) {
if (!\is_string($input)) {
if (!\is_scalar($input)) {
- throw new InvalidArgumentException(sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', get_debug_type($this->input), get_debug_type($input)));
+ throw new InvalidArgumentException(\sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', get_debug_type($this->input), get_debug_type($input)));
}
$input = (string) $input;
}
diff --git a/symfony/process/Pipes/UnixPipes.php b/symfony/process/Pipes/UnixPipes.php
index 7bd0db0e9..8838c68af 100644
--- a/symfony/process/Pipes/UnixPipes.php
+++ b/symfony/process/Pipes/UnixPipes.php
@@ -35,12 +35,12 @@ public function __construct(?bool $ttyMode, bool $ptyMode, mixed $input, bool $h
parent::__construct($input);
}
- public function __sleep(): array
+ public function __serialize(): array
{
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
}
- public function __wakeup(): void
+ public function __unserialize(array $data): void
{
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
}
@@ -74,7 +74,7 @@ public function getDescriptors(): array
return [
['pty'],
['pty'],
- ['pty'],
+ ['pipe', 'w'], // stderr needs to be in a pipe to correctly split error and output, since PHP will use the same stream for both
];
}
diff --git a/symfony/process/Pipes/WindowsPipes.php b/symfony/process/Pipes/WindowsPipes.php
index 8033442a4..bec37358c 100644
--- a/symfony/process/Pipes/WindowsPipes.php
+++ b/symfony/process/Pipes/WindowsPipes.php
@@ -53,7 +53,7 @@ public function __construct(mixed $input, bool $haveReadSupport)
set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
for ($i = 0;; ++$i) {
foreach ($pipes as $pipe => $name) {
- $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
+ $file = \sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
if (!$h = fopen($file.'.lock', 'w')) {
if (file_exists($file.'.lock')) {
@@ -88,12 +88,12 @@ public function __construct(mixed $input, bool $haveReadSupport)
parent::__construct($input);
}
- public function __sleep(): array
+ public function __serialize(): array
{
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
}
- public function __wakeup(): void
+ public function __unserialize(array $data): void
{
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
}
diff --git a/symfony/process/Process.php b/symfony/process/Process.php
index 280a732d5..ce730f98e 100644
--- a/symfony/process/Process.php
+++ b/symfony/process/Process.php
@@ -80,7 +80,6 @@ class Process implements \IteratorAggregate
private WindowsPipes|UnixPipes $processPipes;
private ?int $latestSignal = null;
- private ?int $cachedExitCode = null;
private static ?bool $sigchild = null;
@@ -195,15 +194,12 @@ public static function fromShellCommandline(string $command, ?string $cwd = null
return $process;
}
- public function __sleep(): array
+ public function __serialize(): array
{
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
}
- /**
- * @return void
- */
- public function __wakeup()
+ public function __unserialize(array $data): void
{
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
}
@@ -341,7 +337,7 @@ public function start(?callable $callback = null, array $env = [])
}
if (!is_dir($this->cwd)) {
- throw new RuntimeException(sprintf('The provided cwd "%s" does not exist.', $this->cwd));
+ throw new RuntimeException(\sprintf('The provided cwd "%s" does not exist.', $this->cwd));
}
$process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options);
@@ -1198,7 +1194,7 @@ public function setOptions(array $options)
foreach ($options as $key => $value) {
if (!\in_array($key, $existingOptions)) {
$this->options = $defaultOptions;
- throw new LogicException(sprintf('Invalid option "%s" passed to "%s()". Supported options are "%s".', $key, __METHOD__, implode('", "', $existingOptions)));
+ throw new LogicException(\sprintf('Invalid option "%s" passed to "%s()". Supported options are "%s".', $key, __METHOD__, implode('", "', $existingOptions)));
}
$this->options[$key] = $value;
}
@@ -1289,21 +1285,10 @@ protected function updateStatus(bool $blocking)
return;
}
- $this->processInformation = proc_get_status($this->process);
- $running = $this->processInformation['running'];
-
- // In PHP < 8.3, "proc_get_status" only returns the correct exit status on the first call.
- // Subsequent calls return -1 as the process is discarded. This workaround caches the first
- // retrieved exit status for consistent results in later calls, mimicking PHP 8.3 behavior.
- if (\PHP_VERSION_ID < 80300) {
- if (!isset($this->cachedExitCode) && !$running && -1 !== $this->processInformation['exitcode']) {
- $this->cachedExitCode = $this->processInformation['exitcode'];
- }
-
- if (isset($this->cachedExitCode) && !$running && -1 === $this->processInformation['exitcode']) {
- $this->processInformation['exitcode'] = $this->cachedExitCode;
- }
+ if ($this->processInformation['running'] ?? true) {
+ $this->processInformation = proc_get_status($this->process);
}
+ $running = $this->processInformation['running'];
$this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running);
@@ -1465,10 +1450,10 @@ private function doSignal(int $signal, bool $throwException): bool
}
if ('\\' === \DIRECTORY_SEPARATOR) {
- exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
+ exec(\sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
if ($exitCode && $this->isRunning()) {
if ($throwException) {
- throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));
+ throw new RuntimeException(\sprintf('Unable to kill the process (%s).', implode(' ', $output)));
}
return false;
@@ -1478,12 +1463,12 @@ private function doSignal(int $signal, bool $throwException): bool
$ok = @proc_terminate($this->process, $signal);
} elseif (\function_exists('posix_kill')) {
$ok = @posix_kill($pid, $signal);
- } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), [2 => ['pipe', 'w']], $pipes)) {
+ } elseif ($ok = proc_open(\sprintf('kill -%d %d', $signal, $pid), [2 => ['pipe', 'w']], $pipes)) {
$ok = false === fgets($pipes[2]);
}
if (!$ok) {
if ($throwException) {
- throw new RuntimeException(sprintf('Error while sending signal "%s".', $signal));
+ throw new RuntimeException(\sprintf('Error while sending signal "%s".', $signal));
}
return false;
@@ -1540,7 +1525,7 @@ function ($m) use (&$env, $uid) {
if (!$comSpec && $comSpec = (new ExecutableFinder())->find('cmd.exe')) {
// Escape according to CommandLineToArgvW rules
- $comSpec = '"'.preg_replace('{(\\\\*+)"}', '$1$1\"', $comSpec) .'"';
+ $comSpec = '"'.preg_replace('{(\\\\*+)"}', '$1$1\"', $comSpec).'"';
}
$cmd = ($comSpec ?? 'cmd').' /V:ON /E:ON /D /C ('.str_replace("\n", ' ', $cmd).')';
@@ -1559,7 +1544,7 @@ function ($m) use (&$env, $uid) {
private function requireProcessIsStarted(string $functionName): void
{
if (!$this->isStarted()) {
- throw new LogicException(sprintf('Process must be started before calling "%s()".', $functionName));
+ throw new LogicException(\sprintf('Process must be started before calling "%s()".', $functionName));
}
}
@@ -1571,7 +1556,7 @@ private function requireProcessIsStarted(string $functionName): void
private function requireProcessIsTerminated(string $functionName): void
{
if (!$this->isTerminated()) {
- throw new LogicException(sprintf('Process must be terminated before calling "%s()".', $functionName));
+ throw new LogicException(\sprintf('Process must be terminated before calling "%s()".', $functionName));
}
}
@@ -1601,7 +1586,7 @@ private function replacePlaceholders(string $commandline, array $env): string
{
return preg_replace_callback('/"\$\{:([_a-zA-Z]++[_a-zA-Z0-9]*+)\}"/', function ($matches) use ($commandline, $env) {
if (!isset($env[$matches[1]]) || false === $env[$matches[1]]) {
- throw new InvalidArgumentException(sprintf('Command line is missing a value for parameter "%s": ', $matches[1]).$commandline);
+ throw new InvalidArgumentException(\sprintf('Command line is missing a value for parameter "%s": ', $matches[1]).$commandline);
}
return $this->escapeArgument($env[$matches[1]]);
diff --git a/symfony/process/ProcessUtils.php b/symfony/process/ProcessUtils.php
index 092c5ccf7..a2dbde9f7 100644
--- a/symfony/process/ProcessUtils.php
+++ b/symfony/process/ProcessUtils.php
@@ -56,7 +56,7 @@ public static function validateInput(string $caller, mixed $input): mixed
return new \IteratorIterator($input);
}
- throw new InvalidArgumentException(sprintf('"%s" only accepts strings, Traversable objects or stream resources.', $caller));
+ throw new InvalidArgumentException(\sprintf('"%s" only accepts strings, Traversable objects or stream resources.', $caller));
}
return $input;
diff --git a/symfony/routing/Attribute/Route.php b/symfony/routing/Attribute/Route.php
index a1d86fe61..32ee18e81 100644
--- a/symfony/routing/Attribute/Route.php
+++ b/symfony/routing/Attribute/Route.php
@@ -49,7 +49,7 @@ public function __construct(
?string $format = null,
?bool $utf8 = null,
?bool $stateless = null,
- private ?string $env = null
+ private ?string $env = null,
) {
if (\is_array($path)) {
$this->localizedPaths = $path;
diff --git a/symfony/routing/Exception/MissingMandatoryParametersException.php b/symfony/routing/Exception/MissingMandatoryParametersException.php
index 72d063abb..b64d6d84a 100644
--- a/symfony/routing/Exception/MissingMandatoryParametersException.php
+++ b/symfony/routing/Exception/MissingMandatoryParametersException.php
@@ -31,7 +31,7 @@ public function __construct(string $routeName = '', $missingParameters = null, $
if (\is_array($missingParameters)) {
$this->routeName = $routeName;
$this->missingParameters = $missingParameters;
- $message = sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', $missingParameters), $routeName);
+ $message = \sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', $missingParameters), $routeName);
} else {
trigger_deprecation('symfony/routing', '6.1', 'Construction of "%s" with an exception message is deprecated, provide the route name and an array of missing parameters instead.', __CLASS__);
$message = $routeName;
diff --git a/symfony/routing/Exception/RouteCircularReferenceException.php b/symfony/routing/Exception/RouteCircularReferenceException.php
index 841e35989..3e20cbcbf 100644
--- a/symfony/routing/Exception/RouteCircularReferenceException.php
+++ b/symfony/routing/Exception/RouteCircularReferenceException.php
@@ -15,6 +15,6 @@ class RouteCircularReferenceException extends RuntimeException
{
public function __construct(string $routeId, array $path)
{
- parent::__construct(sprintf('Circular reference detected for route "%s", path: "%s".', $routeId, implode(' -> ', $path)));
+ parent::__construct(\sprintf('Circular reference detected for route "%s", path: "%s".', $routeId, implode(' -> ', $path)));
}
}
diff --git a/symfony/routing/Generator/CompiledUrlGenerator.php b/symfony/routing/Generator/CompiledUrlGenerator.php
index de209cdcf..b7429d1fd 100644
--- a/symfony/routing/Generator/CompiledUrlGenerator.php
+++ b/symfony/routing/Generator/CompiledUrlGenerator.php
@@ -47,7 +47,7 @@ public function generate(string $name, array $parameters = [], int $referenceTyp
}
if (!isset($this->compiledRoutes[$name])) {
- throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
+ throw new RouteNotFoundException(\sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
}
[$variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes, $deprecations] = $this->compiledRoutes[$name] + [6 => []];
diff --git a/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php b/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php
index 1144fed5c..555c5bfbd 100644
--- a/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php
+++ b/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php
@@ -69,7 +69,7 @@ public function getCompiledAliases(): array
}
if (null === $target = $routes->get($currentId)) {
- throw new RouteNotFoundException(sprintf('Target route "%s" for alias "%s" does not exist.', $currentId, $name));
+ throw new RouteNotFoundException(\sprintf('Target route "%s" for alias "%s" does not exist.', $currentId, $name));
}
$compiledTarget = $target->compile();
@@ -109,11 +109,11 @@ private function generateDeclaredRoutes(): string
{
$routes = '';
foreach ($this->getCompiledRoutes() as $name => $properties) {
- $routes .= sprintf("\n '%s' => %s,", $name, CompiledUrlMatcherDumper::export($properties));
+ $routes .= \sprintf("\n '%s' => %s,", $name, CompiledUrlMatcherDumper::export($properties));
}
foreach ($this->getCompiledAliases() as $alias => $properties) {
- $routes .= sprintf("\n '%s' => %s,", $alias, CompiledUrlMatcherDumper::export($properties));
+ $routes .= \sprintf("\n '%s' => %s,", $alias, CompiledUrlMatcherDumper::export($properties));
}
return $routes;
diff --git a/symfony/routing/Generator/UrlGenerator.php b/symfony/routing/Generator/UrlGenerator.php
index 28f30d617..4c8f8f74c 100644
--- a/symfony/routing/Generator/UrlGenerator.php
+++ b/symfony/routing/Generator/UrlGenerator.php
@@ -131,7 +131,7 @@ public function generate(string $name, array $parameters = [], int $referenceTyp
}
if (null === $route ??= $this->routes->get($name)) {
- throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
+ throw new RouteNotFoundException(\sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
}
// the Route has a cache of its own and is not recompiled as long as it does not get modified
diff --git a/symfony/routing/Loader/AttributeClassLoader.php b/symfony/routing/Loader/AttributeClassLoader.php
index 132da8028..6506feae1 100644
--- a/symfony/routing/Loader/AttributeClassLoader.php
+++ b/symfony/routing/Loader/AttributeClassLoader.php
@@ -94,7 +94,7 @@ public function __construct($env = null)
} elseif ($env instanceof \Stringable || \is_scalar($env)) {
$this->env = (string) $env;
} else {
- throw new \TypeError(__METHOD__.sprintf(': Parameter $env was expected to be a string or null, "%s" given.', get_debug_type($env)));
+ throw new \TypeError(__METHOD__.\sprintf(': Parameter $env was expected to be a string or null, "%s" given.', get_debug_type($env)));
}
}
@@ -114,12 +114,12 @@ public function setRouteAnnotationClass(string $class)
public function load(mixed $class, ?string $type = null): RouteCollection
{
if (!class_exists($class)) {
- throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
+ throw new \InvalidArgumentException(\sprintf('Class "%s" does not exist.', $class));
}
$class = new \ReflectionClass($class);
if ($class->isAbstract()) {
- throw new \InvalidArgumentException(sprintf('Attributes from class "%s" cannot be read as it is abstract.', $class->getName()));
+ throw new \InvalidArgumentException(\sprintf('Attributes from class "%s" cannot be read as it is abstract.', $class->getName()));
}
$this->hasDeprecatedAnnotations = false;
@@ -144,7 +144,7 @@ public function load(mixed $class, ?string $type = null): RouteCollection
if (1 === $collection->count() - \count($routeNamesBefore)) {
$newRouteName = current(array_diff(array_keys($collection->all()), $routeNamesBefore));
- if ($newRouteName !== $aliasName = sprintf('%s::%s', $class->name, $method->name)) {
+ if ($newRouteName !== $aliasName = \sprintf('%s::%s', $class->name, $method->name)) {
$collection->addAlias($aliasName, $newRouteName);
}
}
@@ -162,7 +162,7 @@ public function load(mixed $class, ?string $type = null): RouteCollection
$collection->addAlias($class->name, $invokeRouteName);
}
- if ($invokeRouteName !== $aliasName = sprintf('%s::__invoke', $class->name)) {
+ if ($invokeRouteName !== $aliasName = \sprintf('%s::__invoke', $class->name)) {
$collection->addAlias($aliasName, $invokeRouteName);
}
}
@@ -195,7 +195,7 @@ protected function addRoute(RouteCollection $collection, object $annot, array $g
foreach ($requirements as $placeholder => $requirement) {
if (\is_int($placeholder)) {
- throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s::%s()"?', $placeholder, $requirement, $name, $class->getName(), $method->getName()));
+ throw new \InvalidArgumentException(\sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s::%s()"?', $placeholder, $requirement, $name, $class->getName(), $method->getName()));
}
}
@@ -219,11 +219,11 @@ protected function addRoute(RouteCollection $collection, object $annot, array $g
$paths[$locale] = $prefix.$localePath;
}
} elseif ($missing = array_diff_key($prefix, $path)) {
- throw new \LogicException(sprintf('Route to "%s" is missing paths for locale(s) "%s".', $class->name.'::'.$method->name, implode('", "', array_keys($missing))));
+ throw new \LogicException(\sprintf('Route to "%s" is missing paths for locale(s) "%s".', $class->name.'::'.$method->name, implode('", "', array_keys($missing))));
} else {
foreach ($path as $locale => $localePath) {
if (!isset($prefix[$locale])) {
- throw new \LogicException(sprintf('Route to "%s" with locale "%s" is missing a corresponding prefix in class "%s".', $method->name, $locale, $class->name));
+ throw new \LogicException(\sprintf('Route to "%s" with locale "%s" is missing a corresponding prefix in class "%s".', $method->name, $locale, $class->name));
}
$paths[$locale] = $prefix[$locale].$localePath;
@@ -242,7 +242,7 @@ protected function addRoute(RouteCollection $collection, object $annot, array $g
continue;
}
foreach ($paths as $locale => $path) {
- if (preg_match(sprintf('/\{%s(?:<.*?>)?\}/', preg_quote($param->name)), $path)) {
+ if (preg_match(\sprintf('/\{%s(?:<.*?>)?\}/', preg_quote($param->name)), $path)) {
if (\is_scalar($defaultValue = $param->getDefaultValue()) || null === $defaultValue) {
$defaults[$param->name] = $defaultValue;
} elseif ($defaultValue instanceof \BackedEnum) {
@@ -360,7 +360,7 @@ protected function getGlobals(\ReflectionClass $class)
foreach ($globals['requirements'] as $placeholder => $requirement) {
if (\is_int($placeholder)) {
- throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" in "%s"?', $placeholder, $requirement, $class->getName()));
+ throw new \InvalidArgumentException(\sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" in "%s"?', $placeholder, $requirement, $class->getName()));
}
}
}
diff --git a/symfony/routing/Loader/AttributeFileLoader.php b/symfony/routing/Loader/AttributeFileLoader.php
index e9a13e597..8d522f473 100644
--- a/symfony/routing/Loader/AttributeFileLoader.php
+++ b/symfony/routing/Loader/AttributeFileLoader.php
@@ -82,7 +82,7 @@ protected function findClass(string $file): string|false
$tokens = token_get_all(file_get_contents($file));
if (1 === \count($tokens) && \T_INLINE_HTML === $tokens[0][0]) {
- throw new \InvalidArgumentException(sprintf('The file "%s" does not contain PHP code. Did you forget to add the " true, \T_STRING => true];
diff --git a/symfony/routing/Loader/Configurator/CollectionConfigurator.php b/symfony/routing/Loader/Configurator/CollectionConfigurator.php
index 1abf3bc0c..fe4cab4a2 100644
--- a/symfony/routing/Loader/Configurator/CollectionConfigurator.php
+++ b/symfony/routing/Loader/Configurator/CollectionConfigurator.php
@@ -38,15 +38,12 @@ public function __construct(RouteCollection $parent, string $name, ?self $parent
$this->parentPrefixes = $parentPrefixes;
}
- public function __sleep(): array
+ public function __serialize(): array
{
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
}
- /**
- * @return void
- */
- public function __wakeup()
+ public function __unserialize(array $data): void
{
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
}
@@ -84,11 +81,11 @@ final public function prefix(string|array $prefix): static
if (null === $this->parentPrefixes) {
// no-op
} elseif ($missing = array_diff_key($this->parentPrefixes, $prefix)) {
- throw new \LogicException(sprintf('Collection "%s" is missing prefixes for locale(s) "%s".', $this->name, implode('", "', array_keys($missing))));
+ throw new \LogicException(\sprintf('Collection "%s" is missing prefixes for locale(s) "%s".', $this->name, implode('", "', array_keys($missing))));
} else {
foreach ($prefix as $locale => $localePrefix) {
if (!isset($this->parentPrefixes[$locale])) {
- throw new \LogicException(sprintf('Collection "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $this->name, $locale));
+ throw new \LogicException(\sprintf('Collection "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $this->name, $locale));
}
$prefix[$locale] = $this->parentPrefixes[$locale].$localePrefix;
diff --git a/symfony/routing/Loader/Configurator/ImportConfigurator.php b/symfony/routing/Loader/Configurator/ImportConfigurator.php
index 9c92a7d72..ad0c6d131 100644
--- a/symfony/routing/Loader/Configurator/ImportConfigurator.php
+++ b/symfony/routing/Loader/Configurator/ImportConfigurator.php
@@ -30,15 +30,12 @@ public function __construct(RouteCollection $parent, RouteCollection $route)
$this->route = $route;
}
- public function __sleep(): array
+ public function __serialize(): array
{
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
}
- /**
- * @return void
- */
- public function __wakeup()
+ public function __unserialize(array $data): void
{
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
}
diff --git a/symfony/routing/Loader/Configurator/RouteConfigurator.php b/symfony/routing/Loader/Configurator/RouteConfigurator.php
index d9d441da1..26a2e3857 100644
--- a/symfony/routing/Loader/Configurator/RouteConfigurator.php
+++ b/symfony/routing/Loader/Configurator/RouteConfigurator.php
@@ -42,7 +42,14 @@ public function __construct(RouteCollection $collection, RouteCollection $route,
*/
final public function host(string|array $host): static
{
+ $previousRoutes = clone $this->route;
$this->addHost($this->route, $host);
+ foreach ($previousRoutes as $name => $route) {
+ if (!$this->route->get($name)) {
+ $this->collection->remove($name);
+ }
+ }
+ $this->collection->addCollection($this->route);
return $this;
}
diff --git a/symfony/routing/Loader/Configurator/Traits/HostTrait.php b/symfony/routing/Loader/Configurator/Traits/HostTrait.php
index d275f6c67..e584f356f 100644
--- a/symfony/routing/Loader/Configurator/Traits/HostTrait.php
+++ b/symfony/routing/Loader/Configurator/Traits/HostTrait.php
@@ -28,6 +28,7 @@ final protected function addHost(RouteCollection $routes, string|array $hosts):
foreach ($routes->all() as $name => $route) {
if (null === $locale = $route->getDefault('_locale')) {
+ $priority = $routes->getPriority($name) ?? 0;
$routes->remove($name);
foreach ($hosts as $locale => $host) {
$localizedRoute = clone $route;
@@ -35,14 +36,14 @@ final protected function addHost(RouteCollection $routes, string|array $hosts):
$localizedRoute->setRequirement('_locale', preg_quote($locale));
$localizedRoute->setDefault('_canonical_route', $name);
$localizedRoute->setHost($host);
- $routes->add($name.'.'.$locale, $localizedRoute);
+ $routes->add($name.'.'.$locale, $localizedRoute, $priority);
}
} elseif (!isset($hosts[$locale])) {
- throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding host in its parent collection.', $name, $locale));
+ throw new \InvalidArgumentException(\sprintf('Route "%s" with locale "%s" is missing a corresponding host in its parent collection.', $name, $locale));
} else {
$route->setHost($hosts[$locale]);
$route->setRequirement('_locale', preg_quote($locale));
- $routes->add($name, $route);
+ $routes->add($name, $route, $routes->getPriority($name) ?? 0);
}
}
}
diff --git a/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php b/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php
index a26a73420..d90ef9d36 100644
--- a/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php
+++ b/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php
@@ -37,11 +37,11 @@ final protected function createLocalizedRoute(RouteCollection $collection, strin
if (null === $prefixes) {
$paths = $path;
} elseif ($missing = array_diff_key($prefixes, $path)) {
- throw new \LogicException(sprintf('Route "%s" is missing routes for locale(s) "%s".', $name, implode('", "', array_keys($missing))));
+ throw new \LogicException(\sprintf('Route "%s" is missing routes for locale(s) "%s".', $name, implode('", "', array_keys($missing))));
} else {
foreach ($path as $locale => $localePath) {
if (!isset($prefixes[$locale])) {
- throw new \LogicException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale));
+ throw new \LogicException(\sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale));
}
$paths[$locale] = $prefixes[$locale].$localePath;
diff --git a/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php b/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php
index 89a65d8f7..9f2284c5c 100644
--- a/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php
+++ b/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php
@@ -27,10 +27,17 @@ final protected function addPrefix(RouteCollection $routes, string|array $prefix
foreach ($prefix as $locale => $localePrefix) {
$prefix[$locale] = trim(trim($localePrefix), '/');
}
+ $aliases = [];
+ foreach ($routes->getAliases() as $name => $alias) {
+ $aliases[$alias->getId()][] = $name;
+ }
foreach ($routes->all() as $name => $route) {
if (null === $locale = $route->getDefault('_locale')) {
$priority = $routes->getPriority($name) ?? 0;
$routes->remove($name);
+ foreach ($aliases[$name] ?? [] as $aliasName) {
+ $routes->remove($aliasName);
+ }
foreach ($prefix as $locale => $localePrefix) {
$localizedRoute = clone $route;
$localizedRoute->setDefault('_locale', $locale);
@@ -38,9 +45,12 @@ final protected function addPrefix(RouteCollection $routes, string|array $prefix
$localizedRoute->setDefault('_canonical_route', $name);
$localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
$routes->add($name.'.'.$locale, $localizedRoute, $priority);
+ foreach ($aliases[$name] ?? [] as $aliasName) {
+ $routes->addAlias($aliasName.'.'.$locale, $name.'.'.$locale);
+ }
}
} elseif (!isset($prefix[$locale])) {
- throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale));
+ throw new \InvalidArgumentException(\sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale));
} else {
$route->setPath($prefix[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
$routes->add($name, $route, $routes->getPriority($name) ?? 0);
diff --git a/symfony/routing/Loader/ObjectLoader.php b/symfony/routing/Loader/ObjectLoader.php
index c2ad6a03f..d4234c135 100644
--- a/symfony/routing/Loader/ObjectLoader.php
+++ b/symfony/routing/Loader/ObjectLoader.php
@@ -36,7 +36,7 @@ abstract protected function getObject(string $id): object;
public function load(mixed $resource, ?string $type = null): RouteCollection
{
if (!preg_match('/^[^\:]+(?:::(?:[^\:]+))?$/', $resource)) {
- throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the %s route loader: use the format "object_id::method" or "object_id" if your object class has an "__invoke" method.', $resource, \is_string($type) ? '"'.$type.'"' : 'object'));
+ throw new \InvalidArgumentException(\sprintf('Invalid resource "%s" passed to the %s route loader: use the format "object_id::method" or "object_id" if your object class has an "__invoke" method.', $resource, \is_string($type) ? '"'.$type.'"' : 'object'));
}
$parts = explode('::', $resource);
@@ -45,11 +45,11 @@ public function load(mixed $resource, ?string $type = null): RouteCollection
$loaderObject = $this->getObject($parts[0]);
if (!\is_object($loaderObject)) {
- throw new \TypeError(sprintf('"%s:getObject()" must return an object: "%s" returned.', static::class, get_debug_type($loaderObject)));
+ throw new \TypeError(\sprintf('"%s:getObject()" must return an object: "%s" returned.', static::class, get_debug_type($loaderObject)));
}
if (!\is_callable([$loaderObject, $method])) {
- throw new \BadMethodCallException(sprintf('Method "%s" not found on "%s" when importing routing resource "%s".', $method, get_debug_type($loaderObject), $resource));
+ throw new \BadMethodCallException(\sprintf('Method "%s" not found on "%s" when importing routing resource "%s".', $method, get_debug_type($loaderObject), $resource));
}
$routeCollection = $loaderObject->$method($this, $this->env);
@@ -57,7 +57,7 @@ public function load(mixed $resource, ?string $type = null): RouteCollection
if (!$routeCollection instanceof RouteCollection) {
$type = get_debug_type($routeCollection);
- throw new \LogicException(sprintf('The "%s::%s()" method must return a RouteCollection: "%s" returned.', get_debug_type($loaderObject), $method, $type));
+ throw new \LogicException(\sprintf('The "%s::%s()" method must return a RouteCollection: "%s" returned.', get_debug_type($loaderObject), $method, $type));
}
// make the object file tracked so that if it changes, the cache rebuilds
diff --git a/symfony/routing/Loader/XmlFileLoader.php b/symfony/routing/Loader/XmlFileLoader.php
index 2518161ae..5b41bd698 100644
--- a/symfony/routing/Loader/XmlFileLoader.php
+++ b/symfony/routing/Loader/XmlFileLoader.php
@@ -90,7 +90,7 @@ protected function parseNode(RouteCollection $collection, \DOMElement $node, str
}
break;
default:
- throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path));
+ throw new \InvalidArgumentException(\sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path));
}
}
@@ -109,7 +109,7 @@ public function supports(mixed $resource, ?string $type = null): bool
protected function parseRoute(RouteCollection $collection, \DOMElement $node, string $path)
{
if ('' === $id = $node->getAttribute('id')) {
- throw new \InvalidArgumentException(sprintf('The element in file "%s" must have an "id" attribute.', $path));
+ throw new \InvalidArgumentException(\sprintf('The element in file "%s" must have an "id" attribute.', $path));
}
if ('' !== $alias = $node->getAttribute('alias')) {
@@ -128,14 +128,14 @@ protected function parseRoute(RouteCollection $collection, \DOMElement $node, st
[$defaults, $requirements, $options, $condition, $paths, /* $prefixes */, $hosts] = $this->parseConfigs($node, $path);
if (!$paths && '' === $node->getAttribute('path')) {
- throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "path" attribute or child nodes.', $path));
+ throw new \InvalidArgumentException(\sprintf('The element in file "%s" must have a "path" attribute or child nodes.', $path));
}
if ($paths && '' !== $node->getAttribute('path')) {
- throw new \InvalidArgumentException(sprintf('The element in file "%s" must not have both a "path" attribute and child nodes.', $path));
+ throw new \InvalidArgumentException(\sprintf('The element in file "%s" must not have both a "path" attribute and child nodes.', $path));
}
- $routes = $this->createLocalizedRoute($collection, $id, $paths ?: $node->getAttribute('path'));
+ $routes = $this->createLocalizedRoute(new RouteCollection(), $id, $paths ?: $node->getAttribute('path'));
$routes->addDefaults($defaults);
$routes->addRequirements($requirements);
$routes->addOptions($options);
@@ -146,6 +146,8 @@ protected function parseRoute(RouteCollection $collection, \DOMElement $node, st
if (null !== $hosts) {
$this->addHost($routes, $hosts);
}
+
+ $collection->addCollection($routes);
}
/**
@@ -167,7 +169,7 @@ protected function parseImport(RouteCollection $collection, \DOMElement $node, s
}
if (!$resource) {
- throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "resource" attribute or element.', $path));
+ throw new \InvalidArgumentException(\sprintf('The element in file "%s" must have a "resource" attribute or element.', $path));
}
$type = $node->getAttribute('type');
@@ -180,7 +182,7 @@ protected function parseImport(RouteCollection $collection, \DOMElement $node, s
[$defaults, $requirements, $options, $condition, /* $paths */, $prefixes, $hosts] = $this->parseConfigs($node, $path);
if ('' !== $prefix && $prefixes) {
- throw new \InvalidArgumentException(sprintf('The element in file "%s" must not have both a "prefix" attribute and child nodes.', $path));
+ throw new \InvalidArgumentException(\sprintf('The element in file "%s" must not have both a "prefix" attribute and child nodes.', $path));
}
$exclude = [];
@@ -294,15 +296,15 @@ private function parseConfigs(\DOMElement $node, string $path): array
case 'resource':
break;
default:
- throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path));
+ throw new \InvalidArgumentException(\sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path));
}
}
if ($controller = $node->getAttribute('controller')) {
if (isset($defaults['_controller'])) {
- $name = $node->hasAttribute('id') ? sprintf('"%s".', $node->getAttribute('id')) : sprintf('the "%s" tag.', $node->tagName);
+ $name = $node->hasAttribute('id') ? \sprintf('"%s".', $node->getAttribute('id')) : \sprintf('the "%s" tag.', $node->tagName);
- throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for ', $path).$name);
+ throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for ', $path).$name);
}
$defaults['_controller'] = $controller;
@@ -318,9 +320,9 @@ private function parseConfigs(\DOMElement $node, string $path): array
}
if ($stateless = $node->getAttribute('stateless')) {
if (isset($defaults['_stateless'])) {
- $name = $node->hasAttribute('id') ? sprintf('"%s".', $node->getAttribute('id')) : sprintf('the "%s" tag.', $node->tagName);
+ $name = $node->hasAttribute('id') ? \sprintf('"%s".', $node->getAttribute('id')) : \sprintf('the "%s" tag.', $node->tagName);
- throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "stateless" attribute and the defaults key "_stateless" for ', $path).$name);
+ throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "stateless" attribute and the defaults key "_stateless" for ', $path).$name);
}
$defaults['_stateless'] = XmlUtils::phpize($stateless);
@@ -416,7 +418,7 @@ private function parseDefaultNode(\DOMElement $node, string $path): array|bool|f
return $map;
default:
- throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "bool", "int", "float", "string", "list", or "map".', $node->localName, $path));
+ throw new \InvalidArgumentException(\sprintf('Unknown tag "%s" used in file "%s". Expected "bool", "int", "float", "string", "list", or "map".', $node->localName, $path));
}
}
@@ -444,7 +446,7 @@ private function parseDeprecation(\DOMElement $node, string $path): array
continue;
}
if ('deprecated' !== $child->localName) {
- throw new \InvalidArgumentException(sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $node->getAttribute('id'), $path));
+ throw new \InvalidArgumentException(\sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $node->getAttribute('id'), $path));
}
$deprecatedNode = $child;
@@ -455,10 +457,10 @@ private function parseDeprecation(\DOMElement $node, string $path): array
}
if (!$deprecatedNode->hasAttribute('package')) {
- throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "package" attribute.', $path));
+ throw new \InvalidArgumentException(\sprintf('The element in file "%s" must have a "package" attribute.', $path));
}
if (!$deprecatedNode->hasAttribute('version')) {
- throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "version" attribute.', $path));
+ throw new \InvalidArgumentException(\sprintf('The element in file "%s" must have a "version" attribute.', $path));
}
return [
diff --git a/symfony/routing/Loader/YamlFileLoader.php b/symfony/routing/Loader/YamlFileLoader.php
index 9605e9a87..c1924ba65 100644
--- a/symfony/routing/Loader/YamlFileLoader.php
+++ b/symfony/routing/Loader/YamlFileLoader.php
@@ -46,11 +46,11 @@ public function load(mixed $file, ?string $type = null): RouteCollection
$path = $this->locator->locate($file);
if (!stream_is_local($path)) {
- throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $path));
+ throw new \InvalidArgumentException(\sprintf('This is not a local file "%s".', $path));
}
if (!file_exists($path)) {
- throw new \InvalidArgumentException(sprintf('File "%s" not found.', $path));
+ throw new \InvalidArgumentException(\sprintf('File "%s" not found.', $path));
}
$this->yamlParser ??= new YamlParser();
@@ -58,7 +58,7 @@ public function load(mixed $file, ?string $type = null): RouteCollection
try {
$parsedConfig = $this->yamlParser->parseFile($path, Yaml::PARSE_CONSTANT);
} catch (ParseException $e) {
- throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML: ', $path).$e->getMessage(), 0, $e);
+ throw new \InvalidArgumentException(\sprintf('The file "%s" does not contain valid YAML: ', $path).$e->getMessage(), 0, $e);
}
$collection = new RouteCollection();
@@ -71,7 +71,7 @@ public function load(mixed $file, ?string $type = null): RouteCollection
// not an array
if (!\is_array($parsedConfig)) {
- throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path));
+ throw new \InvalidArgumentException(\sprintf('The file "%s" must contain a YAML array.', $path));
}
foreach ($parsedConfig as $name => $config) {
@@ -137,7 +137,7 @@ protected function parseRoute(RouteCollection $collection, string $name, array $
foreach ($requirements as $placeholder => $requirement) {
if (\is_int($placeholder)) {
- throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s"?', $placeholder, $requirement, $name, $path));
+ throw new \InvalidArgumentException(\sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s"?', $placeholder, $requirement, $name, $path));
}
}
@@ -157,7 +157,7 @@ protected function parseRoute(RouteCollection $collection, string $name, array $
$defaults['_stateless'] = $config['stateless'];
}
- $routes = $this->createLocalizedRoute($collection, $name, $config['path']);
+ $routes = $this->createLocalizedRoute(new RouteCollection(), $name, $config['path']);
$routes->addDefaults($defaults);
$routes->addRequirements($requirements);
$routes->addOptions($options);
@@ -168,6 +168,8 @@ protected function parseRoute(RouteCollection $collection, string $name, array $
if (isset($config['host'])) {
$this->addHost($routes, $config['host']);
}
+
+ $collection->addCollection($routes);
}
/**
@@ -250,7 +252,7 @@ protected function parseImport(RouteCollection $collection, array $config, strin
protected function validate(mixed $config, string $name, string $path)
{
if (!\is_array($config)) {
- throw new \InvalidArgumentException(sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path));
+ throw new \InvalidArgumentException(\sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path));
}
if (isset($config['alias'])) {
$this->validateAlias($config, $name, $path);
@@ -258,22 +260,22 @@ protected function validate(mixed $config, string $name, string $path)
return;
}
if ($extraKeys = array_diff(array_keys($config), self::AVAILABLE_KEYS)) {
- throw new \InvalidArgumentException(sprintf('The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', $path, $name, implode('", "', $extraKeys), implode('", "', self::AVAILABLE_KEYS)));
+ throw new \InvalidArgumentException(\sprintf('The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', $path, $name, implode('", "', $extraKeys), implode('", "', self::AVAILABLE_KEYS)));
}
if (isset($config['resource']) && isset($config['path'])) {
- throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', $path, $name));
+ throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', $path, $name));
}
if (!isset($config['resource']) && isset($config['type'])) {
- throw new \InvalidArgumentException(sprintf('The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', $name, $path));
+ throw new \InvalidArgumentException(\sprintf('The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', $name, $path));
}
if (!isset($config['resource']) && !isset($config['path'])) {
- throw new \InvalidArgumentException(sprintf('You must define a "path" for the route "%s" in file "%s".', $name, $path));
+ throw new \InvalidArgumentException(\sprintf('You must define a "path" for the route "%s" in file "%s".', $name, $path));
}
if (isset($config['controller']) && isset($config['defaults']['_controller'])) {
- throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name));
+ throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name));
}
if (isset($config['stateless']) && isset($config['defaults']['_stateless'])) {
- throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "stateless" key and the defaults key "_stateless" for "%s".', $path, $name));
+ throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "stateless" key and the defaults key "_stateless" for "%s".', $path, $name));
}
}
@@ -285,16 +287,16 @@ private function validateAlias(array $config, string $name, string $path): void
{
foreach ($config as $key => $value) {
if (!\in_array($key, ['alias', 'deprecated'], true)) {
- throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify other keys than "alias" and "deprecated" for "%s".', $path, $name));
+ throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify other keys than "alias" and "deprecated" for "%s".', $path, $name));
}
if ('deprecated' === $key) {
if (!isset($value['package'])) {
- throw new \InvalidArgumentException(sprintf('The routing file "%s" must specify the attribute "package" of the "deprecated" option for "%s".', $path, $name));
+ throw new \InvalidArgumentException(\sprintf('The routing file "%s" must specify the attribute "package" of the "deprecated" option for "%s".', $path, $name));
}
if (!isset($value['version'])) {
- throw new \InvalidArgumentException(sprintf('The routing file "%s" must specify the attribute "version" of the "deprecated" option for "%s".', $path, $name));
+ throw new \InvalidArgumentException(\sprintf('The routing file "%s" must specify the attribute "version" of the "deprecated" option for "%s".', $path, $name));
}
}
}
diff --git a/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php b/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php
index a7639cd4c..f71264ce9 100644
--- a/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php
+++ b/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php
@@ -137,7 +137,7 @@ private function generateCompiledRoutes(): string
$code .= '[ // $staticRoutes'."\n";
foreach ($staticRoutes as $path => $routes) {
- $code .= sprintf(" %s => [\n", self::export($path));
+ $code .= \sprintf(" %s => [\n", self::export($path));
foreach ($routes as $route) {
$code .= vsprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", array_map([__CLASS__, 'export'], $route));
}
@@ -145,11 +145,11 @@ private function generateCompiledRoutes(): string
}
$code .= "],\n";
- $code .= sprintf("[ // \$regexpList%s\n],\n", $regexpCode);
+ $code .= \sprintf("[ // \$regexpList%s\n],\n", $regexpCode);
$code .= '[ // $dynamicRoutes'."\n";
foreach ($dynamicRoutes as $path => $routes) {
- $code .= sprintf(" %s => [\n", self::export($path));
+ $code .= \sprintf(" %s => [\n", self::export($path));
foreach ($routes as $route) {
$code .= vsprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", array_map([__CLASS__, 'export'], $route));
}
@@ -222,7 +222,12 @@ private function compileStaticRoutes(array $staticRoutes, array &$conditions): a
foreach ($staticRoutes as $url => $routes) {
$compiledRoutes[$url] = [];
foreach ($routes as $name => [$route, $hasTrailingSlash]) {
- $compiledRoutes[$url][] = $this->compileRoute($route, $name, (!$route->compile()->getHostVariables() ? $route->getHost() : $route->compile()->getHostRegex()) ?: null, $hasTrailingSlash, false, $conditions);
+ if ($route->compile()->getHostVariables()) {
+ $host = $route->compile()->getHostRegex();
+ } elseif ($host = $route->getHost()) {
+ $host = strtolower($host);
+ }
+ $compiledRoutes[$url][] = $this->compileRoute($route, $name, $host ?: null, $hasTrailingSlash, false, $conditions);
}
}
@@ -402,7 +407,7 @@ private function compileStaticPrefixCollection(StaticPrefixCollection $tree, \st
$state->mark += 3 + $state->markTail + \strlen($regex) - $prefixLen;
$state->markTail = 2 + \strlen($state->mark);
- $rx = sprintf('|%s(*:%s)', substr($regex, $prefixLen), $state->mark);
+ $rx = \sprintf('|%s(*:%s)', substr($regex, $prefixLen), $state->mark);
$code .= "\n .".self::export($rx);
$state->regex .= $rx;
diff --git a/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php b/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php
index 50abf4587..5177c269a 100644
--- a/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php
+++ b/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php
@@ -42,7 +42,7 @@ public function match(string $pathinfo): array
throw new MethodNotAllowedException(array_keys($allow));
}
if (!$this instanceof RedirectableUrlMatcherInterface) {
- throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo));
+ throw new ResourceNotFoundException(\sprintf('No routes found for "%s".', $pathinfo));
}
if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], true)) {
// no-op
@@ -57,7 +57,7 @@ public function match(string $pathinfo): array
} finally {
$this->context->setScheme($scheme);
}
- } elseif ('/' !== $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') {
+ } elseif ('' !== $trimmedPathinfo = rtrim($pathinfo, '/')) {
$pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo.'/' : $trimmedPathinfo;
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
return $this->redirect($pathinfo, $ret['_route']) + $ret;
@@ -67,14 +67,14 @@ public function match(string $pathinfo): array
}
}
- throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo));
+ throw new ResourceNotFoundException(\sprintf('No routes found for "%s".', $pathinfo));
}
private function doMatch(string $pathinfo, array &$allow = [], array &$allowSchemes = []): array
{
$allow = $allowSchemes = [];
- $pathinfo = rawurldecode($pathinfo) ?: '/';
- $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/';
+ $pathinfo = '' === ($pathinfo = rawurldecode($pathinfo)) ? '/' : $pathinfo;
+ $trimmedPathinfo = '' === ($trimmedPathinfo = rtrim($pathinfo, '/')) ? '/' : $trimmedPathinfo;
$context = $this->context;
$requestMethod = $canonicalMethod = $context->getMethod();
diff --git a/symfony/routing/Matcher/ExpressionLanguageProvider.php b/symfony/routing/Matcher/ExpressionLanguageProvider.php
index 3aeebe699..a910a07a2 100644
--- a/symfony/routing/Matcher/ExpressionLanguageProvider.php
+++ b/symfony/routing/Matcher/ExpressionLanguageProvider.php
@@ -36,7 +36,7 @@ public function getFunctions(): array
foreach ($this->functions->getProvidedServices() as $function => $type) {
$functions[] = new ExpressionFunction(
$function,
- static fn (...$args) => sprintf('($context->getParameter(\'_functions\')->get(%s)(%s))', var_export($function, true), implode(', ', $args)),
+ static fn (...$args) => \sprintf('($context->getParameter(\'_functions\')->get(%s)(%s))', var_export($function, true), implode(', ', $args)),
fn ($values, ...$args) => $values['context']->getParameter('_functions')->get($function)(...$args)
);
}
diff --git a/symfony/routing/Matcher/RedirectableUrlMatcher.php b/symfony/routing/Matcher/RedirectableUrlMatcher.php
index 8d1ad4f90..3e7b78b5e 100644
--- a/symfony/routing/Matcher/RedirectableUrlMatcher.php
+++ b/symfony/routing/Matcher/RedirectableUrlMatcher.php
@@ -41,7 +41,7 @@ public function match(string $pathinfo): array
} finally {
$this->context->setScheme($scheme);
}
- } elseif ('/' === $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') {
+ } elseif ('' === $trimmedPathinfo = rtrim($pathinfo, '/')) {
throw $e;
} else {
try {
diff --git a/symfony/routing/Matcher/TraceableUrlMatcher.php b/symfony/routing/Matcher/TraceableUrlMatcher.php
index 3c7e24d06..8ff018309 100644
--- a/symfony/routing/Matcher/TraceableUrlMatcher.php
+++ b/symfony/routing/Matcher/TraceableUrlMatcher.php
@@ -63,7 +63,7 @@ protected function matchCollection(string $pathinfo, RouteCollection $routes): a
$method = 'GET';
}
$supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface;
- $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/';
+ $trimmedPathinfo = '' === ($trimmedPathinfo = rtrim($pathinfo, '/')) ? '/' : $trimmedPathinfo;
foreach ($routes as $name => $route) {
$compiledRoute = $route->compile();
@@ -72,7 +72,7 @@ protected function matchCollection(string $pathinfo, RouteCollection $routes): a
// check the static prefix of the URL first. Only use the more expensive preg_match when it matches
if ('' !== $staticPrefix && !str_starts_with($trimmedPathinfo, $staticPrefix)) {
- $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route);
+ $this->addTrace(\sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route);
continue;
}
$regex = $compiledRoute->getRegex();
@@ -86,7 +86,7 @@ protected function matchCollection(string $pathinfo, RouteCollection $routes): a
$r = new Route($route->getPath(), $route->getDefaults(), [], $route->getOptions());
$cr = $r->compile();
if (!preg_match($cr->getRegex(), $pathinfo)) {
- $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route);
+ $this->addTrace(\sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route);
continue;
}
@@ -96,7 +96,7 @@ protected function matchCollection(string $pathinfo, RouteCollection $routes): a
$cr = $r->compile();
if (\in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) {
- $this->addTrace(sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route);
+ $this->addTrace(\sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route);
continue 2;
}
@@ -117,7 +117,7 @@ protected function matchCollection(string $pathinfo, RouteCollection $routes): a
$hostMatches = [];
if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) {
- $this->addTrace(sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route);
+ $this->addTrace(\sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route);
continue;
}
@@ -126,7 +126,7 @@ protected function matchCollection(string $pathinfo, RouteCollection $routes): a
$status = $this->handleRouteRequirements($pathinfo, $name, $route, $attributes);
if (self::REQUIREMENT_MISMATCH === $status[0]) {
- $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $route->getCondition()), self::ROUTE_ALMOST_MATCHES, $name, $route);
+ $this->addTrace(\sprintf('Condition "%s" does not evaluate to "true"', $route->getCondition()), self::ROUTE_ALMOST_MATCHES, $name, $route);
continue;
}
@@ -136,19 +136,19 @@ protected function matchCollection(string $pathinfo, RouteCollection $routes): a
return $this->allow = $this->allowSchemes = [];
}
- $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route);
+ $this->addTrace(\sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route);
continue;
}
if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) {
$this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes());
- $this->addTrace(sprintf('Scheme "%s" does not match any of the required schemes (%s)', $this->context->getScheme(), implode(', ', $route->getSchemes())), self::ROUTE_ALMOST_MATCHES, $name, $route);
+ $this->addTrace(\sprintf('Scheme "%s" does not match any of the required schemes (%s)', $this->context->getScheme(), implode(', ', $route->getSchemes())), self::ROUTE_ALMOST_MATCHES, $name, $route);
continue;
}
if ($requiredMethods && !\in_array($method, $requiredMethods)) {
$this->allow = array_merge($this->allow, $requiredMethods);
- $this->addTrace(sprintf('Method "%s" does not match any of the required methods (%s)', $this->context->getMethod(), implode(', ', $requiredMethods)), self::ROUTE_ALMOST_MATCHES, $name, $route);
+ $this->addTrace(\sprintf('Method "%s" does not match any of the required methods (%s)', $this->context->getMethod(), implode(', ', $requiredMethods)), self::ROUTE_ALMOST_MATCHES, $name, $route);
continue;
}
diff --git a/symfony/routing/Matcher/UrlMatcher.php b/symfony/routing/Matcher/UrlMatcher.php
index 778d154ed..f3ab414f0 100644
--- a/symfony/routing/Matcher/UrlMatcher.php
+++ b/symfony/routing/Matcher/UrlMatcher.php
@@ -78,8 +78,9 @@ public function getContext(): RequestContext
public function match(string $pathinfo): array
{
$this->allow = $this->allowSchemes = [];
+ $pathinfo = '' === ($pathinfo = rawurldecode($pathinfo)) ? '/' : $pathinfo;
- if ($ret = $this->matchCollection(rawurldecode($pathinfo) ?: '/', $this->routes)) {
+ if ($ret = $this->matchCollection($pathinfo, $this->routes)) {
return $ret;
}
@@ -87,7 +88,7 @@ public function match(string $pathinfo): array
throw new NoConfigurationException();
}
- throw 0 < \count($this->allow) ? new MethodNotAllowedException(array_unique($this->allow)) : new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo));
+ throw 0 < \count($this->allow) ? new MethodNotAllowedException(array_unique($this->allow)) : new ResourceNotFoundException(\sprintf('No routes found for "%s".', $pathinfo));
}
public function matchRequest(Request $request): array
@@ -125,7 +126,7 @@ protected function matchCollection(string $pathinfo, RouteCollection $routes): a
$method = 'GET';
}
$supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface;
- $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/';
+ $trimmedPathinfo = '' === ($trimmedPathinfo = rtrim($pathinfo, '/')) ? '/' : $trimmedPathinfo;
foreach ($routes as $name => $route) {
$compiledRoute = $route->compile();
@@ -225,7 +226,7 @@ protected function handleRouteRequirements(string $pathinfo, string $name, Route
$routeParameters = func_get_arg(3);
if (!\is_array($routeParameters)) {
- throw new \TypeError(sprintf('"%s": Argument $routeParameters is expected to be an array, got "%s".', __METHOD__, get_debug_type($routeParameters)));
+ throw new \TypeError(\sprintf('"%s": Argument $routeParameters is expected to be an array, got "%s".', __METHOD__, get_debug_type($routeParameters)));
}
}
diff --git a/symfony/routing/Requirement/EnumRequirement.php b/symfony/routing/Requirement/EnumRequirement.php
index 3ab2ed332..acbd3bab0 100644
--- a/symfony/routing/Requirement/EnumRequirement.php
+++ b/symfony/routing/Requirement/EnumRequirement.php
@@ -26,7 +26,7 @@ public function __construct(string|array $cases = [])
{
if (\is_string($cases)) {
if (!is_subclass_of($cases, \BackedEnum::class, true)) {
- throw new InvalidArgumentException(sprintf('"%s" is not a "BackedEnum" class.', $cases));
+ throw new InvalidArgumentException(\sprintf('"%s" is not a "BackedEnum" class.', $cases));
}
$cases = $cases::cases();
@@ -35,13 +35,13 @@ public function __construct(string|array $cases = [])
foreach ($cases as $case) {
if (!$case instanceof \BackedEnum) {
- throw new InvalidArgumentException(sprintf('Case must be a "BackedEnum" instance, "%s" given.', get_debug_type($case)));
+ throw new InvalidArgumentException(\sprintf('Case must be a "BackedEnum" instance, "%s" given.', get_debug_type($case)));
}
$class ??= $case::class;
if (!$case instanceof $class) {
- throw new InvalidArgumentException(sprintf('"%s::%s" is not a case of "%s".', get_debug_type($case), $case->name, $class));
+ throw new InvalidArgumentException(\sprintf('"%s::%s" is not a case of "%s".', get_debug_type($case), $case->name, $class));
}
}
}
diff --git a/symfony/routing/Route.php b/symfony/routing/Route.php
index ac8d8bc6e..e34dcb75e 100644
--- a/symfony/routing/Route.php
+++ b/symfony/routing/Route.php
@@ -35,7 +35,7 @@ class Route implements \Serializable
* Available options:
*
* * compiler_class: A class name able to compile this route instance (RouteCompiler by default)
- * * utf8: Whether UTF-8 matching is enforced ot not
+ * * utf8: Whether UTF-8 matching is enforced or not
*
* @param string $path The path pattern to match
* @param array $defaults An array of default parameter values
@@ -445,7 +445,7 @@ private function sanitizeRequirement(string $key, string $regex): string
}
if ('' === $regex) {
- throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key));
+ throw new \InvalidArgumentException(\sprintf('Routing requirement for "%s" cannot be empty.', $key));
}
return $regex;
diff --git a/symfony/routing/RouteCollection.php b/symfony/routing/RouteCollection.php
index 2f49ad217..a253bc56d 100644
--- a/symfony/routing/RouteCollection.php
+++ b/symfony/routing/RouteCollection.php
@@ -239,7 +239,13 @@ public function addNamePrefix(string $prefix)
}
foreach ($this->aliases as $name => $alias) {
- $prefixedAliases[$prefix.$name] = $alias->withId($prefix.$alias->getId());
+ $targetId = $alias->getId();
+
+ if (isset($this->routes[$targetId]) || isset($this->aliases[$targetId])) {
+ $targetId = $prefix.$targetId;
+ }
+
+ $prefixedAliases[$prefix.$name] = $alias->withId($targetId);
}
$this->routes = $prefixedRoutes;
@@ -387,7 +393,7 @@ public function addResource(ResourceInterface $resource)
public function addAlias(string $name, string $alias): Alias
{
if ($name === $alias) {
- throw new InvalidArgumentException(sprintf('Route alias "%s" can not reference itself.', $name));
+ throw new InvalidArgumentException(\sprintf('Route alias "%s" can not reference itself.', $name));
}
unset($this->routes[$name], $this->priorities[$name]);
diff --git a/symfony/routing/RouteCompiler.php b/symfony/routing/RouteCompiler.php
index 330639f48..a96fb9ad9 100644
--- a/symfony/routing/RouteCompiler.php
+++ b/symfony/routing/RouteCompiler.php
@@ -75,7 +75,7 @@ public static function compile(Route $route): CompiledRoute
foreach ($pathVariables as $pathParam) {
if ('_fragment' === $pathParam) {
- throw new \InvalidArgumentException(sprintf('Route pattern "%s" cannot contain "_fragment" as a path parameter.', $route->getPath()));
+ throw new \InvalidArgumentException(\sprintf('Route pattern "%s" cannot contain "_fragment" as a path parameter.', $route->getPath()));
}
}
@@ -107,10 +107,10 @@ private static function compilePattern(Route $route, string $pattern, bool $isHo
$needsUtf8 = $route->getOption('utf8');
if (!$needsUtf8 && $useUtf8 && preg_match('/[\x80-\xFF]/', $pattern)) {
- throw new \LogicException(sprintf('Cannot use UTF-8 route patterns without setting the "utf8" option for route "%s".', $route->getPath()));
+ throw new \LogicException(\sprintf('Cannot use UTF-8 route patterns without setting the "utf8" option for route "%s".', $route->getPath()));
}
if (!$useUtf8 && $needsUtf8) {
- throw new \LogicException(sprintf('Cannot mix UTF-8 requirements with non-UTF-8 pattern "%s".', $pattern));
+ throw new \LogicException(\sprintf('Cannot mix UTF-8 requirements with non-UTF-8 pattern "%s".', $pattern));
}
// Match all variables enclosed in "{}" and iterate over them. But we only want to match the innermost variable
@@ -136,14 +136,14 @@ private static function compilePattern(Route $route, string $pattern, bool $isHo
// A PCRE subpattern name must start with a non-digit. Also a PHP variable cannot start with a digit so the
// variable would not be usable as a Controller action argument.
if (preg_match('/^\d/', $varName)) {
- throw new \DomainException(sprintf('Variable name "%s" cannot start with a digit in route pattern "%s". Please use a different name.', $varName, $pattern));
+ throw new \DomainException(\sprintf('Variable name "%s" cannot start with a digit in route pattern "%s". Please use a different name.', $varName, $pattern));
}
if (\in_array($varName, $variables)) {
- throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName));
+ throw new \LogicException(\sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName));
}
if (\strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) {
- throw new \DomainException(sprintf('Variable name "%s" cannot be longer than %d characters in route pattern "%s". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern));
+ throw new \DomainException(\sprintf('Variable name "%s" cannot be longer than %d characters in route pattern "%s". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern));
}
if ($isSeparator && $precedingText !== $precedingChar) {
@@ -163,7 +163,7 @@ private static function compilePattern(Route $route, string $pattern, bool $isHo
// Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally
// part of {_format} when generating the URL, e.g. _format = 'mobile.html'.
$nextSeparator = self::findNextSeparator($followingPattern, $useUtf8);
- $regexp = sprintf(
+ $regexp = \sprintf(
'[^%s%s]+',
preg_quote($defaultSeparator),
$defaultSeparator !== $nextSeparator && '' !== $nextSeparator ? preg_quote($nextSeparator) : ''
@@ -180,10 +180,10 @@ private static function compilePattern(Route $route, string $pattern, bool $isHo
if (!preg_match('//u', $regexp)) {
$useUtf8 = false;
} elseif (!$needsUtf8 && preg_match('/[\x80-\xFF]|(?%s)?', preg_quote($token[1]), $token[3], $token[2]);
+ return \sprintf('%s(?P<%s>%s)?', preg_quote($token[1]), $token[3], $token[2]);
} else {
- $regexp = sprintf('%s(?P<%s>%s)', preg_quote($token[1]), $token[3], $token[2]);
+ $regexp = \sprintf('%s(?P<%s>%s)', preg_quote($token[1]), $token[3], $token[2]);
if ($index >= $firstOptional) {
// Enclose each optional token in a subpattern to make it optional.
// "?:" means it is non-capturing, i.e. the portion of the subject string that
diff --git a/symfony/routing/Router.php b/symfony/routing/Router.php
index b769caee6..95f6091d7 100644
--- a/symfony/routing/Router.php
+++ b/symfony/routing/Router.php
@@ -144,7 +144,7 @@ public function setOptions(array $options)
}
if ($invalid) {
- throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid)));
+ throw new \InvalidArgumentException(\sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid)));
}
}
@@ -158,7 +158,7 @@ public function setOptions(array $options)
public function setOption(string $key, mixed $value)
{
if (!\array_key_exists($key, $this->options)) {
- throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key));
+ throw new \InvalidArgumentException(\sprintf('The Router does not support the "%s" option.', $key));
}
$this->options[$key] = $value;
@@ -172,7 +172,7 @@ public function setOption(string $key, mixed $value)
public function getOption(string $key): mixed
{
if (!\array_key_exists($key, $this->options)) {
- throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key));
+ throw new \InvalidArgumentException(\sprintf('The Router does not support the "%s" option.', $key));
}
return $this->options[$key];
diff --git a/symfony/service-contracts/ServiceLocatorTrait.php b/symfony/service-contracts/ServiceLocatorTrait.php
index b62ec3e53..bbe454843 100644
--- a/symfony/service-contracts/ServiceLocatorTrait.php
+++ b/symfony/service-contracts/ServiceLocatorTrait.php
@@ -26,16 +26,15 @@ class_exists(NotFoundExceptionInterface::class);
*/
trait ServiceLocatorTrait
{
- private array $factories;
private array $loading = [];
private array $providedTypes;
/**
* @param array $factories
*/
- public function __construct(array $factories)
- {
- $this->factories = $factories;
+ public function __construct(
+ private array $factories,
+ ) {
}
public function has(string $id): bool
@@ -91,16 +90,16 @@ private function createNotFoundException(string $id): NotFoundExceptionInterface
} else {
$last = array_pop($alternatives);
if ($alternatives) {
- $message = sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last);
+ $message = \sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last);
} else {
- $message = sprintf('only knows about the "%s" service.', $last);
+ $message = \sprintf('only knows about the "%s" service.', $last);
}
}
if ($this->loading) {
- $message = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message);
+ $message = \sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message);
} else {
- $message = sprintf('Service "%s" not found: the current service locator %s', $id, $message);
+ $message = \sprintf('Service "%s" not found: the current service locator %s', $id, $message);
}
return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface {
@@ -109,7 +108,7 @@ private function createNotFoundException(string $id): NotFoundExceptionInterface
private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface
{
- return new class(sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface {
+ return new class(\sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface {
};
}
}
diff --git a/symfony/service-contracts/ServiceMethodsSubscriberTrait.php b/symfony/service-contracts/ServiceMethodsSubscriberTrait.php
index 0d89d9f25..844be8907 100644
--- a/symfony/service-contracts/ServiceMethodsSubscriberTrait.php
+++ b/symfony/service-contracts/ServiceMethodsSubscriberTrait.php
@@ -42,18 +42,18 @@ public static function getSubscribedServices(): array
}
if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) {
- throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name));
+ throw new \LogicException(\sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name));
}
if (!$returnType = $method->getReturnType()) {
- throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class));
+ throw new \LogicException(\sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class));
}
/* @var SubscribedService $attribute */
$attribute = $attribute->newInstance();
$attribute->key ??= self::class.'::'.$method->name;
$attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType;
- $attribute->nullable = $returnType->allowsNull();
+ $attribute->nullable = $attribute->nullable ?: $returnType->allowsNull();
if ($attribute->attributes) {
$services[] = $attribute;
diff --git a/symfony/service-contracts/ServiceSubscriberTrait.php b/symfony/service-contracts/ServiceSubscriberTrait.php
index cc3bc321a..58ea7c549 100644
--- a/symfony/service-contracts/ServiceSubscriberTrait.php
+++ b/symfony/service-contracts/ServiceSubscriberTrait.php
@@ -46,18 +46,18 @@ public static function getSubscribedServices(): array
}
if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) {
- throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name));
+ throw new \LogicException(\sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name));
}
if (!$returnType = $method->getReturnType()) {
- throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class));
+ throw new \LogicException(\sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class));
}
- /* @var SubscribedService $attribute */
+ /** @var SubscribedService $attribute */
$attribute = $attribute->newInstance();
$attribute->key ??= self::class.'::'.$method->name;
$attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType;
- $attribute->nullable = $returnType->allowsNull();
+ $attribute->nullable = $attribute->nullable ?: $returnType->allowsNull();
if ($attribute->attributes) {
$services[] = $attribute;
diff --git a/symfony/string/AbstractString.php b/symfony/string/AbstractString.php
index f55c72161..45bcf0c03 100644
--- a/symfony/string/AbstractString.php
+++ b/symfony/string/AbstractString.php
@@ -263,7 +263,7 @@ public function containsAny(string|iterable $needle): bool
public function endsWith(string|iterable $suffix): bool
{
if (\is_string($suffix)) {
- throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
+ throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
}
foreach ($suffix as $s) {
@@ -312,7 +312,7 @@ public function ensureStart(string $prefix): static
public function equalsTo(string|iterable $string): bool
{
if (\is_string($string)) {
- throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
+ throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
}
foreach ($string as $s) {
@@ -340,7 +340,7 @@ public function ignoreCase(): static
public function indexOf(string|iterable $needle, int $offset = 0): ?int
{
if (\is_string($needle)) {
- throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
+ throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
}
$i = \PHP_INT_MAX;
@@ -362,7 +362,7 @@ public function indexOf(string|iterable $needle, int $offset = 0): ?int
public function indexOfLast(string|iterable $needle, int $offset = 0): ?int
{
if (\is_string($needle)) {
- throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
+ throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
}
$i = null;
@@ -414,7 +414,7 @@ abstract public function prepend(string ...$prefix): static;
public function repeat(int $multiplier): static
{
if (0 > $multiplier) {
- throw new InvalidArgumentException(sprintf('Multiplier must be positive, %d given.', $multiplier));
+ throw new InvalidArgumentException(\sprintf('Multiplier must be positive, %d given.', $multiplier));
}
$str = clone $this;
@@ -481,7 +481,7 @@ public function split(string $delimiter, ?int $limit = null, ?int $flags = null)
public function startsWith(string|iterable $prefix): bool
{
if (\is_string($prefix)) {
- throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
+ throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
}
foreach ($prefix as $prefix) {
diff --git a/symfony/string/AbstractUnicodeString.php b/symfony/string/AbstractUnicodeString.php
index 70598e409..6ea79938f 100644
--- a/symfony/string/AbstractUnicodeString.php
+++ b/symfony/string/AbstractUnicodeString.php
@@ -124,7 +124,7 @@ public function ascii(array $rules = []): self
}
if (null === $transliterator) {
- throw new InvalidArgumentException(sprintf('Unknown transliteration rule "%s".', $rule));
+ throw new InvalidArgumentException(\sprintf('Unknown transliteration rule "%s".', $rule));
}
self::$transliterators['any-latin/bgn'] = $transliterator;
@@ -135,15 +135,21 @@ public function ascii(array $rules = []): self
} elseif (!\function_exists('iconv')) {
$s = preg_replace('/[^\x00-\x7F]/u', '?', $s);
} else {
- $s = @preg_replace_callback('/[^\x00-\x7F]/u', static function ($c) {
- $c = (string) iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]);
-
- if ('' === $c && '' === iconv('UTF-8', 'ASCII//TRANSLIT', '²')) {
- throw new \LogicException(sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class));
- }
+ $previousLocale = setlocale(\LC_CTYPE, 0);
+ try {
+ setlocale(\LC_CTYPE, 'C');
+ $s = @preg_replace_callback('/[^\x00-\x7F]/u', static function ($c) {
+ $c = (string) iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]);
+
+ if ('' === $c && '' === iconv('UTF-8', 'ASCII//TRANSLIT', '²')) {
+ throw new \LogicException(\sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class));
+ }
- return 1 < \strlen($c) ? ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?');
- }, $s);
+ return 1 < \strlen($c) ? ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?');
+ }, $s);
+ } finally {
+ setlocale(\LC_CTYPE, $previousLocale);
+ }
}
}
diff --git a/symfony/string/ByteString.php b/symfony/string/ByteString.php
index 3ebe43c10..e96a184ca 100644
--- a/symfony/string/ByteString.php
+++ b/symfony/string/ByteString.php
@@ -45,7 +45,7 @@ public function __construct(string $string = '')
public static function fromRandom(int $length = 16, ?string $alphabet = null): self
{
if ($length <= 0) {
- throw new InvalidArgumentException(sprintf('A strictly positive length is expected, "%d" given.', $length));
+ throw new InvalidArgumentException(\sprintf('A strictly positive length is expected, "%d" given.', $length));
}
$alphabet ??= self::ALPHABET_ALPHANUMERIC;
@@ -436,7 +436,7 @@ public function toCodePointString(?string $fromEncoding = null): CodePointString
}
if (!$validEncoding) {
- throw new InvalidArgumentException(sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252'));
+ throw new InvalidArgumentException(\sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252'));
}
$u->string = mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252');
diff --git a/symfony/string/Inflector/EnglishInflector.php b/symfony/string/Inflector/EnglishInflector.php
index a5be28d66..558366996 100644
--- a/symfony/string/Inflector/EnglishInflector.php
+++ b/symfony/string/Inflector/EnglishInflector.php
@@ -25,9 +25,22 @@ final class EnglishInflector implements InflectorInterface
// Fourth entry: Whether the suffix may succeed a consonant
// Fifth entry: singular suffix, normal
+ // insignias (insigne), insignia (insigne)
+ ['saingisni', 9, true, true, 'insigne'],
+ ['aingisni', 8, true, true, 'insigne'],
+
+ // passersby (passerby)
+ ['ybsressap', 9, true, true, 'passerby'],
+
+ // nodes (node)
+ ['sedon', 5, true, true, 'node'],
+
// bacteria (bacterium)
['airetcab', 8, true, true, 'bacterium'],
+ // issues (issue)
+ ['seussi', 6, true, true, 'issue'],
+
// corpora (corpus)
['aroproc', 7, true, true, 'corpus'],
@@ -166,6 +179,9 @@ final class EnglishInflector implements InflectorInterface
// edges (edge)
['segd', 4, true, true, 'dge'],
+ // outages (outage) - specific fix to avoid 'outag'
+ ['segatuo', 7, true, true, 'outage'],
+
// roses (rose), garages (garage), cassettes (cassette),
// waltzes (waltz), heroes (hero), bushes (bush), arches (arch),
// shoes (shoe)
@@ -196,6 +212,15 @@ final class EnglishInflector implements InflectorInterface
// Fourth entry: Whether the suffix may succeed a consonant
// Fifth entry: plural suffix, normal
+ // passerby (passersby)
+ ['ybressap', 8, true, true, 'passersby'],
+
+ // insigne (insignia, insignias)
+ ['engisni', 7, true, true, ['insignia', 'insignias']],
+
+ // nodes (node)
+ ['edon', 4, true, true, 'nodes'],
+
// axes (axis)
['sixa', 4, false, false, 'axes'],
@@ -333,6 +358,9 @@ final class EnglishInflector implements InflectorInterface
// conspectuses (conspectus), prospectuses (prospectus)
['sutcep', 6, true, true, 'pectuses'],
+ // nexuses (nexus)
+ ['suxen', 5, false, false, 'nexuses'],
+
// fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
['su', 2, true, true, 'i'],
diff --git a/symfony/string/LazyString.php b/symfony/string/LazyString.php
index 3d893ef9e..b89ec4df1 100644
--- a/symfony/string/LazyString.php
+++ b/symfony/string/LazyString.php
@@ -26,7 +26,7 @@ class LazyString implements \Stringable, \JsonSerializable
public static function fromCallable(callable|array $callback, mixed ...$arguments): static
{
if (\is_array($callback) && !\is_callable($callback) && !(($callback[0] ?? null) instanceof \Closure || 2 < \count($callback))) {
- throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, '['.implode(', ', array_map('get_debug_type', $callback)).']'));
+ throw new \TypeError(\sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, '['.implode(', ', array_map('get_debug_type', $callback)).']'));
}
$lazyString = new static();
@@ -94,7 +94,7 @@ public function __toString(): string
$r = new \ReflectionFunction($this->value);
$callback = $r->getStaticVariables()['callback'];
- $e = new \TypeError(sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type));
+ $e = new \TypeError(\sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type));
}
throw $e;
diff --git a/symfony/string/Slugger/AsciiSlugger.php b/symfony/string/Slugger/AsciiSlugger.php
index a9693d494..d4d4e942a 100644
--- a/symfony/string/Slugger/AsciiSlugger.php
+++ b/symfony/string/Slugger/AsciiSlugger.php
@@ -95,7 +95,7 @@ public function getLocale(): string
public function withEmoji(bool|string $emoji = true): static
{
if (false !== $emoji && !class_exists(EmojiTransliterator::class)) {
- throw new \LogicException(sprintf('You cannot use the "%s()" method as the "symfony/intl" package is not installed. Try running "composer require symfony/intl".', __METHOD__));
+ throw new \LogicException(\sprintf('You cannot use the "%s()" method as the "symfony/intl" package is not installed. Try running "composer require symfony/intl".', __METHOD__));
}
$new = clone $this;
@@ -131,8 +131,8 @@ public function slug(string $string, string $separator = '-', ?string $locale =
if (\is_array($this->symbolsMap)) {
$map = null;
- if (isset($this->symbolsMap[$locale])) {
- $map = $this->symbolsMap[$locale];
+ if (isset($this->symbolsMap[$locale ?? ''])) {
+ $map = $this->symbolsMap[$locale ?? ''];
} else {
$parent = self::getParentLocale($locale);
if ($parent && isset($this->symbolsMap[$parent])) {
diff --git a/symfony/string/UnicodeString.php b/symfony/string/UnicodeString.php
index 75af2da42..f416ee1b2 100644
--- a/symfony/string/UnicodeString.php
+++ b/symfony/string/UnicodeString.php
@@ -362,6 +362,44 @@ public function startsWith(string|iterable|AbstractString $prefix): bool
return $prefix === grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES);
}
+ public function trimPrefix($prefix): static
+ {
+ if (\is_array($prefix) || $prefix instanceof \Traversable) {
+ return parent::trimPrefix($prefix);
+ }
+
+ if ($prefix instanceof AbstractString) {
+ $prefix = $prefix->string;
+ } else {
+ $prefix = (string) $prefix;
+ }
+
+ if (!normalizer_is_normalized($prefix, \Normalizer::NFC)) {
+ $prefix = normalizer_normalize($prefix, \Normalizer::NFC);
+ }
+
+ return parent::trimPrefix($prefix);
+ }
+
+ public function trimSuffix($suffix): static
+ {
+ if (\is_array($suffix) || $suffix instanceof \Traversable) {
+ return parent::trimSuffix($suffix);
+ }
+
+ if ($suffix instanceof AbstractString) {
+ $suffix = $suffix->string;
+ } else {
+ $suffix = (string) $suffix;
+ }
+
+ if (!normalizer_is_normalized($suffix, \Normalizer::NFC)) {
+ $suffix = normalizer_normalize($suffix, \Normalizer::NFC);
+ }
+
+ return parent::trimSuffix($suffix);
+ }
+
/**
* @return void
*/
diff --git a/symfony/translation-contracts/TranslatorTrait.php b/symfony/translation-contracts/TranslatorTrait.php
index 63f6fb333..afedd9928 100644
--- a/symfony/translation-contracts/TranslatorTrait.php
+++ b/symfony/translation-contracts/TranslatorTrait.php
@@ -41,6 +41,12 @@ public function trans(?string $id, array $parameters = [], ?string $domain = nul
return '';
}
+ foreach ($parameters as $k => $v) {
+ if ($v instanceof TranslatableInterface) {
+ $parameters[$k] = $v->trans($this, $locale);
+ }
+ }
+
if (!isset($parameters['%count%']) || !is_numeric($parameters['%count%'])) {
return strtr($id, $parameters);
}
@@ -111,7 +117,7 @@ public function trans(?string $id, array $parameters = [], ?string $domain = nul
return strtr($standardRules[0], $parameters);
}
- $message = sprintf('Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $id, $locale, $number);
+ $message = \sprintf('Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $id, $locale, $number);
if (class_exists(InvalidArgumentException::class)) {
throw new InvalidArgumentException($message);
diff --git a/symfony/translation/Catalogue/AbstractOperation.php b/symfony/translation/Catalogue/AbstractOperation.php
index 7dff58ff4..32fc5813c 100644
--- a/symfony/translation/Catalogue/AbstractOperation.php
+++ b/symfony/translation/Catalogue/AbstractOperation.php
@@ -97,7 +97,7 @@ public function getDomains(): array
public function getMessages(string $domain): array
{
if (!\in_array($domain, $this->getDomains())) {
- throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
+ throw new InvalidArgumentException(\sprintf('Invalid domain: "%s".', $domain));
}
if (!isset($this->messages[$domain][self::ALL_BATCH])) {
@@ -110,7 +110,7 @@ public function getMessages(string $domain): array
public function getNewMessages(string $domain): array
{
if (!\in_array($domain, $this->getDomains())) {
- throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
+ throw new InvalidArgumentException(\sprintf('Invalid domain: "%s".', $domain));
}
if (!isset($this->messages[$domain][self::NEW_BATCH])) {
@@ -123,7 +123,7 @@ public function getNewMessages(string $domain): array
public function getObsoleteMessages(string $domain): array
{
if (!\in_array($domain, $this->getDomains())) {
- throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
+ throw new InvalidArgumentException(\sprintf('Invalid domain: "%s".', $domain));
}
if (!isset($this->messages[$domain][self::OBSOLETE_BATCH])) {
@@ -160,7 +160,7 @@ public function moveMessagesToIntlDomainsIfPossible(string $batch = self::ALL_BA
self::OBSOLETE_BATCH => $this->getObsoleteMessages($domain),
self::NEW_BATCH => $this->getNewMessages($domain),
self::ALL_BATCH => $this->getMessages($domain),
- default => throw new \InvalidArgumentException(sprintf('$batch argument must be one of ["%s", "%s", "%s"].', self::ALL_BATCH, self::NEW_BATCH, self::OBSOLETE_BATCH)),
+ default => throw new \InvalidArgumentException(\sprintf('$batch argument must be one of ["%s", "%s", "%s"].', self::ALL_BATCH, self::NEW_BATCH, self::OBSOLETE_BATCH)),
};
if (!$messages || (!$this->source->all($intlDomain) && $this->source->all($domain))) {
diff --git a/symfony/translation/Command/TranslationPullCommand.php b/symfony/translation/Command/TranslationPullCommand.php
index 5d9c092c3..2394b3efe 100644
--- a/symfony/translation/Command/TranslationPullCommand.php
+++ b/symfony/translation/Command/TranslationPullCommand.php
@@ -92,10 +92,10 @@ protected function configure(): void
new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to pull translations from.', $defaultProvider),
new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with provider ones (it will delete not synchronized messages).'),
new InputOption('intl-icu', null, InputOption::VALUE_NONE, 'Associated to --force option, it will write messages in "%domain%+intl-icu.%locale%.xlf" files.'),
- new InputOption('domains', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the domains to pull.'),
- new InputOption('locales', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the locales to pull.'),
- new InputOption('format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format.', 'xlf12'),
- new InputOption('as-tree', null, InputOption::VALUE_OPTIONAL, 'Write messages as a tree-like structure. Needs --format=yaml. The given value defines the level where to switch to inline YAML'),
+ new InputOption('domains', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Specify the domains to pull.'),
+ new InputOption('locales', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Specify the locales to pull.'),
+ new InputOption('format', null, InputOption::VALUE_REQUIRED, 'Override the default output format.', 'xlf12'),
+ new InputOption('as-tree', null, InputOption::VALUE_REQUIRED, 'Write messages as a tree-like structure. Needs --format=yaml. The given value defines the level where to switch to inline YAML'),
])
->setHelp(<<<'EOF'
The %command.name%> command pulls translations from the given provider. Only
@@ -163,7 +163,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$this->writer->write($operation->getResult(), $format, $writeOptions);
}
- $io->success(sprintf('Local translations has been updated from "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+ $io->success(\sprintf('Local translations has been updated from "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
return 0;
}
@@ -177,7 +177,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$this->writer->write($catalogue, $format, $writeOptions);
}
- $io->success(sprintf('New translations from "%s" has been written locally (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+ $io->success(\sprintf('New translations from "%s" has been written locally (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
return 0;
}
diff --git a/symfony/translation/Command/TranslationPushCommand.php b/symfony/translation/Command/TranslationPushCommand.php
index 1d04adbc9..e0be0f447 100644
--- a/symfony/translation/Command/TranslationPushCommand.php
+++ b/symfony/translation/Command/TranslationPushCommand.php
@@ -83,8 +83,8 @@ protected function configure(): void
new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to push translations to.', $defaultProvider),
new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with local ones (it will delete not synchronized messages).'),
new InputOption('delete-missing', null, InputOption::VALUE_NONE, 'Delete translations available on provider but not locally.'),
- new InputOption('domains', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the domains to push.'),
- new InputOption('locales', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the locales to push.', $this->enabledLocales),
+ new InputOption('domains', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Specify the domains to push.'),
+ new InputOption('locales', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Specify the locales to push.', $this->enabledLocales),
])
->setHelp(<<<'EOF'
The %command.name%> command pushes translations to the given provider. Only new
@@ -115,7 +115,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$provider = $this->providers->get($input->getArgument('provider'));
if (!$this->enabledLocales) {
- throw new InvalidArgumentException(sprintf('You must define "framework.enabled_locales" or "framework.translator.providers.%s.locales" config key in order to work with translation providers.', parse_url($provider, \PHP_URL_SCHEME)));
+ throw new InvalidArgumentException(\sprintf('You must define "framework.enabled_locales" or "framework.translator.providers.%s.locales" config key in order to work with translation providers.', parse_url($provider, \PHP_URL_SCHEME)));
}
$io = new SymfonyStyle($input, $output);
@@ -139,7 +139,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
if (!$deleteMissing && $force) {
$provider->write($localTranslations);
- $io->success(sprintf('All local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+ $io->success(\sprintf('All local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
return 0;
}
@@ -149,7 +149,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
if ($deleteMissing) {
$provider->delete($providerTranslations->diff($localTranslations));
- $io->success(sprintf('Missing translations on "%s" has been deleted (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+ $io->success(\sprintf('Missing translations on "%s" has been deleted (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
// Read provider translations again, after missing translations deletion,
// to avoid push freshly deleted translations.
@@ -164,7 +164,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$provider->write($translationsToWrite);
- $io->success(sprintf('%s local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', $force ? 'All' : 'New', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+ $io->success(\sprintf('%s local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', $force ? 'All' : 'New', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
return 0;
}
diff --git a/symfony/translation/Command/XliffLintCommand.php b/symfony/translation/Command/XliffLintCommand.php
index ba946389e..7220e24a9 100644
--- a/symfony/translation/Command/XliffLintCommand.php
+++ b/symfony/translation/Command/XliffLintCommand.php
@@ -57,7 +57,7 @@ protected function configure()
{
$this
->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN')
- ->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())))
+ ->addOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())))
->setHelp(<<%command.name% command lints an XLIFF file and outputs to STDOUT
the first encountered syntax error.
@@ -98,7 +98,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$filesInfo = [];
foreach ($filenames as $filename) {
if (!$this->isReadable($filename)) {
- throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename));
+ throw new RuntimeException(\sprintf('File or directory "%s" is not readable.', $filename));
}
foreach ($this->getFiles($filename) as $file) {
@@ -124,18 +124,18 @@ private function validate(string $content, ?string $file = null): array
$document->loadXML($content);
if (null !== $targetLanguage = $this->getTargetLanguageFromFile($document)) {
- $normalizedLocalePattern = sprintf('(%s|%s)', preg_quote($targetLanguage, '/'), preg_quote(str_replace('-', '_', $targetLanguage), '/'));
+ $normalizedLocalePattern = \sprintf('(%s|%s)', preg_quote($targetLanguage, '/'), preg_quote(str_replace('-', '_', $targetLanguage), '/'));
// strict file names require translation files to be named '____.locale.xlf'
// otherwise, both '____.locale.xlf' and 'locale.____.xlf' are allowed
// also, the regexp matching must be case-insensitive, as defined for 'target-language' values
// http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#target-language
- $expectedFilenamePattern = $this->requireStrictFileNames ? sprintf('/^.*\.(?i:%s)\.(?:xlf|xliff)/', $normalizedLocalePattern) : sprintf('/^(?:.*\.(?i:%s)|(?i:%s)\..*)\.(?:xlf|xliff)/', $normalizedLocalePattern, $normalizedLocalePattern);
+ $expectedFilenamePattern = $this->requireStrictFileNames ? \sprintf('/^.*\.(?i:%s)\.(?:xlf|xliff)/', $normalizedLocalePattern) : \sprintf('/^(?:.*\.(?i:%s)|(?i:%s)\..*)\.(?:xlf|xliff)/', $normalizedLocalePattern, $normalizedLocalePattern);
if (0 === preg_match($expectedFilenamePattern, basename($file))) {
$errors[] = [
'line' => -1,
'column' => -1,
- 'message' => sprintf('There is a mismatch between the language included in the file name ("%s") and the "%s" value used in the "target-language" attribute of the file.', basename($file), $targetLanguage),
+ 'message' => \sprintf('There is a mismatch between the language included in the file name ("%s") and the "%s" value used in the "target-language" attribute of the file.', basename($file), $targetLanguage),
];
}
}
@@ -160,7 +160,7 @@ private function display(SymfonyStyle $io, array $files): int
'txt' => $this->displayTxt($io, $files),
'json' => $this->displayJson($io, $files),
'github' => $this->displayTxt($io, $files, true),
- default => throw new InvalidArgumentException(sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))),
+ default => throw new InvalidArgumentException(\sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))),
};
}
@@ -172,25 +172,25 @@ private function displayTxt(SymfonyStyle $io, array $filesInfo, bool $errorAsGit
foreach ($filesInfo as $info) {
if ($info['valid'] && $this->displayCorrectFiles) {
- $io->comment('OK'.($info['file'] ? sprintf(' in %s', $info['file']) : ''));
+ $io->comment('OK'.($info['file'] ? \sprintf(' in %s', $info['file']) : ''));
} elseif (!$info['valid']) {
++$erroredFiles;
- $io->text(' ERROR '.($info['file'] ? sprintf(' in %s', $info['file']) : ''));
+ $io->text(' ERROR '.($info['file'] ? \sprintf(' in %s', $info['file']) : ''));
$io->listing(array_map(function ($error) use ($info, $githubReporter) {
// general document errors have a '-1' line number
$line = -1 === $error['line'] ? null : $error['line'];
$githubReporter?->error($error['message'], $info['file'], $line, null !== $line ? $error['column'] : null);
- return null === $line ? $error['message'] : sprintf('Line %d, Column %d: %s', $line, $error['column'], $error['message']);
+ return null === $line ? $error['message'] : \sprintf('Line %d, Column %d: %s', $line, $error['column'], $error['message']);
}, $info['messages']));
}
}
if (0 === $erroredFiles) {
- $io->success(sprintf('All %d XLIFF files contain valid syntax.', $countFiles));
+ $io->success(\sprintf('All %d XLIFF files contain valid syntax.', $countFiles));
} else {
- $io->warning(sprintf('%d XLIFF files have valid syntax and %d contain errors.', $countFiles - $erroredFiles, $erroredFiles));
+ $io->warning(\sprintf('%d XLIFF files have valid syntax and %d contain errors.', $countFiles - $erroredFiles, $erroredFiles));
}
return min($erroredFiles, 1);
diff --git a/symfony/translation/DataCollectorTranslator.php b/symfony/translation/DataCollectorTranslator.php
index a2832ee8e..7ab3b047b 100644
--- a/symfony/translation/DataCollectorTranslator.php
+++ b/symfony/translation/DataCollectorTranslator.php
@@ -34,7 +34,7 @@ class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInter
public function __construct(TranslatorInterface $translator)
{
if (!$translator instanceof TranslatorBagInterface || !$translator instanceof LocaleAwareInterface) {
- throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', get_debug_type($translator)));
+ throw new InvalidArgumentException(\sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', get_debug_type($translator)));
}
$this->translator = $translator;
diff --git a/symfony/translation/DependencyInjection/LoggingTranslatorPass.php b/symfony/translation/DependencyInjection/LoggingTranslatorPass.php
index c21552f97..fba86981c 100644
--- a/symfony/translation/DependencyInjection/LoggingTranslatorPass.php
+++ b/symfony/translation/DependencyInjection/LoggingTranslatorPass.php
@@ -37,7 +37,7 @@ public function process(ContainerBuilder $container): void
$class = $container->getParameterBag()->resolveValue($definition->getClass());
if (!$r = $container->getReflectionClass($class)) {
- throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $translatorAlias));
+ throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $translatorAlias));
}
if (!$r->isSubclassOf(TranslatorInterface::class) || !$r->isSubclassOf(TranslatorBagInterface::class)) {
diff --git a/symfony/translation/DependencyInjection/TranslationExtractorPass.php b/symfony/translation/DependencyInjection/TranslationExtractorPass.php
index 1baf9341e..5e9b5af34 100644
--- a/symfony/translation/DependencyInjection/TranslationExtractorPass.php
+++ b/symfony/translation/DependencyInjection/TranslationExtractorPass.php
@@ -34,7 +34,7 @@ public function process(ContainerBuilder $container)
foreach ($container->findTaggedServiceIds('translation.extractor', true) as $id => $attributes) {
if (!isset($attributes[0]['alias'])) {
- throw new RuntimeException(sprintf('The alias for the tag "translation.extractor" of service "%s" must be set.', $id));
+ throw new RuntimeException(\sprintf('The alias for the tag "translation.extractor" of service "%s" must be set.', $id));
}
$definition->addMethodCall('addExtractor', [$attributes[0]['alias'], new Reference($id)]);
diff --git a/symfony/translation/DependencyInjection/TranslatorPathsPass.php b/symfony/translation/DependencyInjection/TranslatorPathsPass.php
index 1756e3c8c..b6112e5b3 100644
--- a/symfony/translation/DependencyInjection/TranslatorPathsPass.php
+++ b/symfony/translation/DependencyInjection/TranslatorPathsPass.php
@@ -96,10 +96,10 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
$class = $this->definitions[$i]->getClass();
if (ServiceLocator::class === $class) {
- if (!isset($this->controllers[$this->currentId])) {
+ if (!isset($this->controllers[$this->currentId ?? ''])) {
continue;
}
- foreach ($this->controllers[$this->currentId] as $class => $_) {
+ foreach ($this->controllers[$this->currentId ?? ''] as $class => $_) {
$this->paths[$class] = true;
}
} else {
diff --git a/symfony/translation/Dumper/CsvFileDumper.php b/symfony/translation/Dumper/CsvFileDumper.php
index 8f5475259..a4ae476b3 100644
--- a/symfony/translation/Dumper/CsvFileDumper.php
+++ b/symfony/translation/Dumper/CsvFileDumper.php
@@ -28,7 +28,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra
$handle = fopen('php://memory', 'r+');
foreach ($messages->all($domain) as $source => $target) {
- fputcsv($handle, [$source, $target], $this->delimiter, $this->enclosure);
+ fputcsv($handle, [$source, $target], $this->delimiter, $this->enclosure, '\\');
}
rewind($handle);
diff --git a/symfony/translation/Dumper/FileDumper.php b/symfony/translation/Dumper/FileDumper.php
index e30d4770e..8f3a953e3 100644
--- a/symfony/translation/Dumper/FileDumper.php
+++ b/symfony/translation/Dumper/FileDumper.php
@@ -57,7 +57,7 @@ public function dump(MessageCatalogue $messages, array $options = [])
if (!file_exists($fullpath)) {
$directory = \dirname($fullpath);
if (!file_exists($directory) && !@mkdir($directory, 0777, true)) {
- throw new RuntimeException(sprintf('Unable to create directory "%s".', $directory));
+ throw new RuntimeException(\sprintf('Unable to create directory "%s".', $directory));
}
}
diff --git a/symfony/translation/Dumper/PoFileDumper.php b/symfony/translation/Dumper/PoFileDumper.php
index a2d0deb78..acf046c14 100644
--- a/symfony/translation/Dumper/PoFileDumper.php
+++ b/symfony/translation/Dumper/PoFileDumper.php
@@ -51,14 +51,14 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra
$sourceRules = $this->getStandardRules($source);
$targetRules = $this->getStandardRules($target);
if (2 == \count($sourceRules) && [] !== $targetRules) {
- $output .= sprintf('msgid "%s"'."\n", $this->escape($sourceRules[0]));
- $output .= sprintf('msgid_plural "%s"'."\n", $this->escape($sourceRules[1]));
+ $output .= \sprintf('msgid "%s"'."\n", $this->escape($sourceRules[0]));
+ $output .= \sprintf('msgid_plural "%s"'."\n", $this->escape($sourceRules[1]));
foreach ($targetRules as $i => $targetRule) {
- $output .= sprintf('msgstr[%d] "%s"'."\n", $i, $this->escape($targetRule));
+ $output .= \sprintf('msgstr[%d] "%s"'."\n", $i, $this->escape($targetRule));
}
} else {
- $output .= sprintf('msgid "%s"'."\n", $this->escape($source));
- $output .= sprintf('msgstr "%s"'."\n", $this->escape($target));
+ $output .= \sprintf('msgid "%s"'."\n", $this->escape($source));
+ $output .= \sprintf('msgstr "%s"'."\n", $this->escape($target));
}
}
@@ -123,7 +123,7 @@ private function formatComments(string|array $comments, string $prefix = ''): ?s
$output = null;
foreach ((array) $comments as $comment) {
- $output .= sprintf('#%s %s'."\n", $prefix, $comment);
+ $output .= \sprintf('#%s %s'."\n", $prefix, $comment);
}
return $output;
diff --git a/symfony/translation/Dumper/XliffFileDumper.php b/symfony/translation/Dumper/XliffFileDumper.php
index d0f016b23..a2dfcd16d 100644
--- a/symfony/translation/Dumper/XliffFileDumper.php
+++ b/symfony/translation/Dumper/XliffFileDumper.php
@@ -46,7 +46,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra
return $this->dumpXliff2($defaultLocale, $messages, $domain);
}
- throw new InvalidArgumentException(sprintf('No support implemented for dumping XLIFF version "%s".', $xliffVersion));
+ throw new InvalidArgumentException(\sprintf('No support implemented for dumping XLIFF version "%s".', $xliffVersion));
}
protected function getExtension(): string
@@ -176,7 +176,7 @@ private function dumpXliff2(string $defaultLocale, MessageCatalogue $messages, ?
$metadata = $messages->getMetadata($source, $domain);
// Add notes section
- if ($this->hasMetadataArrayInfo('notes', $metadata)) {
+ if ($this->hasMetadataArrayInfo('notes', $metadata) && $metadata['notes']) {
$notesElement = $dom->createElement('notes');
foreach ($metadata['notes'] as $note) {
$n = $dom->createElement('note');
diff --git a/symfony/translation/Exception/IncompleteDsnException.php b/symfony/translation/Exception/IncompleteDsnException.php
index b304bde01..6c9247f89 100644
--- a/symfony/translation/Exception/IncompleteDsnException.php
+++ b/symfony/translation/Exception/IncompleteDsnException.php
@@ -16,7 +16,7 @@ class IncompleteDsnException extends InvalidArgumentException
public function __construct(string $message, ?string $dsn = null, ?\Throwable $previous = null)
{
if ($dsn) {
- $message = sprintf('Invalid "%s" provider DSN: ', $dsn).$message;
+ $message = \sprintf('Invalid "%s" provider DSN: ', $dsn).$message;
}
parent::__construct($message, 0, $previous);
diff --git a/symfony/translation/Exception/MissingRequiredOptionException.php b/symfony/translation/Exception/MissingRequiredOptionException.php
index 46152e254..8cef03a81 100644
--- a/symfony/translation/Exception/MissingRequiredOptionException.php
+++ b/symfony/translation/Exception/MissingRequiredOptionException.php
@@ -18,7 +18,7 @@ class MissingRequiredOptionException extends IncompleteDsnException
{
public function __construct(string $option, ?string $dsn = null, ?\Throwable $previous = null)
{
- $message = sprintf('The option "%s" is required but missing.', $option);
+ $message = \sprintf('The option "%s" is required but missing.', $option);
parent::__construct($message, $dsn, $previous);
}
diff --git a/symfony/translation/Exception/UnsupportedSchemeException.php b/symfony/translation/Exception/UnsupportedSchemeException.php
index 8d3295184..ca18444e4 100644
--- a/symfony/translation/Exception/UnsupportedSchemeException.php
+++ b/symfony/translation/Exception/UnsupportedSchemeException.php
@@ -43,14 +43,14 @@ public function __construct(Dsn $dsn, ?string $name = null, array $supported = [
}
$package = self::SCHEME_TO_PACKAGE_MAP[$provider] ?? null;
if ($package && !class_exists($package['class'])) {
- parent::__construct(sprintf('Unable to synchronize translations via "%s" as the provider is not installed. Try running "composer require %s".', $provider, $package['package']));
+ parent::__construct(\sprintf('Unable to synchronize translations via "%s" as the provider is not installed. Try running "composer require %s".', $provider, $package['package']));
return;
}
- $message = sprintf('The "%s" scheme is not supported', $dsn->getScheme());
+ $message = \sprintf('The "%s" scheme is not supported', $dsn->getScheme());
if ($name && $supported) {
- $message .= sprintf('; supported schemes for translation provider "%s" are: "%s"', $name, implode('", "', $supported));
+ $message .= \sprintf('; supported schemes for translation provider "%s" are: "%s"', $name, implode('", "', $supported));
}
parent::__construct($message.'.');
diff --git a/symfony/translation/Extractor/AbstractFileExtractor.php b/symfony/translation/Extractor/AbstractFileExtractor.php
index 4c088b94f..8af022402 100644
--- a/symfony/translation/Extractor/AbstractFileExtractor.php
+++ b/symfony/translation/Extractor/AbstractFileExtractor.php
@@ -49,7 +49,7 @@ private function toSplFileInfo(string $file): \SplFileInfo
protected function isFile(string $file): bool
{
if (!is_file($file)) {
- throw new InvalidArgumentException(sprintf('The "%s" file does not exist.', $file));
+ throw new InvalidArgumentException(\sprintf('The "%s" file does not exist.', $file));
}
return true;
diff --git a/symfony/translation/Extractor/PhpAstExtractor.php b/symfony/translation/Extractor/PhpAstExtractor.php
index 06fc77de3..a5375f480 100644
--- a/symfony/translation/Extractor/PhpAstExtractor.php
+++ b/symfony/translation/Extractor/PhpAstExtractor.php
@@ -36,7 +36,7 @@ public function __construct(
private string $prefix = '',
) {
if (!class_exists(ParserFactory::class)) {
- throw new \LogicException(sprintf('You cannot use "%s" as the "nikic/php-parser" package is not installed. Try running "composer require nikic/php-parser".', static::class));
+ throw new \LogicException(\sprintf('You cannot use "%s" as the "nikic/php-parser" package is not installed. Try running "composer require nikic/php-parser".', static::class));
}
$this->parser = (new ParserFactory())->createForHostVersion();
@@ -77,7 +77,7 @@ protected function canBeExtracted(string $file): bool
protected function extractFromDirectory(array|string $resource): iterable|Finder
{
if (!class_exists(Finder::class)) {
- throw new \LogicException(sprintf('You cannot use "%s" as the "symfony/finder" package is not installed. Try running "composer require symfony/finder".', static::class));
+ throw new \LogicException(\sprintf('You cannot use "%s" as the "symfony/finder" package is not installed. Try running "composer require symfony/finder".', static::class));
}
return (new Finder())->files()->name('*.php')->in($resource);
diff --git a/symfony/translation/Extractor/PhpExtractor.php b/symfony/translation/Extractor/PhpExtractor.php
index 7ff27f7c8..72afe4777 100644
--- a/symfony/translation/Extractor/PhpExtractor.php
+++ b/symfony/translation/Extractor/PhpExtractor.php
@@ -323,7 +323,7 @@ protected function canBeExtracted(string $file): bool
protected function extractFromDirectory(string|array $directory): iterable
{
if (!class_exists(Finder::class)) {
- throw new \LogicException(sprintf('You cannot use "%s" as the "symfony/finder" package is not installed. Try running "composer require symfony/finder".', static::class));
+ throw new \LogicException(\sprintf('You cannot use "%s" as the "symfony/finder" package is not installed. Try running "composer require symfony/finder".', static::class));
}
$finder = new Finder();
diff --git a/symfony/translation/Extractor/Visitor/ConstraintVisitor.php b/symfony/translation/Extractor/Visitor/ConstraintVisitor.php
index 00fb9eedc..45cae3536 100644
--- a/symfony/translation/Extractor/Visitor/ConstraintVisitor.php
+++ b/symfony/translation/Extractor/Visitor/ConstraintVisitor.php
@@ -22,7 +22,7 @@
final class ConstraintVisitor extends AbstractVisitor implements NodeVisitor
{
public function __construct(
- private readonly array $constraintClassNames = []
+ private readonly array $constraintClassNames = [],
) {
}
diff --git a/symfony/translation/Extractor/Visitor/TransMethodVisitor.php b/symfony/translation/Extractor/Visitor/TransMethodVisitor.php
index 011bf3b11..a3dcd6d2b 100644
--- a/symfony/translation/Extractor/Visitor/TransMethodVisitor.php
+++ b/symfony/translation/Extractor/Visitor/TransMethodVisitor.php
@@ -44,7 +44,7 @@ public function leaveNode(Node $node): ?Node
if ('trans' === $name || 't' === $name) {
$firstNamedArgumentIndex = $this->nodeFirstNamedArgumentIndex($node);
- if (!$messages = $this->getStringArguments($node, 0 < $firstNamedArgumentIndex ? 0 : 'message')) {
+ if (!$messages = $this->getStringArguments($node, 0 < $firstNamedArgumentIndex ? 0 : 'id')) {
return null;
}
diff --git a/symfony/translation/Formatter/IntlFormatter.php b/symfony/translation/Formatter/IntlFormatter.php
index e62de253f..87cb00733 100644
--- a/symfony/translation/Formatter/IntlFormatter.php
+++ b/symfony/translation/Formatter/IntlFormatter.php
@@ -37,7 +37,7 @@ public function formatIntl(string $message, string $locale, array $parameters =
try {
$this->cache[$locale][$message] = $formatter = new \MessageFormatter($locale, $message);
} catch (\IntlException $e) {
- throw new InvalidArgumentException(sprintf('Invalid message format (error #%d): ', intl_get_error_code()).intl_get_error_message(), 0, $e);
+ throw new InvalidArgumentException(\sprintf('Invalid message format (error #%d): ', intl_get_error_code()).intl_get_error_message(), 0, $e);
}
}
@@ -49,7 +49,7 @@ public function formatIntl(string $message, string $locale, array $parameters =
}
if (false === $message = $formatter->format($parameters)) {
- throw new InvalidArgumentException(sprintf('Unable to format message (error #%s): ', $formatter->getErrorCode()).$formatter->getErrorMessage());
+ throw new InvalidArgumentException(\sprintf('Unable to format message (error #%s): ', $formatter->getErrorCode()).$formatter->getErrorMessage());
}
return $message;
diff --git a/symfony/translation/Loader/CsvFileLoader.php b/symfony/translation/Loader/CsvFileLoader.php
index 7f2f96be6..9d26611e5 100644
--- a/symfony/translation/Loader/CsvFileLoader.php
+++ b/symfony/translation/Loader/CsvFileLoader.php
@@ -22,7 +22,7 @@ class CsvFileLoader extends FileLoader
{
private string $delimiter = ';';
private string $enclosure = '"';
- private string $escape = '\\';
+ private string $escape = '';
protected function loadResource(string $resource): array
{
@@ -31,7 +31,7 @@ protected function loadResource(string $resource): array
try {
$file = new \SplFileObject($resource, 'rb');
} catch (\RuntimeException $e) {
- throw new NotFoundResourceException(sprintf('Error opening file "%s".', $resource), 0, $e);
+ throw new NotFoundResourceException(\sprintf('Error opening file "%s".', $resource), 0, $e);
}
$file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY);
@@ -55,7 +55,7 @@ protected function loadResource(string $resource): array
*
* @return void
*/
- public function setCsvControl(string $delimiter = ';', string $enclosure = '"', string $escape = '\\')
+ public function setCsvControl(string $delimiter = ';', string $enclosure = '"', string $escape = '')
{
$this->delimiter = $delimiter;
$this->enclosure = $enclosure;
diff --git a/symfony/translation/Loader/FileLoader.php b/symfony/translation/Loader/FileLoader.php
index 877c3bbc7..94f6e2022 100644
--- a/symfony/translation/Loader/FileLoader.php
+++ b/symfony/translation/Loader/FileLoader.php
@@ -24,11 +24,11 @@ abstract class FileLoader extends ArrayLoader
public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue
{
if (!stream_is_local($resource)) {
- throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ throw new InvalidResourceException(\sprintf('This is not a local file "%s".', $resource));
}
if (!file_exists($resource)) {
- throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ throw new NotFoundResourceException(\sprintf('File "%s" not found.', $resource));
}
$messages = $this->loadResource($resource);
@@ -38,7 +38,7 @@ public function load(mixed $resource, string $locale, string $domain = 'messages
// not an array
if (!\is_array($messages)) {
- throw new InvalidResourceException(sprintf('Unable to load file "%s".', $resource));
+ throw new InvalidResourceException(\sprintf('Unable to load file "%s".', $resource));
}
$catalogue = parent::load($messages, $locale, $domain);
diff --git a/symfony/translation/Loader/IcuDatFileLoader.php b/symfony/translation/Loader/IcuDatFileLoader.php
index 76e4e7f02..1af864303 100644
--- a/symfony/translation/Loader/IcuDatFileLoader.php
+++ b/symfony/translation/Loader/IcuDatFileLoader.php
@@ -26,11 +26,11 @@ class IcuDatFileLoader extends IcuResFileLoader
public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue
{
if (!stream_is_local($resource.'.dat')) {
- throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ throw new InvalidResourceException(\sprintf('This is not a local file "%s".', $resource));
}
if (!file_exists($resource.'.dat')) {
- throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ throw new NotFoundResourceException(\sprintf('File "%s" not found.', $resource));
}
try {
@@ -40,7 +40,7 @@ public function load(mixed $resource, string $locale, string $domain = 'messages
}
if (!$rb) {
- throw new InvalidResourceException(sprintf('Cannot load resource "%s".', $resource));
+ throw new InvalidResourceException(\sprintf('Cannot load resource "%s".', $resource));
} elseif (intl_is_failure($rb->getErrorCode())) {
throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
}
diff --git a/symfony/translation/Loader/IcuResFileLoader.php b/symfony/translation/Loader/IcuResFileLoader.php
index 949dd9792..8ada43dca 100644
--- a/symfony/translation/Loader/IcuResFileLoader.php
+++ b/symfony/translation/Loader/IcuResFileLoader.php
@@ -26,11 +26,11 @@ class IcuResFileLoader implements LoaderInterface
public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue
{
if (!stream_is_local($resource)) {
- throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ throw new InvalidResourceException(\sprintf('This is not a local file "%s".', $resource));
}
if (!is_dir($resource)) {
- throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ throw new NotFoundResourceException(\sprintf('File "%s" not found.', $resource));
}
try {
@@ -40,7 +40,7 @@ public function load(mixed $resource, string $locale, string $domain = 'messages
}
if (!$rb) {
- throw new InvalidResourceException(sprintf('Cannot load resource "%s".', $resource));
+ throw new InvalidResourceException(\sprintf('Cannot load resource "%s".', $resource));
} elseif (intl_is_failure($rb->getErrorCode())) {
throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
}
diff --git a/symfony/translation/Loader/QtFileLoader.php b/symfony/translation/Loader/QtFileLoader.php
index 235f85ee9..1b167bd6d 100644
--- a/symfony/translation/Loader/QtFileLoader.php
+++ b/symfony/translation/Loader/QtFileLoader.php
@@ -32,17 +32,17 @@ public function load(mixed $resource, string $locale, string $domain = 'messages
}
if (!stream_is_local($resource)) {
- throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ throw new InvalidResourceException(\sprintf('This is not a local file "%s".', $resource));
}
if (!file_exists($resource)) {
- throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ throw new NotFoundResourceException(\sprintf('File "%s" not found.', $resource));
}
try {
$dom = XmlUtils::loadFile($resource);
} catch (\InvalidArgumentException $e) {
- throw new InvalidResourceException(sprintf('Unable to load "%s".', $resource), $e->getCode(), $e);
+ throw new InvalidResourceException(\sprintf('Unable to load "%s".', $resource), $e->getCode(), $e);
}
$internalErrors = libxml_use_internal_errors(true);
diff --git a/symfony/translation/Loader/XliffFileLoader.php b/symfony/translation/Loader/XliffFileLoader.php
index 31b3251ba..98c759fae 100644
--- a/symfony/translation/Loader/XliffFileLoader.php
+++ b/symfony/translation/Loader/XliffFileLoader.php
@@ -36,15 +36,15 @@ public function load(mixed $resource, string $locale, string $domain = 'messages
if (!$this->isXmlString($resource)) {
if (!stream_is_local($resource)) {
- throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ throw new InvalidResourceException(\sprintf('This is not a local file "%s".', $resource));
}
if (!file_exists($resource)) {
- throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ throw new NotFoundResourceException(\sprintf('File "%s" not found.', $resource));
}
if (!is_file($resource)) {
- throw new InvalidResourceException(sprintf('This is neither a file nor an XLIFF string "%s".', $resource));
+ throw new InvalidResourceException(\sprintf('This is neither a file nor an XLIFF string "%s".', $resource));
}
}
@@ -55,11 +55,11 @@ public function load(mixed $resource, string $locale, string $domain = 'messages
$dom = XmlUtils::loadFile($resource);
}
} catch (\InvalidArgumentException|XmlParsingException|InvalidXmlException $e) {
- throw new InvalidResourceException(sprintf('Unable to load "%s": ', $resource).$e->getMessage(), $e->getCode(), $e);
+ throw new InvalidResourceException(\sprintf('Unable to load "%s": ', $resource).$e->getMessage(), $e->getCode(), $e);
}
if ($errors = XliffUtils::validateSchema($dom)) {
- throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: ', $resource).XliffUtils::getErrorsAsString($errors));
+ throw new InvalidResourceException(\sprintf('Invalid resource provided: "%s"; Errors: ', $resource).XliffUtils::getErrorsAsString($errors));
}
$catalogue = new MessageCatalogue($locale);
@@ -112,16 +112,20 @@ private function extractXliff1(\DOMDocument $dom, MessageCatalogue $catalogue, s
continue;
}
- if (isset($translation->target) && 'needs-translation' === (string) $translation->target->attributes()['state']) {
+ $source = (string) (isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source);
+
+ if (isset($translation->target)
+ && 'needs-translation' === (string) $translation->target->attributes()['state']
+ && \in_array((string) $translation->target, [$source, (string) $translation->source], true)
+ ) {
continue;
}
- $source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source;
// If the xlf file has another encoding specified, try to convert it because
// simple_xml will always return utf-8 encoded values
$target = $this->utf8ToCharset((string) ($translation->target ?? $translation->source), $encoding);
- $catalogue->set((string) $source, $target, $domain);
+ $catalogue->set($source, $target, $domain);
$metadata = [
'source' => (string) $translation->source,
@@ -144,7 +148,7 @@ private function extractXliff1(\DOMDocument $dom, MessageCatalogue $catalogue, s
$metadata['id'] = (string) $attributes['id'];
}
- $catalogue->setMetadata((string) $source, $metadata, $domain);
+ $catalogue->setMetadata($source, $metadata, $domain);
}
}
}
diff --git a/symfony/translation/Loader/YamlFileLoader.php b/symfony/translation/Loader/YamlFileLoader.php
index 48e735d16..39d5a0e99 100644
--- a/symfony/translation/Loader/YamlFileLoader.php
+++ b/symfony/translation/Loader/YamlFileLoader.php
@@ -29,7 +29,7 @@ class YamlFileLoader extends FileLoader
protected function loadResource(string $resource): array
{
if (!isset($this->yamlParser)) {
- if (!class_exists(\Symfony\Component\Yaml\Parser::class)) {
+ if (!class_exists(YamlParser::class)) {
throw new LogicException('Loading translations from the YAML format requires the Symfony Yaml component.');
}
@@ -39,11 +39,11 @@ protected function loadResource(string $resource): array
try {
$messages = $this->yamlParser->parseFile($resource, Yaml::PARSE_CONSTANT);
} catch (ParseException $e) {
- throw new InvalidResourceException(sprintf('The file "%s" does not contain valid YAML: ', $resource).$e->getMessage(), 0, $e);
+ throw new InvalidResourceException(\sprintf('The file "%s" does not contain valid YAML: ', $resource).$e->getMessage(), 0, $e);
}
if (null !== $messages && !\is_array($messages)) {
- throw new InvalidResourceException(sprintf('Unable to load file "%s".', $resource));
+ throw new InvalidResourceException(\sprintf('Unable to load file "%s".', $resource));
}
return $messages ?: [];
diff --git a/symfony/translation/LocaleSwitcher.php b/symfony/translation/LocaleSwitcher.php
index c07809c58..4950a56bb 100644
--- a/symfony/translation/LocaleSwitcher.php
+++ b/symfony/translation/LocaleSwitcher.php
@@ -34,9 +34,14 @@ public function __construct(
public function setLocale(string $locale): void
{
- if (class_exists(\Locale::class)) {
- \Locale::setDefault($locale);
+ // Silently ignore if the intl extension is not loaded
+ try {
+ if (class_exists(\Locale::class, false)) {
+ \Locale::setDefault($locale);
+ }
+ } catch (\Exception) {
}
+
$this->locale = $locale;
$this->requestContext?->setParameter('_locale', $locale);
diff --git a/symfony/translation/LoggingTranslator.php b/symfony/translation/LoggingTranslator.php
index 4a560bd6a..629f3f7ad 100644
--- a/symfony/translation/LoggingTranslator.php
+++ b/symfony/translation/LoggingTranslator.php
@@ -30,7 +30,7 @@ class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface,
public function __construct(TranslatorInterface $translator, LoggerInterface $logger)
{
if (!$translator instanceof TranslatorBagInterface || !$translator instanceof LocaleAwareInterface) {
- throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', get_debug_type($translator)));
+ throw new InvalidArgumentException(\sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', get_debug_type($translator)));
}
$this->translator = $translator;
@@ -56,7 +56,7 @@ public function setLocale(string $locale)
return;
}
- $this->logger->debug(sprintf('The locale of the translator has changed from "%s" to "%s".', $prev, $locale));
+ $this->logger->debug(\sprintf('The locale of the translator has changed from "%s" to "%s".', $prev, $locale));
}
public function getLocale(): string
diff --git a/symfony/translation/MessageCatalogue.php b/symfony/translation/MessageCatalogue.php
index d56f04393..9098619e8 100644
--- a/symfony/translation/MessageCatalogue.php
+++ b/symfony/translation/MessageCatalogue.php
@@ -155,7 +155,7 @@ public function add(array $messages, string $domain = 'messages')
public function addCatalogue(MessageCatalogueInterface $catalogue)
{
if ($catalogue->getLocale() !== $this->locale) {
- throw new LogicException(sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s".', $catalogue->getLocale(), $this->locale));
+ throw new LogicException(\sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s".', $catalogue->getLocale(), $this->locale));
}
foreach ($catalogue->all() as $domain => $messages) {
@@ -190,14 +190,14 @@ public function addFallbackCatalogue(MessageCatalogueInterface $catalogue)
$c = $catalogue;
while ($c = $c->getFallbackCatalogue()) {
if ($c->getLocale() === $this->getLocale()) {
- throw new LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
+ throw new LogicException(\sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
}
}
$c = $this;
do {
if ($c->getLocale() === $catalogue->getLocale()) {
- throw new LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
+ throw new LogicException(\sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
}
foreach ($catalogue->getResources() as $resource) {
@@ -237,6 +237,16 @@ public function getMetadata(string $key = '', string $domain = 'messages'): mixe
return $this->metadata;
}
+ if (isset($this->metadata[$domain.self::INTL_DOMAIN_SUFFIX])) {
+ if ('' === $key) {
+ return $this->metadata[$domain.self::INTL_DOMAIN_SUFFIX];
+ }
+
+ if (isset($this->metadata[$domain.self::INTL_DOMAIN_SUFFIX][$key])) {
+ return $this->metadata[$domain.self::INTL_DOMAIN_SUFFIX][$key];
+ }
+ }
+
if (isset($this->metadata[$domain])) {
if ('' == $key) {
return $this->metadata[$domain];
diff --git a/symfony/translation/Provider/TranslationProviderCollection.php b/symfony/translation/Provider/TranslationProviderCollection.php
index b917415ba..878998fec 100644
--- a/symfony/translation/Provider/TranslationProviderCollection.php
+++ b/symfony/translation/Provider/TranslationProviderCollection.php
@@ -44,7 +44,7 @@ public function has(string $name): bool
public function get(string $name): ProviderInterface
{
if (!$this->has($name)) {
- throw new InvalidArgumentException(sprintf('Provider "%s" not found. Available: "%s".', $name, (string) $this));
+ throw new InvalidArgumentException(\sprintf('Provider "%s" not found. Available: "%s".', $name, (string) $this));
}
return $this->providers[$name];
diff --git a/symfony/translation/PseudoLocalizationTranslator.php b/symfony/translation/PseudoLocalizationTranslator.php
index f26909f5e..4bfbba901 100644
--- a/symfony/translation/PseudoLocalizationTranslator.php
+++ b/symfony/translation/PseudoLocalizationTranslator.php
@@ -55,7 +55,7 @@ final class PseudoLocalizationTranslator implements TranslatorInterface
* * parse_html:
* type: boolean
* default: false
- * description: parse the translated string as HTML - looking for HTML tags has a performance impact but allows to preserve them from alterations - it also allows to compute the visible translated string length which is useful to correctly expand ot when it contains HTML
+ * description: parse the translated string as HTML - looking for HTML tags has a performance impact but allows to preserve them from alterations - it also allows to compute the visible translated string length which is useful to correctly expand or when it contains HTML
* warning: unclosed tags are unsupported, they will be fixed (closed) by the parser - eg, "foo bar" => "foo
bar
"
*
* * localizable_html_attributes:
diff --git a/symfony/translation/Resources/data/parents.json b/symfony/translation/Resources/data/parents.json
index 24d4d119e..0197e451b 100644
--- a/symfony/translation/Resources/data/parents.json
+++ b/symfony/translation/Resources/data/parents.json
@@ -18,29 +18,37 @@
"en_CM": "en_001",
"en_CX": "en_001",
"en_CY": "en_001",
+ "en_CZ": "en_150",
"en_DE": "en_150",
"en_DG": "en_001",
"en_DK": "en_150",
"en_DM": "en_001",
+ "en_EE": "en_150",
"en_ER": "en_001",
+ "en_ES": "en_150",
"en_FI": "en_150",
"en_FJ": "en_001",
"en_FK": "en_001",
"en_FM": "en_001",
+ "en_FR": "en_150",
"en_GB": "en_001",
"en_GD": "en_001",
+ "en_GE": "en_150",
"en_GG": "en_001",
"en_GH": "en_001",
"en_GI": "en_001",
"en_GM": "en_001",
+ "en_GS": "en_001",
"en_GY": "en_001",
"en_HK": "en_001",
+ "en_HU": "en_150",
"en_ID": "en_001",
"en_IE": "en_001",
"en_IL": "en_001",
"en_IM": "en_001",
"en_IN": "en_001",
"en_IO": "en_001",
+ "en_IT": "en_150",
"en_JE": "en_001",
"en_JM": "en_001",
"en_KE": "en_001",
@@ -50,6 +58,8 @@
"en_LC": "en_001",
"en_LR": "en_001",
"en_LS": "en_001",
+ "en_LT": "en_150",
+ "en_LV": "en_150",
"en_MG": "en_001",
"en_MO": "en_001",
"en_MS": "en_001",
@@ -62,13 +72,17 @@
"en_NF": "en_001",
"en_NG": "en_001",
"en_NL": "en_150",
+ "en_NO": "en_150",
"en_NR": "en_001",
"en_NU": "en_001",
"en_NZ": "en_001",
"en_PG": "en_001",
"en_PK": "en_001",
+ "en_PL": "en_150",
"en_PN": "en_001",
+ "en_PT": "en_150",
"en_PW": "en_001",
+ "en_RO": "en_150",
"en_RW": "en_001",
"en_SB": "en_001",
"en_SC": "en_001",
@@ -77,6 +91,7 @@
"en_SG": "en_001",
"en_SH": "en_001",
"en_SI": "en_150",
+ "en_SK": "en_150",
"en_SL": "en_001",
"en_SS": "en_001",
"en_SX": "en_001",
@@ -87,6 +102,7 @@
"en_TT": "en_001",
"en_TV": "en_001",
"en_TZ": "en_001",
+ "en_UA": "en_150",
"en_UG": "en_001",
"en_VC": "en_001",
"en_VG": "en_001",
@@ -119,6 +135,7 @@
"es_VE": "es_419",
"ff_Adlm": "root",
"hi_Latn": "en_IN",
+ "kk_Arab": "root",
"ks_Deva": "root",
"nb": "no",
"nn": "no",
diff --git a/symfony/translation/TranslatableMessage.php b/symfony/translation/TranslatableMessage.php
index c591e68c2..8f6063c50 100644
--- a/symfony/translation/TranslatableMessage.php
+++ b/symfony/translation/TranslatableMessage.php
@@ -52,9 +52,13 @@ public function getDomain(): ?string
public function trans(TranslatorInterface $translator, ?string $locale = null): string
{
- return $translator->trans($this->getMessage(), array_map(
- static fn ($parameter) => $parameter instanceof TranslatableInterface ? $parameter->trans($translator, $locale) : $parameter,
- $this->getParameters()
- ), $this->getDomain(), $locale);
+ $parameters = $this->getParameters();
+ foreach ($parameters as $k => $v) {
+ if ($v instanceof TranslatableInterface) {
+ $parameters[$k] = $v->trans($translator, $locale);
+ }
+ }
+
+ return $translator->trans($this->getMessage(), $parameters, $this->getDomain(), $locale);
}
}
diff --git a/symfony/translation/Translator.php b/symfony/translation/Translator.php
index 1973d079f..d3396c515 100644
--- a/symfony/translation/Translator.php
+++ b/symfony/translation/Translator.php
@@ -290,7 +290,7 @@ private function dumpCatalogue(string $locale, ConfigCacheInterface $cache): voi
$this->initializeCatalogue($locale);
$fallbackContent = $this->getFallbackContent($this->catalogues[$locale]);
- $content = sprintf(<<
addFallbackCatalogue($catalogue%s);
@@ -356,10 +356,10 @@ protected function doLoadCatalogue(string $locale): void
foreach ($this->resources[$locale] as $resource) {
if (!isset($this->loaders[$resource[0]])) {
if (\is_string($resource[1])) {
- throw new RuntimeException(sprintf('No loader is registered for the "%s" format when loading the "%s" resource.', $resource[0], $resource[1]));
+ throw new RuntimeException(\sprintf('No loader is registered for the "%s" format when loading the "%s" resource.', $resource[0], $resource[1]));
}
- throw new RuntimeException(sprintf('No loader is registered for the "%s" format.', $resource[0]));
+ throw new RuntimeException(\sprintf('No loader is registered for the "%s" format.', $resource[0]));
}
$this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
}
@@ -438,7 +438,7 @@ protected function computeFallbackLocales(string $locale)
protected function assertValidLocale(string $locale)
{
if (!preg_match('/^[a-z0-9@_\\.\\-]*$/i', $locale)) {
- throw new InvalidArgumentException(sprintf('Invalid "%s" locale.', $locale));
+ throw new InvalidArgumentException(\sprintf('Invalid "%s" locale.', $locale));
}
}
diff --git a/symfony/translation/Util/XliffUtils.php b/symfony/translation/Util/XliffUtils.php
index 335c34beb..e76e12284 100644
--- a/symfony/translation/Util/XliffUtils.php
+++ b/symfony/translation/Util/XliffUtils.php
@@ -41,7 +41,7 @@ public static function getVersionNumber(\DOMDocument $dom): string
$namespace = $xliff->attributes->getNamedItem('xmlns');
if ($namespace) {
if (0 !== substr_compare('urn:oasis:names:tc:xliff:document:', $namespace->nodeValue, 0, 34)) {
- throw new InvalidArgumentException(sprintf('Not a valid XLIFF namespace "%s".', $namespace));
+ throw new InvalidArgumentException(\sprintf('Not a valid XLIFF namespace "%s".', $namespace));
}
return substr($namespace, 34);
@@ -113,7 +113,7 @@ public static function getErrorsAsString(array $xmlErrors): string
$errorsAsString = '';
foreach ($xmlErrors as $error) {
- $errorsAsString .= sprintf("[%s %s] %s (in %s - line %d, column %d)\n",
+ $errorsAsString .= \sprintf("[%s %s] %s (in %s - line %d, column %d)\n",
\LIBXML_ERR_WARNING === $error['level'] ? 'WARNING' : 'ERROR',
$error['code'],
$error['message'],
@@ -135,7 +135,7 @@ private static function getSchema(string $xliffVersion): string
$schemaSource = file_get_contents(__DIR__.'/../Resources/schemas/xliff-core-2.0.xsd');
$xmlUri = 'informativeCopiesOf3rdPartySchemas/w3c/xml.xsd';
} else {
- throw new InvalidArgumentException(sprintf('No support implemented for loading XLIFF version "%s".', $xliffVersion));
+ throw new InvalidArgumentException(\sprintf('No support implemented for loading XLIFF version "%s".', $xliffVersion));
}
return self::fixXmlLocation($schemaSource, $xmlUri);
diff --git a/symfony/translation/Writer/TranslationWriter.php b/symfony/translation/Writer/TranslationWriter.php
index 61e03cb0e..464a83c5b 100644
--- a/symfony/translation/Writer/TranslationWriter.php
+++ b/symfony/translation/Writer/TranslationWriter.php
@@ -59,14 +59,14 @@ public function getFormats(): array
public function write(MessageCatalogue $catalogue, string $format, array $options = [])
{
if (!isset($this->dumpers[$format])) {
- throw new InvalidArgumentException(sprintf('There is no dumper associated with format "%s".', $format));
+ throw new InvalidArgumentException(\sprintf('There is no dumper associated with format "%s".', $format));
}
// get the right dumper
$dumper = $this->dumpers[$format];
if (isset($options['path']) && !is_dir($options['path']) && !@mkdir($options['path'], 0777, true) && !is_dir($options['path'])) {
- throw new RuntimeException(sprintf('Translation Writer was not able to create directory "%s".', $options['path']));
+ throw new RuntimeException(\sprintf('Translation Writer was not able to create directory "%s".', $options['path']));
}
// save