From 1696353f17340133604890f1a313718fd09f5c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sun, 1 Dec 2024 19:30:20 +0100 Subject: [PATCH 01/57] [HttpFoundation] Fixed `IpUtils::anonymize` exception when using IPv6 link-local addresses with RFC4007 scoping --- src/Symfony/Component/HttpFoundation/IpUtils.php | 10 ++++++++++ .../Component/HttpFoundation/Tests/IpUtilsTest.php | 1 + 2 files changed, 11 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/IpUtils.php b/src/Symfony/Component/HttpFoundation/IpUtils.php index ceab620c2f560..18b1c5faf6af3 100644 --- a/src/Symfony/Component/HttpFoundation/IpUtils.php +++ b/src/Symfony/Component/HttpFoundation/IpUtils.php @@ -182,6 +182,16 @@ public static function checkIp6(string $requestIp, string $ip): bool */ public static function anonymize(string $ip): string { + /** + * If the IP contains a % symbol, then it is a local-link address with scoping according to RFC 4007 + * In that case, we only care about the part before the % symbol, as the following functions, can only work with + * the IP address itself. As the scope can leak information (containing interface name), we do not want to + * include it in our anonymized IP data. + */ + if (str_contains($ip, '%')) { + $ip = substr($ip, 0, strpos($ip, '%')); + } + $wrappedIPv6 = false; if (str_starts_with($ip, '[') && str_ends_with($ip, ']')) { $wrappedIPv6 = true; diff --git a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php index ce93c69e90043..2a86fbc2dfed9 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php @@ -147,6 +147,7 @@ public static function anonymizedIpData() ['[2a01:198::3]', '[2a01:198::]'], ['::ffff:123.234.235.236', '::ffff:123.234.235.0'], // IPv4-mapped IPv6 addresses ['::123.234.235.236', '::123.234.235.0'], // deprecated IPv4-compatible IPv6 address + ['fe80::1fc4:15d8:78db:2319%enp4s0', 'fe80::'], // IPv6 link-local with RFC4007 scoping ]; } From 6eaf6df00db0b1e0679038c5b14c909185d90531 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Tue, 7 Jan 2025 22:40:30 +0100 Subject: [PATCH 02/57] [Validator] Review Croatian translations --- .../Resources/translations/validators.hr.xlf | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf index 7b14181ec91d6..a436950b27258 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf @@ -444,31 +444,31 @@ This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Ova vrijednost je prekratka. Trebala bi sadržavati barem jednu riječ.|Ova vrijednost je prekratka. Trebala bi sadržavati barem {{ min }} riječi. + Ova vrijednost je prekratka. Trebala bi sadržavati barem jednu riječ.|Ova vrijednost je prekratka. Trebala bi sadržavati barem {{ min }} riječi. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Ova vrijednost je predugačka. Trebala bi sadržavati samo jednu riječ.|Ova vrijednost je predugačka. Trebala bi sadržavati {{ max }} riječi ili manje. + Ova vrijednost je predugačka. Trebala bi sadržavati samo jednu riječ.|Ova vrijednost je predugačka. Trebala bi sadržavati {{ max }} riječi ili manje. This value does not represent a valid week in the ISO 8601 format. - Ova vrijednost ne predstavlja valjani tjedan u ISO 8601 formatu. + Ova vrijednost ne predstavlja valjani tjedan u ISO 8601 formatu. This value is not a valid week. - Ova vrijednost nije valjani tjedan. + Ova vrijednost nije valjani tjedan. This value should not be before week "{{ min }}". - Ova vrijednost ne bi trebala biti prije tjedna "{{ min }}". + Ova vrijednost ne bi trebala biti prije tjedna "{{ min }}". This value should not be after week "{{ max }}". - Ova vrijednost ne bi trebala biti nakon tjedna "{{ max }}". + Ova vrijednost ne bi trebala biti nakon tjedna "{{ max }}". This value is not a valid slug. - Ova vrijednost nije valjani slug. + Ova vrijednost nije valjani slug. From 6e5fc5d95cb36d2cd593e3bdac54b259554cd8a7 Mon Sep 17 00:00:00 2001 From: Ionut Enache Date: Wed, 8 Jan 2025 11:07:25 +0200 Subject: [PATCH 03/57] Review validator-related romanian translations with ids 114-120 --- .../Resources/translations/validators.ro.xlf | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf index 610b0e733f5f9..73dc6f2e0d235 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf @@ -444,31 +444,31 @@ This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Această valoare este prea scurtă. Ar trebui să conțină cel puțin un cuvânt.|Această valoare este prea scurtă. Ar trebui să conțină cel puțin {{ min }} cuvinte. + Această valoare este prea scurtă. Trebuie să conțină cel puțin un cuvânt.|Această valoare este prea scurtă. Trebuie să conțină cel puțin {{ min }} cuvinte. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Această valoare este prea lungă. Ar trebui să conțină doar un cuvânt.|Această valoare este prea lungă. Ar trebui să conțină {{ max }} cuvinte sau mai puține. + Această valoare este prea lungă. Trebuie să conțină un singur cuvânt.|Această valoare este prea lungă. Trebuie să conțină cel mult {{ max }} cuvinte. This value does not represent a valid week in the ISO 8601 format. - Această valoare nu reprezintă o săptămână validă în formatul ISO 8601. + Această valoare nu reprezintă o săptămână validă în formatul ISO 8601. This value is not a valid week. - Această valoare nu este o săptămână validă. + Această valoare nu este o săptămână validă. This value should not be before week "{{ min }}". - Această valoare nu trebuie să fie înainte de săptămâna "{{ min }}". + Această valoare nu trebuie să fie înainte de săptămâna "{{ min }}". This value should not be after week "{{ max }}". - Această valoare nu trebuie să fie după săptămâna "{{ max }}". + Această valoare nu trebuie să fie după săptămâna "{{ max }}". This value is not a valid slug. - Această valoare nu este un slug valid. + Această valoare nu este un slug valid. From 51c32ef9b6bd9188c5feb97f4579113ca826a55e Mon Sep 17 00:00:00 2001 From: "Phil E. Taylor" Date: Fri, 29 Nov 2024 16:35:04 +0000 Subject: [PATCH 04/57] [HttpClient] Fix Undefined array key "connection" #59044 Signed-off-by: Phil E. Taylor --- .../Component/HttpClient/Response/CurlResponse.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpClient/Response/CurlResponse.php b/src/Symfony/Component/HttpClient/Response/CurlResponse.php index 4cb2a30976d46..88cb764384dad 100644 --- a/src/Symfony/Component/HttpClient/Response/CurlResponse.php +++ b/src/Symfony/Component/HttpClient/Response/CurlResponse.php @@ -312,7 +312,16 @@ private static function perform(ClientState $multi, ?array &$responses = null): } $multi->handlesActivity[$id][] = null; - $multi->handlesActivity[$id][] = \in_array($result, [\CURLE_OK, \CURLE_TOO_MANY_REDIRECTS], true) || '_0' === $waitFor || curl_getinfo($ch, \CURLINFO_SIZE_DOWNLOAD) === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) || (curl_error($ch) === 'OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 0' && -1.0 === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) && \in_array('close', array_map('strtolower', $responses[$id]->headers['connection']), true)) ? null : new TransportException(ucfirst(curl_error($ch) ?: curl_strerror($result)).sprintf(' for "%s".', curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL))); + $multi->handlesActivity[$id][] = \in_array($result, [\CURLE_OK, \CURLE_TOO_MANY_REDIRECTS], true) + || '_0' === $waitFor + || curl_getinfo($ch, \CURLINFO_SIZE_DOWNLOAD) === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) + || ('C' === $waitFor[0] + && 'OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 0' === curl_error($ch) + && -1.0 === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) + && \in_array('close', array_map('strtolower', $responses[$id]->headers['connection'] ?? []), true) + ) + ? null + : new TransportException(ucfirst(curl_error($ch) ?: curl_strerror($result)).\sprintf(' for "%s".', curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL))); } } finally { $multi->performing = false; From 74dc4d2d522d11b9b5e400798f9b19154162a428 Mon Sep 17 00:00:00 2001 From: Kurt Thiemann Date: Sat, 16 Nov 2024 19:21:25 +0100 Subject: [PATCH 05/57] [HttpClient] Ignore RuntimeExceptions thrown when rewinding the PSR-7 created in HttplugWaitLoop::createPsr7Response --- src/Symfony/Component/HttpClient/HttplugClient.php | 12 ++++++++++-- .../HttpClient/Internal/HttplugWaitLoop.php | 6 +++++- src/Symfony/Component/HttpClient/Psr18Client.php | 12 ++++++++++-- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/HttpClient/HttplugClient.php b/src/Symfony/Component/HttpClient/HttplugClient.php index b0a6d4a8cdf02..b01579d06f27a 100644 --- a/src/Symfony/Component/HttpClient/HttplugClient.php +++ b/src/Symfony/Component/HttpClient/HttplugClient.php @@ -202,7 +202,11 @@ public function createStream($content = ''): StreamInterface } if ($stream->isSeekable()) { - $stream->seek(0); + try { + $stream->seek(0); + } catch (\RuntimeException) { + // ignore + } } return $stream; @@ -274,7 +278,11 @@ private function sendPsr7Request(RequestInterface $request, ?bool $buffer = null $body = $request->getBody(); if ($body->isSeekable()) { - $body->seek(0); + try { + $body->seek(0); + } catch (\RuntimeException) { + // ignore + } } $options = [ diff --git a/src/Symfony/Component/HttpClient/Internal/HttplugWaitLoop.php b/src/Symfony/Component/HttpClient/Internal/HttplugWaitLoop.php index bebe135604a4e..1412fcf45466e 100644 --- a/src/Symfony/Component/HttpClient/Internal/HttplugWaitLoop.php +++ b/src/Symfony/Component/HttpClient/Internal/HttplugWaitLoop.php @@ -145,7 +145,11 @@ public static function createPsr7Response(ResponseFactoryInterface $responseFact } if ($body->isSeekable()) { - $body->seek(0); + try { + $body->seek(0); + } catch (\RuntimeException) { + // ignore + } } return $psrResponse->withBody($body); diff --git a/src/Symfony/Component/HttpClient/Psr18Client.php b/src/Symfony/Component/HttpClient/Psr18Client.php index d46a7b14d19a7..f138f55e81d92 100644 --- a/src/Symfony/Component/HttpClient/Psr18Client.php +++ b/src/Symfony/Component/HttpClient/Psr18Client.php @@ -90,7 +90,11 @@ public function sendRequest(RequestInterface $request): ResponseInterface $body = $request->getBody(); if ($body->isSeekable()) { - $body->seek(0); + try { + $body->seek(0); + } catch (\RuntimeException) { + // ignore + } } $options = [ @@ -136,7 +140,11 @@ public function createStream(string $content = ''): StreamInterface $stream = $this->streamFactory->createStream($content); if ($stream->isSeekable()) { - $stream->seek(0); + try { + $stream->seek(0); + } catch (\RuntimeException) { + // ignore + } } return $stream; From 2f94a5875ef105f7db70fa53b2a40102dcb0108a Mon Sep 17 00:00:00 2001 From: Norbert Schvoy Date: Thu, 9 Jan 2025 00:18:23 +0100 Subject: [PATCH 06/57] [Validator] Review Hungarian translations, fix typo --- .../Resources/translations/validators.hu.xlf | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf index 7bdb8983e1a7d..ebeb01d47beac 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf @@ -408,7 +408,7 @@ The password strength is too low. Please use a stronger password. - A jelszó túl egyszerű. Kérjük, használjon egy bonyolultabb jelszót. + A jelszó túl egyszerű. Kérjük, használjon egy erősebb jelszót. This value contains characters that are not allowed by the current restriction-level. @@ -416,7 +416,7 @@ Using invisible characters is not allowed. - Láthatatlan karaktert használata nem megengedett. + Láthatatlan karakterek használata nem megengedett. Mixing numbers from different scripts is not allowed. @@ -444,31 +444,31 @@ This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Ez az érték túl rövid. Tartalmaznia kell legalább egy szót.|Ez az érték túl rövid. Tartalmaznia kell legalább {{ min }} szót. + Ez az érték túl rövid. Tartalmaznia kell legalább egy szót.|Ez az érték túl rövid. Tartalmaznia kell legalább {{ min }} szót. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Ez az érték túl hosszú. Csak egy szót tartalmazhat.|Ez az érték túl hosszú. {{ max }} vagy kevesebb szót tartalmazhat. + Ez az érték túl hosszú. Csak egy szót tartalmazhat.|Ez az érték túl hosszú. Legfeljebb {{ max }} szót vagy kevesebbet tartalmazhat. This value does not represent a valid week in the ISO 8601 format. - Ez a érték nem érvényes hetet jelent az ISO 8601 formátumban. + Ez a érték érvénytelen hetet jelent az ISO 8601 formátumban. This value is not a valid week. - Ez az érték nem érvényes hét. + Ez az érték érvénytelen hét. This value should not be before week "{{ min }}". - Ennek az értéknek nem szabad a "{{ min }}" hét előtt lennie. + Ez az érték nem lehet a "{{ min }}". hétnél korábbi. This value should not be after week "{{ max }}". - Ez az érték nem lehet a "{{ max }}" hét után. + Ez az érték nem lehet a "{{ max }}". hétnél későbbi. This value is not a valid slug. - Ez az érték nem érvényes slug. + Ez az érték nem érvényes slug. From c21192134adca965c68ba8cc08617c3460264897 Mon Sep 17 00:00:00 2001 From: Link1515 Date: Thu, 9 Jan 2025 13:52:26 +0800 Subject: [PATCH 07/57] chore: update Chinese (zh-TW) translations --- .../Validator/Resources/translations/validators.zh_TW.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf index 9d36613267875..fc343e6c8d010 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf @@ -468,7 +468,7 @@ This value is not a valid slug. - 此值不是有效的 slug。 + 這個數值不是有效的 slug。 From ecbaff0138f88f7e30d42a8a1b9cbd696f519d74 Mon Sep 17 00:00:00 2001 From: matlec Date: Wed, 8 Jan 2025 09:44:49 +0100 Subject: [PATCH 08/57] =?UTF-8?q?[Routing]=20Fix=20configuring=20a=20singl?= =?UTF-8?q?e=20route=E2=80=99=20hosts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Loader/Configurator/RouteConfigurator.php | 7 ++++++ .../Routing/Loader/XmlFileLoader.php | 4 +++- .../Routing/Loader/YamlFileLoader.php | 4 +++- .../route-with-hosts-expected-collection.php | 23 +++++++++++++++++++ .../locale_and_host/route-with-hosts.php | 10 ++++++++ .../locale_and_host/route-with-hosts.xml | 10 ++++++++ .../locale_and_host/route-with-hosts.yml | 6 +++++ .../Tests/Loader/PhpFileLoaderTest.php | 10 ++++++++ .../Tests/Loader/XmlFileLoaderTest.php | 10 ++++++++ .../Tests/Loader/YamlFileLoaderTest.php | 10 ++++++++ 10 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts-expected-collection.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts.xml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts.yml diff --git a/src/Symfony/Component/Routing/Loader/Configurator/RouteConfigurator.php b/src/Symfony/Component/Routing/Loader/Configurator/RouteConfigurator.php index d9d441da19a37..26a2e3857e09e 100644 --- a/src/Symfony/Component/Routing/Loader/Configurator/RouteConfigurator.php +++ b/src/Symfony/Component/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/src/Symfony/Component/Routing/Loader/XmlFileLoader.php b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php index 2518161ae0c9b..1e3e3283dcab0 100644 --- a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php @@ -135,7 +135,7 @@ protected function parseRoute(RouteCollection $collection, \DOMElement $node, st 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); } /** diff --git a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php index 9605e9a8772e0..09beb7cd54739 100644 --- a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php @@ -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); } /** diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts-expected-collection.php b/src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts-expected-collection.php new file mode 100644 index 0000000000000..afff1f0bcdcfe --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts-expected-collection.php @@ -0,0 +1,23 @@ +add('static.en', $route = new Route('/example')); + $route->setHost('www.example.com'); + $route->setRequirement('_locale', 'en'); + $route->setDefault('_locale', 'en'); + $route->setDefault('_canonical_route', 'static'); + $expectedRoutes->add('static.nl', $route = new Route('/example')); + $route->setHost('www.example.nl'); + $route->setRequirement('_locale', 'nl'); + $route->setDefault('_locale', 'nl'); + $route->setDefault('_canonical_route', 'static'); + + $expectedRoutes->addResource(new FileResource(__DIR__."/route-with-hosts.$format")); + + return $expectedRoutes; +}; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts.php b/src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts.php new file mode 100644 index 0000000000000..44472d77ae171 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts.php @@ -0,0 +1,10 @@ +add('static', '/example')->host([ + 'nl' => 'www.example.nl', + 'en' => 'www.example.com', + ]); +}; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts.xml b/src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts.xml new file mode 100644 index 0000000000000..f4b16e4d80700 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts.xml @@ -0,0 +1,10 @@ + + + + www.example.nl + www.example.com + + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts.yml b/src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts.yml new file mode 100644 index 0000000000000..c340f71ff016d --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/locale_and_host/route-with-hosts.yml @@ -0,0 +1,6 @@ +--- +static: + path: /example + host: + nl: www.example.nl + en: www.example.com diff --git a/src/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php index dbe45bcf82ec2..2ec8bd04ddacc 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php @@ -317,6 +317,16 @@ public function testImportingRoutesWithSingleHostInImporter() $this->assertEquals($expectedRoutes('php'), $routes); } + public function testAddingRouteWithHosts() + { + $loader = new PhpFileLoader(new FileLocator([__DIR__.'/../Fixtures/locale_and_host'])); + $routes = $loader->load('route-with-hosts.php'); + + $expectedRoutes = require __DIR__.'/../Fixtures/locale_and_host/route-with-hosts-expected-collection.php'; + + $this->assertEquals($expectedRoutes('php'), $routes); + } + public function testImportingAliases() { $loader = new PhpFileLoader(new FileLocator([__DIR__.'/../Fixtures/alias'])); diff --git a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php index 9e42db7a7e6fe..83859120e31f8 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php @@ -577,6 +577,16 @@ public function testImportingRoutesWithSingleHostsInImporter() $this->assertEquals($expectedRoutes('xml'), $routes); } + public function testAddingRouteWithHosts() + { + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/locale_and_host'])); + $routes = $loader->load('route-with-hosts.xml'); + + $expectedRoutes = require __DIR__.'/../Fixtures/locale_and_host/route-with-hosts-expected-collection.php'; + + $this->assertEquals($expectedRoutes('xml'), $routes); + } + public function testWhenEnv() { $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures']), 'some-env'); diff --git a/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php index 6573fd0138ac8..1e34386818e6b 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php @@ -443,6 +443,16 @@ public function testImportingRoutesWithSingleHostInImporter() $this->assertEquals($expectedRoutes('yml'), $routes); } + public function testAddingRouteWithHosts() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/locale_and_host'])); + $routes = $loader->load('route-with-hosts.yml'); + + $expectedRoutes = require __DIR__.'/../Fixtures/locale_and_host/route-with-hosts-expected-collection.php'; + + $this->assertEquals($expectedRoutes('yml'), $routes); + } + public function testWhenEnv() { $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures']), 'some-env'); From a2f70401ecf28681f1c7fa413f06fe42ea1ff43e Mon Sep 17 00:00:00 2001 From: Nikita Sklyarov Date: Thu, 9 Jan 2025 12:33:41 +0200 Subject: [PATCH 09/57] [Validator] Review and reword Ukrainian translation --- .../Resources/translations/validators.uk.xlf | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf index c952f2abe25b3..f83a179b1c37a 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf @@ -444,31 +444,31 @@ This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Це значення занадто коротке. Воно має містити принаймні одне слово.|Це значення занадто коротке. Воно має містити принаймні {{ min }} слова. + Це значення занадто коротке. Воно має містити принаймні одне слово.|Це значення занадто коротке. Мінімальна кількість слів — {{ min }}. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Це значення занадто довге. Воно має містити лише одне слово.|Це значення занадто довге. Воно має містити {{ max }} слова або менше. + Це значення занадто довге. Воно має містити лише одне слово.|Це значення занадто довге. Максимальна кількість слів — {{ max }}. This value does not represent a valid week in the ISO 8601 format. - Це значення не представляє дійсний тиждень у форматі ISO 8601. + Це значення не представляє дійсний тиждень у форматі ISO 8601. This value is not a valid week. - Це значення не є дійсним тижнем. + Це значення не є дійсним тижнем. This value should not be before week "{{ min }}". - Це значення не повинно бути раніше тижня "{{ min }}". + Це значення не повинно бути раніше тижня "{{ min }}". This value should not be after week "{{ max }}". - Це значення не повинно бути після тижня "{{ max }}". + Це значення не повинно бути після тижня "{{ max }}". This value is not a valid slug. - Це значення не є дійсним slug. + Це значення не є дійсним slug. From b0c2a59f37d8490fdfad3ea251204b6ead50d6b2 Mon Sep 17 00:00:00 2001 From: matlec Date: Thu, 9 Jan 2025 12:51:25 +0100 Subject: [PATCH 10/57] [VarDumper] Fix blank strings display --- .../Component/VarDumper/Dumper/HtmlDumper.php | 81 ++++++++++--------- .../Tests/Caster/ExceptionCasterTest.php | 8 +- .../VarDumper/Tests/Caster/StubCasterTest.php | 4 +- .../VarDumper/Tests/Dumper/HtmlDumperTest.php | 20 ++--- 4 files changed, 59 insertions(+), 54 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php index ea09e68194cb1..cb41112792dfa 100644 --- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php @@ -663,7 +663,7 @@ function showCurrent(state) height: 0; clear: both; } -pre.sf-dump span { +pre.sf-dump .sf-dump-ellipsization { display: inline-flex; } pre.sf-dump a { @@ -681,16 +681,12 @@ function showCurrent(state) background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAHUlEQVQY02O8zAABilCaiQEN0EeA8QuUcX9g3QEAAjcC5piyhyEAAAAASUVORK5CYII=) #D3D3D3; } pre.sf-dump .sf-dump-ellipsis { - display: inline-block; - overflow: visible; text-overflow: ellipsis; - max-width: 5em; white-space: nowrap; overflow: hidden; - vertical-align: top; } -pre.sf-dump .sf-dump-ellipsis+.sf-dump-ellipsis { - max-width: none; +pre.sf-dump .sf-dump-ellipsis-tail { + flex-shrink: 0; } pre.sf-dump code { display:inline; @@ -863,66 +859,75 @@ protected function style(string $style, string $value, array $attr = []): string return sprintf('%s', $this->dumpId, $r, 1 + $attr['count'], $v); } + $dumpClasses = ['sf-dump-'.$style]; + $dumpTitle = ''; + if ('const' === $style && isset($attr['value'])) { - $style .= sprintf(' title="%s"', esc(\is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value']))); + $dumpTitle = esc(\is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value'])); } elseif ('public' === $style) { - $style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property'); + $dumpTitle = empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property'; } elseif ('str' === $style && 1 < $attr['length']) { - $style .= sprintf(' title="%d%s characters"', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : ''); + $dumpTitle = sprintf('%d%s characters', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : ''); } elseif ('note' === $style && 0 < ($attr['depth'] ?? 0) && false !== $c = strrpos($value, '\\')) { - $style .= ' title=""'; $attr += [ 'ellipsis' => \strlen($value) - $c, 'ellipsis-type' => 'note', 'ellipsis-tail' => 1, ]; } elseif ('protected' === $style) { - $style .= ' title="Protected property"'; + $dumpTitle = 'Protected property'; } elseif ('meta' === $style && isset($attr['title'])) { - $style .= sprintf(' title="%s"', esc($this->utf8Encode($attr['title']))); + $dumpTitle = esc($this->utf8Encode($attr['title'])); } elseif ('private' === $style) { - $style .= sprintf(' title="Private property defined in class: `%s`"', esc($this->utf8Encode($attr['class']))); + $dumpTitle = sprintf('Private property defined in class: `%s`"', esc($this->utf8Encode($attr['class']))); } if (isset($attr['ellipsis'])) { - $class = 'sf-dump-ellipsis'; + $dumpClasses[] = 'sf-dump-ellipsization'; + $ellipsisClass = 'sf-dump-ellipsis'; if (isset($attr['ellipsis-type'])) { - $class = sprintf('"%s sf-dump-ellipsis-%s"', $class, $attr['ellipsis-type']); + $ellipsisClass .= ' sf-dump-ellipsis-'.$attr['ellipsis-type']; } $label = esc(substr($value, -$attr['ellipsis'])); - $style = str_replace(' title="', " title=\"$v\n", $style); - $v = sprintf('%s', $class, substr($v, 0, -\strlen($label))); + $dumpTitle = $v."\n".$dumpTitle; + $v = sprintf('%s', $ellipsisClass, substr($v, 0, -\strlen($label))); if (!empty($attr['ellipsis-tail'])) { $tail = \strlen(esc(substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']))); - $v .= sprintf('%s%s', $class, substr($label, 0, $tail), substr($label, $tail)); + $v .= sprintf('%s%s', $ellipsisClass, substr($label, 0, $tail), substr($label, $tail)); } else { - $v .= $label; + $v .= sprintf('%s', $label); } } $map = static::$controlCharsMap; - $v = "".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) { - $s = $b = '%s', + 1 === count($dumpClasses) ? '' : '"', + implode(' ', $dumpClasses), + $dumpTitle ? ' title="'.$dumpTitle.'"' : '', + preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) { + $s = $b = ''; - }, $v).''; + return $s.''; + }, $v) + ); if (!($attr['binary'] ?? false)) { $v = preg_replace_callback(static::$unicodeCharsRx, function ($c) { diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php index f8fe43d8ddcee..dcdc36715c1ab 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php @@ -259,12 +259,12 @@ public function testHtmlDump() Exception { #message: "1" #code: 0 - #file: "%s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php" + #file: "%s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php" #line: %d trace: { - %s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php:%d + %s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php:%d …%d } } diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/StubCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/StubCasterTest.php index cf0bc7338326d..eb110b481aec8 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/StubCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/StubCasterTest.php @@ -175,8 +175,8 @@ public function testClassStubWithNotExistingClass() $expectedDump = <<<'EODUMP' array:1 [ - 0 => "Symfony\Component\VarDumper\Tests\Caster\NotExisting" + 0 => "Symfony\Component\VarDumper\Tests\Caster\NotExisting" ] EODUMP; diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/HtmlDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/HtmlDumperTest.php index 9b914ad6d3c37..d843e14371f69 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/HtmlDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/HtmlDumperTest.php @@ -79,18 +79,18 @@ public function testGet() seekable: true %A options: [] } - "obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d + "obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d +foo: "foo" +"bar": "bar" } "closure" => Closure(\$a, ?PDO &\$b = null) {#%d - class: "Symfony\Component\VarDumper\Tests\Dumper\HtmlDumperTest" - this: Symfony\Component\VarDumper\Tests\Dumper\HtmlDumperTest {#%d &%s;} - file: "%s%eVarDumper%eTests%eFixtures%edumb-var.php" + class: "Symfony\Component\VarDumper\Tests\Dumper\HtmlDumperTest" + this: Symfony\Component\VarDumper\Tests\Dumper\HtmlDumperTest {#%d &%s;} + file: "%s%eVarDumper%eTests%eFixtures%edumb-var.php" line: "{$var['line']} to {$var['line']}" } "line" => {$var['line']} @@ -101,8 +101,8 @@ public function testGet() 0 => &4 array:1 [&4] ] 8 => &1 null - "sobj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d} + "sobj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d} "snobj" => &3 {#%d} "snobj2" => {#%d} "file" => "{$var['file']}" From 438b58ceadd61ac051976c3d2efe07943ec9a323 Mon Sep 17 00:00:00 2001 From: Halil Hakan Karabay Date: Wed, 8 Jan 2025 23:27:54 +0300 Subject: [PATCH 11/57] [Validator] Checked Turkish validators translations and confirmed --- .../Validator/Resources/translations/validators.tr.xlf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf index 75312780dab03..fa69fb2e19e64 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf @@ -192,7 +192,7 @@ No temporary folder was configured in php.ini, or the configured folder does not exist. - php.ini'de geçici bir klasör yapılandırılmadı, veya yapılandırılan klasör mevcut değildir. + php.ini'de geçici bir klasör yapılandırılmadı veya yapılandırılan klasör mevcut değildir. Cannot write temporary file to disk. @@ -468,7 +468,7 @@ This value is not a valid slug. - Bu değer geçerli bir slug değildir. + Bu değer geçerli bir “slug” değildir. From 9807ce6058f4502ff1e743d613eb240a91d9e97d Mon Sep 17 00:00:00 2001 From: matlec Date: Tue, 7 Jan 2025 14:43:18 +0100 Subject: [PATCH 12/57] [DomCrawler] Make `ChoiceFormField::isDisabled` return `true` for unchecked disabled checkboxes --- .../Component/DomCrawler/Field/ChoiceFormField.php | 4 ++++ .../DomCrawler/Tests/Field/ChoiceFormFieldTest.php | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php index dcae5490ad35c..7688b6d7e63d3 100644 --- a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php +++ b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php @@ -45,6 +45,10 @@ public function hasValue(): bool */ public function isDisabled(): bool { + if ('checkbox' === $this->type) { + return parent::isDisabled(); + } + if (parent::isDisabled() && 'select' === $this->type) { return true; } diff --git a/src/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php b/src/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php index 176ea5927fe1c..5de407344d2f8 100644 --- a/src/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php @@ -272,6 +272,17 @@ public function testCheckboxWithEmptyBooleanAttribute() $this->assertEquals('foo', $field->getValue()); } + public function testCheckboxIsDisabled() + { + $node = $this->createNode('input', '', ['type' => 'checkbox', 'name' => 'name', 'disabled' => '']); + $field = new ChoiceFormField($node); + + $this->assertTrue($field->isDisabled(), '->isDisabled() returns true when the checkbox is disabled, even if it is not checked'); + + $field->tick(); + $this->assertTrue($field->isDisabled(), '->isDisabled() returns true when the checkbox is disabled, even if it is checked'); + } + public function testTick() { $node = $this->createSelectNode(['foo' => false, 'bar' => false]); From 75e7454b2ed2a35ccc4afbafd6a7a78c810c34a5 Mon Sep 17 00:00:00 2001 From: PatNowak Date: Wed, 8 Jan 2025 12:21:20 +0100 Subject: [PATCH 13/57] [Translations] Make sure PL translations validators.pl.xlf follow the same style --- .../Resources/translations/validators.pl.xlf | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf index 592a5c6209cc8..8946381120ae7 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf @@ -440,35 +440,35 @@ This URL is missing a top-level domain. - Podany URL nie zawiera domeny najwyższego poziomu. + Ten URL nie zawiera domeny najwyższego poziomu. This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Podana wartość jest zbyt krótka. Powinna zawierać co najmniej jedno słowo.|Podana wartość jest zbyt krótka. Powinna zawierać co najmniej {{ min }} słów. + Ta wartość jest zbyt krótka. Powinna zawierać co najmniej jedno słowo.|Ta wartość jest zbyt krótka. Powinna zawierać co najmniej {{ min }} słów. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Podana wartość jest zbyt długa. Powinna zawierać jedno słowo.|Podana wartość jest zbyt długa. Powinna zawierać {{ max }} słów lub mniej. + Ta wartość jest zbyt długa. Powinna zawierać jedno słowo.|Ta wartość jest zbyt długa. Powinna zawierać {{ max }} słów lub mniej. This value does not represent a valid week in the ISO 8601 format. - Podana wartość nie jest poprawnym oznaczeniem tygodnia w formacie ISO 8601. + Ta wartość nie jest poprawnym oznaczeniem tygodnia w formacie ISO 8601. This value is not a valid week. - Podana wartość nie jest poprawnym oznaczeniem tygodnia. + Ta wartość nie jest poprawnym oznaczeniem tygodnia. This value should not be before week "{{ min }}". - Podana wartość nie powinna być przed tygodniem "{{ min }}". + Ta wartość nie powinna być przed tygodniem "{{ min }}". This value should not be after week "{{ max }}". - Podana wartość nie powinna być po tygodniu "{{ max }}". + Ta wartość nie powinna być po tygodniu "{{ max }}". This value is not a valid slug. - Ta wartość nie jest prawidłowym slugiem. + Ta wartość nie jest prawidłowym slugiem. From ed18c7ce46663eb4e5b20ed15d8c18c2a9348ec3 Mon Sep 17 00:00:00 2001 From: skmedix Date: Tue, 7 Jan 2025 20:44:28 +0100 Subject: [PATCH 14/57] [Mailer] Fix SMTP stream EOF handling on Windows by using feof() --- .../Mailer/Transport/Smtp/Stream/AbstractStream.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Mailer/Transport/Smtp/Stream/AbstractStream.php b/src/Symfony/Component/Mailer/Transport/Smtp/Stream/AbstractStream.php index 498dc560c3ede..55a2594ac1de5 100644 --- a/src/Symfony/Component/Mailer/Transport/Smtp/Stream/AbstractStream.php +++ b/src/Symfony/Component/Mailer/Transport/Smtp/Stream/AbstractStream.php @@ -80,11 +80,10 @@ public function readLine(): string $line = @fgets($this->out); if ('' === $line || false === $line) { - $metas = stream_get_meta_data($this->out); - if ($metas['timed_out']) { + if (stream_get_meta_data($this->out)['timed_out']) { throw new TransportException(sprintf('Connection to "%s" timed out.', $this->getReadConnectionDescription())); } - if ($metas['eof']) { + if (feof($this->out)) { // don't use "eof" metadata, it's not accurate on Windows throw new TransportException(sprintf('Connection to "%s" has been closed unexpectedly.', $this->getReadConnectionDescription())); } if (false === $line) { From 56f3df494c1d3be1e6df3a869b2e9e8099bc0b2e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 7 Jan 2025 18:11:41 +0100 Subject: [PATCH 15/57] [HttpFoundation][FrameworkBundle] Reset Request's formats using the service resetter --- .../Command/ContainerDebugCommand.php | 8 ++++++-- .../FrameworkBundle/Resources/config/services.php | 1 + .../Tests/Functional/ContainerDebugCommandTest.php | 12 ++++++------ .../Component/HttpFoundation/RequestStack.php | 7 +++++++ .../HttpFoundation/Tests/RequestStackTest.php | 14 ++++++++++++++ 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php index df6aef5dd6b3e..3000da51a7a11 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php @@ -284,7 +284,9 @@ private function findProperServiceName(InputInterface $input, SymfonyStyle $io, return $matchingServices[0]; } - return $io->choice('Select one of the following services to display its information', $matchingServices); + natsort($matchingServices); + + return $io->choice('Select one of the following services to display its information', array_values($matchingServices)); } private function findProperTagName(InputInterface $input, SymfonyStyle $io, ContainerBuilder $container, string $tagName): string @@ -302,7 +304,9 @@ private function findProperTagName(InputInterface $input, SymfonyStyle $io, Cont return $matchingTags[0]; } - return $io->choice('Select one of the following tags to display its information', $matchingTags); + natsort($matchingTags); + + return $io->choice('Select one of the following tags to display its information', array_values($matchingTags)); } private function findServiceIdsContaining(ContainerBuilder $container, string $name, bool $showHidden): array diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php index 905e16f9b9e9c..5f280bdfbb242 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php @@ -100,6 +100,7 @@ class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : [] ->alias(HttpKernelInterface::class, 'http_kernel') ->set('request_stack', RequestStack::class) + ->tag('kernel.reset', ['method' => 'resetRequestFormats', 'on_invalid' => 'ignore']) ->public() ->alias(RequestStack::class, 'request_stack') diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php index efbc1f54acb08..1adddd1832500 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php @@ -140,13 +140,13 @@ public function testTagsPartialSearch() $tester->run(['command' => 'debug:container', '--tag' => 'kernel.'], ['decorated' => false]); $this->assertStringContainsString('Select one of the following tags to display its information', $tester->getDisplay()); - $this->assertStringContainsString('[0] kernel.event_subscriber', $tester->getDisplay()); - $this->assertStringContainsString('[1] kernel.locale_aware', $tester->getDisplay()); - $this->assertStringContainsString('[2] kernel.cache_warmer', $tester->getDisplay()); + $this->assertStringContainsString('[0] kernel.cache_clearer', $tester->getDisplay()); + $this->assertStringContainsString('[1] kernel.cache_warmer', $tester->getDisplay()); + $this->assertStringContainsString('[2] kernel.event_subscriber', $tester->getDisplay()); $this->assertStringContainsString('[3] kernel.fragment_renderer', $tester->getDisplay()); - $this->assertStringContainsString('[4] kernel.reset', $tester->getDisplay()); - $this->assertStringContainsString('[5] kernel.cache_clearer', $tester->getDisplay()); - $this->assertStringContainsString('Symfony Container Services Tagged with "kernel.event_subscriber" Tag', $tester->getDisplay()); + $this->assertStringContainsString('[4] kernel.locale_aware', $tester->getDisplay()); + $this->assertStringContainsString('[5] kernel.reset', $tester->getDisplay()); + $this->assertStringContainsString('Symfony Container Services Tagged with "kernel.cache_clearer" Tag', $tester->getDisplay()); } public function testDescribeEnvVars() diff --git a/src/Symfony/Component/HttpFoundation/RequestStack.php b/src/Symfony/Component/HttpFoundation/RequestStack.php index 5aa8ba793414c..ca61eef2953e2 100644 --- a/src/Symfony/Component/HttpFoundation/RequestStack.php +++ b/src/Symfony/Component/HttpFoundation/RequestStack.php @@ -106,4 +106,11 @@ public function getSession(): SessionInterface throw new SessionNotFoundException(); } + + public function resetRequestFormats(): void + { + static $resetRequestFormats; + $resetRequestFormats ??= \Closure::bind(static fn () => self::$formats = null, null, Request::class); + $resetRequestFormats(); + } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestStackTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestStackTest.php index 2b26ce5c64aea..3b958653f0bfa 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestStackTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestStackTest.php @@ -67,4 +67,18 @@ public function testGetParentRequest() $requestStack->push($secondSubRequest); $this->assertSame($firstSubRequest, $requestStack->getParentRequest()); } + + public function testResetRequestFormats() + { + $requestStack = new RequestStack(); + + $request = Request::create('/foo'); + $request->setFormat('foo', ['application/foo']); + + $this->assertSame(['application/foo'], $request->getMimeTypes('foo')); + + $requestStack->resetRequestFormats(); + + $this->assertSame([], $request->getMimeTypes('foo')); + } } From cc923ba459b334f1466db3fcaa7923106874adfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20H=C3=A9lias?= Date: Tue, 17 Dec 2024 10:19:23 +0100 Subject: [PATCH 16/57] [Scheduler] Clarify description of exclusion time --- src/Symfony/Component/Scheduler/Trigger/ExcludeTimeTrigger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Scheduler/Trigger/ExcludeTimeTrigger.php b/src/Symfony/Component/Scheduler/Trigger/ExcludeTimeTrigger.php index 57bed27a22dda..22bf88b626f93 100644 --- a/src/Symfony/Component/Scheduler/Trigger/ExcludeTimeTrigger.php +++ b/src/Symfony/Component/Scheduler/Trigger/ExcludeTimeTrigger.php @@ -23,7 +23,7 @@ public function __construct( public function __toString(): string { - return sprintf('%s, from: %s, until: %s', $this->inner, $this->from->format(\DateTimeInterface::ATOM), $this->until->format(\DateTimeInterface::ATOM)); + return \sprintf('%s, excluding from %s until %s', $this->inner, $this->from->format(\DateTimeInterface::ATOM), $this->until->format(\DateTimeInterface::ATOM)); } public function getNextRunDate(\DateTimeImmutable $run): ?\DateTimeImmutable From a1a26dc356aee539809bea9b123ba209c439027c Mon Sep 17 00:00:00 2001 From: 4lia Date: Fri, 10 Jan 2025 10:41:34 +0330 Subject: [PATCH 17/57] Review validator-related persian translation with id 120 --- .../Validator/Resources/translations/validators.fa.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf index d93b457422950..a9cd0f2cdb9c5 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf @@ -468,7 +468,7 @@ This value is not a valid slug. - این مقدار یک اسلاگ معتبر نیست. + این مقدار یک slug معتبر نیست. From 0f3b06539e9f5737bf9cb2810eb7ccdea96b4ce4 Mon Sep 17 00:00:00 2001 From: Sergey Panteleev Date: Fri, 10 Jan 2025 11:02:41 +0300 Subject: [PATCH 18/57] [Translation][Validator] Review Russian translation (114 - 120) --- .../Resources/translations/validators.ru.xlf | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf index 42f3804a4f327..b382b77bb00fa 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf @@ -444,31 +444,31 @@ This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Это значение слишком короткое. Оно должно содержать как минимум одно слово.|Это значение слишком короткое. Оно должно содержать как минимум {{ min }} слова. + Это значение слишком короткое. Оно должно содержать как минимум одно слово.|Это значение слишком короткое. Оно должно содержать как минимум {{ min }} слова.|Это значение слишком короткое. Оно должно содержать как минимум {{ min }} слов. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Это значение слишком длинное. Оно должно содержать только одно слово.|Это значение слишком длинное. Оно должно содержать {{ max }} слова или меньше. + Это значение слишком длинное. Оно должно содержать только одно слово.|Это значение слишком длинное. Оно должно содержать {{ max }} слова или меньше.|Это значение слишком длинное. Оно должно содержать {{ max }} слов или меньше. This value does not represent a valid week in the ISO 8601 format. - Это значение не представляет допустимую неделю в формате ISO 8601. + Это значение не представляет допустимую неделю в формате ISO 8601. This value is not a valid week. - Это значение не является допустимой неделей. + Это значение не является допустимой неделей. This value should not be before week "{{ min }}". - Это значение не должно быть раньше недели "{{ min }}". + Это значение не должно быть раньше недели "{{ min }}". This value should not be after week "{{ max }}". - Это значение не должно быть после недели "{{ max }}". + Это значение не должно быть после недели "{{ max }}". This value is not a valid slug. - Это значение не является допустимым slug. + Это значение не является допустимым slug. From 4c9e1a40c9b6e18b671bcced0717ad3426cb8fdc Mon Sep 17 00:00:00 2001 From: Faizan Akram Date: Sun, 8 Dec 2024 10:46:43 +0100 Subject: [PATCH 19/57] fix(dependency-injection): reset env vars with kernel.reset - fixes #59128 --- .../Bundle/FrameworkBundle/Resources/config/services.php | 1 + src/Symfony/Component/DependencyInjection/Container.php | 8 ++++++++ .../Component/DependencyInjection/EnvVarProcessor.php | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php index c85ccf5d066b4..a7e1c51980563 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php @@ -195,6 +195,7 @@ class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : [] tagged_iterator('container.env_var_loader'), ]) ->tag('container.env_var_processor') + ->tag('kernel.reset', ['method' => 'reset']) ->set('slugger', AsciiSlugger::class) ->args([ diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index cd7105546f250..a028de7eea42f 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -290,6 +290,14 @@ public function reset(): void $this->envCache = $this->services = $this->factories = $this->privates = []; } + /** + * @internal + */ + public function resetEnvCache(): void + { + $this->envCache = []; + } + /** * Gets all service ids. * diff --git a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php index 62da6e8104de3..fe81341e6cab6 100644 --- a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php +++ b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php @@ -374,5 +374,9 @@ public function reset(): void { $this->loadedVars = []; $this->loaders = $this->originalLoaders; + + if ($this->container instanceof Container) { + $this->container->resetEnvCache(); + } } } From 97e44eacb9e7770a64fcf5729d51e1b79696f189 Mon Sep 17 00:00:00 2001 From: TheMhv Date: Fri, 10 Jan 2025 08:23:17 -0300 Subject: [PATCH 20/57] [Validator] Missing translations for Brazilian Portuguese (pt_BR) --- .../Resources/translations/validators.pt_BR.xlf | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf index 3022c27c96f09..a7be9976c4b60 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf @@ -444,31 +444,31 @@ This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Este valor é muito curto. Deve conter pelo menos uma palavra.|Este valor é muito curto. Deve conter pelo menos {{ min }} palavras. + Este valor é muito curto. Deve conter pelo menos uma palavra.|Este valor é muito curto. Deve conter pelo menos {{ min }} palavras. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Este valor é muito longo. Deve conter apenas uma palavra.|Este valor é muito longo. Deve conter {{ max }} palavras ou menos. + Este valor é muito longo. Deve conter apenas uma palavra.|Este valor é muito longo. Deve conter {{ max }} palavras ou menos. This value does not represent a valid week in the ISO 8601 format. - Este valor não representa uma semana válida no formato ISO 8601. + Este valor não representa uma semana válida no formato ISO 8601. This value is not a valid week. - Este valor não é uma semana válida. + Este valor não é uma semana válida. This value should not be before week "{{ min }}". - Este valor não deve ser anterior à semana "{{ min }}". + Este valor não deve ser anterior à semana "{{ min }}". This value should not be after week "{{ max }}". - Este valor não deve estar após a semana "{{ max }}". + Este valor não deve estar após a semana "{{ max }}". This value is not a valid slug. - Este valor não é um slug válido. + Este valor não é um slug válido. From bb9adefe4c21b7adbf4d2fbd906d5956e399b6a4 Mon Sep 17 00:00:00 2001 From: Michel Roca Date: Sat, 11 Jan 2025 17:55:58 +0100 Subject: [PATCH 21/57] tests(notifier): avoid failing SNS test with local AWS configuration --- .../AmazonSns/Tests/AmazonSnsTransportFactoryTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Symfony/Component/Notifier/Bridge/AmazonSns/Tests/AmazonSnsTransportFactoryTest.php b/src/Symfony/Component/Notifier/Bridge/AmazonSns/Tests/AmazonSnsTransportFactoryTest.php index 489c54a4f0812..61016929e93fe 100644 --- a/src/Symfony/Component/Notifier/Bridge/AmazonSns/Tests/AmazonSnsTransportFactoryTest.php +++ b/src/Symfony/Component/Notifier/Bridge/AmazonSns/Tests/AmazonSnsTransportFactoryTest.php @@ -18,6 +18,12 @@ class AmazonSnsTransportFactoryTest extends TransportFactoryTestCase { public function createFactory(): AmazonSnsTransportFactory { + // Tests will fail if a ~/.aws/config file exists with a default.region value, + // or if AWS_REGION env variable is set. + // Setting a profile & region names will bypass default options retrieved by \AsyncAws\Core::get + $_ENV['AWS_PROFILE'] = 'not-existing'; + $_ENV['AWS_REGION'] = 'us-east-1'; + return new AmazonSnsTransportFactory(); } From 2caa0fd4f5516c55052c3ffed36fb0fcb19b44b9 Mon Sep 17 00:00:00 2001 From: Eddy <76176151+eddya92@users.noreply.github.com> Date: Fri, 10 Jan 2025 15:53:19 +0100 Subject: [PATCH 22/57] 6.4 Missing translations for Italian (it) #59419 --- .../Resources/translations/validators.it.xlf | 6 +++--- .../Resources/translations/validators.ru.xlf | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf index b1badf3ccc044..9aa09394cc37e 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf @@ -20,7 +20,7 @@ The value you selected is not a valid choice. - Questo valore dovrebbe essere una delle opzioni disponibili. + Il valore selezionato non è una scelta valida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. @@ -308,7 +308,7 @@ This value does not match the expected {{ charset }} charset. - Questo valore non corrisponde al charset {{ charset }}. + Questo valore non corrisponde al charset {{ charset }} previsto. This value is not a valid Business Identifier Code (BIC). @@ -468,7 +468,7 @@ This value is not a valid slug. - Questo valore non è uno slug valido. + Questo valore non è uno slug valido. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf index 42f3804a4f327..b382b77bb00fa 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf @@ -444,31 +444,31 @@ This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Это значение слишком короткое. Оно должно содержать как минимум одно слово.|Это значение слишком короткое. Оно должно содержать как минимум {{ min }} слова. + Это значение слишком короткое. Оно должно содержать как минимум одно слово.|Это значение слишком короткое. Оно должно содержать как минимум {{ min }} слова.|Это значение слишком короткое. Оно должно содержать как минимум {{ min }} слов. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Это значение слишком длинное. Оно должно содержать только одно слово.|Это значение слишком длинное. Оно должно содержать {{ max }} слова или меньше. + Это значение слишком длинное. Оно должно содержать только одно слово.|Это значение слишком длинное. Оно должно содержать {{ max }} слова или меньше.|Это значение слишком длинное. Оно должно содержать {{ max }} слов или меньше. This value does not represent a valid week in the ISO 8601 format. - Это значение не представляет допустимую неделю в формате ISO 8601. + Это значение не представляет допустимую неделю в формате ISO 8601. This value is not a valid week. - Это значение не является допустимой неделей. + Это значение не является допустимой неделей. This value should not be before week "{{ min }}". - Это значение не должно быть раньше недели "{{ min }}". + Это значение не должно быть раньше недели "{{ min }}". This value should not be after week "{{ max }}". - Это значение не должно быть после недели "{{ max }}". + Это значение не должно быть после недели "{{ max }}". This value is not a valid slug. - Это значение не является допустимым slug. + Это значение не является допустимым slug. From 87f24358870c89aa1b7931076bda3fd84ee4ba1b Mon Sep 17 00:00:00 2001 From: Marko Kaznovac Date: Sun, 12 Jan 2025 16:51:36 +0100 Subject: [PATCH 23/57] [Validator] Update sr_Latn 120:This value is not a valid slug. inline with the tone and terminology of the rest of the translations --- .../Validator/Resources/translations/validators.sr_Latn.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf index 142ca0e290a20..a521dbaa70474 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf @@ -468,7 +468,7 @@ This value is not a valid slug. - Ova vrednost nije važeći slug. + Ova vrednost nije validan slug. From aed5cd6925a34735fe8a3a4184565075576b7ff3 Mon Sep 17 00:00:00 2001 From: Marko Kaznovac Date: Sun, 12 Jan 2025 16:54:47 +0100 Subject: [PATCH 24/57] [Validator] Update sr_Cyrl 120:This value is not a valid slug. inline with the tone and terminology of the rest of the translations --- .../Validator/Resources/translations/validators.sr_Cyrl.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf index e3ce9d818fcab..dda7e1fab683e 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf @@ -468,7 +468,7 @@ This value is not a valid slug. - Ова вредност није важећи слуг. + Ова вредност није валидан слуг. From 48af4d84406d5cbe29f25b00d14b1d21ae1be470 Mon Sep 17 00:00:00 2001 From: Ahmad Al-Naib <47335118+ahmadalnaib@users.noreply.github.com> Date: Tue, 14 Jan 2025 14:02:15 +0100 Subject: [PATCH 25/57] Update validators.ar.xlf I changed some words and corrected others to be appropriate --- .../Resources/translations/validators.ar.xlf | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf index 38bf7684ef16e..96fd59f68a520 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf @@ -8,7 +8,7 @@ This value should be true. - هذه القيمة يجب أن تكون حقيقية. + هذه القيمة يجب أن تكون صحيحة. This value should be of type {{ type }}. @@ -20,7 +20,7 @@ The value you selected is not a valid choice. - القيمة المختارة ليست خيارا صحيحا. + القيمة المختارة ليست خيار صحيح. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. @@ -36,23 +36,23 @@ This field was not expected. - لم يكن من المتوقع هذا المجال. + لم يكن من المتوقع هذا الحقل. This field is missing. - هذا المجال مفقود. + هذا الحقل مفقود. This value is not a valid date. - هذه القيمة ليست تاريخا صالحا. + هذه القيمة ليست تاريخ صالح. This value is not a valid datetime. - هذه القيمة ليست تاريخا و وقتا صالحا. + هذه القيمة ليست تاريخ و وقت صالح. This value is not a valid email address. - هذه القيمة ليست عنوان بريد إلكتروني صحيح. + هذه القيمة ليست لها عنوان بريد إلكتروني صحيح. The file could not be found. @@ -88,11 +88,11 @@ This value should not be blank. - هذه القيمة يجب الا تكون فارغة. + هذه القيمة يجب لا تكون فارغة. This value should not be null. - هذه القيمة يجب الا تكون فارغة. + هذه القيمة يجب لا تكون فارغة. This value should be null. @@ -124,7 +124,7 @@ The file could not be uploaded. - لم استطع استقبال الملف. + تعذر تحميل الملف. This value should be a valid number. @@ -132,7 +132,7 @@ This file is not a valid image. - هذا الملف ليس صورة صحيحة. + هذا الملف غير صالح للصورة. This value is not a valid IP address. From d993526b694c1170c7841a64b121ac76404976b5 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 14 Jan 2025 15:54:07 +0100 Subject: [PATCH 26/57] [HttpKernel] Fix link to php doc --- .../Component/HttpKernel/Attribute/MapQueryParameter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Attribute/MapQueryParameter.php b/src/Symfony/Component/HttpKernel/Attribute/MapQueryParameter.php index f83e331e4118f..bbc1fff273e9d 100644 --- a/src/Symfony/Component/HttpKernel/Attribute/MapQueryParameter.php +++ b/src/Symfony/Component/HttpKernel/Attribute/MapQueryParameter.php @@ -22,7 +22,7 @@ final class MapQueryParameter extends ValueResolver { /** - * @see https://php.net/filter.filters.validate for filter, flags and options + * @see https://php.net/manual/filter.constants for filter, flags and options * * @param string|null $name The name of the query parameter. If null, the name of the argument in the controller will be used. */ From 45763bd0972874772f014e090c008daa5ca38762 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 15 Jan 2025 19:35:52 +0100 Subject: [PATCH 27/57] [FrameworkBundle] Fix wiring ConsoleProfilerListener --- .../EventListener/ConsoleProfilerListener.php | 14 ++++++++++---- .../FrameworkBundle/Resources/config/profiling.php | 7 ++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/EventListener/ConsoleProfilerListener.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/ConsoleProfilerListener.php index c2a71d0a7cf50..03274450de741 100644 --- a/src/Symfony/Bundle/FrameworkBundle/EventListener/ConsoleProfilerListener.php +++ b/src/Symfony/Bundle/FrameworkBundle/EventListener/ConsoleProfilerListener.php @@ -38,6 +38,8 @@ final class ConsoleProfilerListener implements EventSubscriberInterface /** @var \SplObjectStorage */ private \SplObjectStorage $parents; + private bool $disabled = false; + public function __construct( private readonly Profiler $profiler, private readonly RequestStack $requestStack, @@ -66,7 +68,7 @@ public function initialize(ConsoleCommandEvent $event): void $input = $event->getInput(); if (!$input->hasOption('profile') || !$input->getOption('profile')) { - $this->profiler->disable(); + $this->disabled = true; return; } @@ -92,7 +94,12 @@ public function catch(ConsoleErrorEvent $event): void public function profile(ConsoleTerminateEvent $event): void { - if (!$this->cliMode || !$this->profiler->isEnabled()) { + $error = $this->error; + $this->error = null; + + if (!$this->cliMode || $this->disabled) { + $this->disabled = false; + return; } @@ -114,8 +121,7 @@ public function profile(ConsoleTerminateEvent $event): void $request->command->exitCode = $event->getExitCode(); $request->command->interruptedBySignal = $event->getInterruptingSignal(); - $profile = $this->profiler->collect($request, $request->getResponse(), $this->error); - $this->error = null; + $profile = $this->profiler->collect($request, $request->getResponse(), $error); $this->profiles[$request] = $profile; if ($this->parents[$request] = $this->requestStack->getParentRequest()) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.php index eaef795977d98..4ae34649b4aaf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.php @@ -40,7 +40,7 @@ ->set('console_profiler_listener', ConsoleProfilerListener::class) ->args([ - service('profiler'), + service('.lazy_profiler'), service('.virtual_request_stack'), service('debug.stopwatch'), param('kernel.runtime_mode.cli'), @@ -48,6 +48,11 @@ ]) ->tag('kernel.event_subscriber') + ->set('.lazy_profiler', Profiler::class) + ->factory('current') + ->args([[service('profiler')]]) + ->lazy() + ->set('.virtual_request_stack', VirtualRequestStack::class) ->args([service('request_stack')]) ->public() From 67b32ef7a4b02ca1f8f3d528b299798f42db2d35 Mon Sep 17 00:00:00 2001 From: Evert Harmeling Date: Thu, 16 Jan 2025 10:36:10 +0100 Subject: [PATCH 28/57] [validator] Updated Dutch translation --- .../Validator/Resources/translations/validators.nl.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf index 512d0c4e771ed..ae378a6269bf7 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf @@ -468,7 +468,7 @@ This value is not a valid slug. - Deze waarde is geen geldige slug. + Deze waarde is geen geldige slug. From 52377cc65e1b989827d29941c0c232c0ecbf540a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDan=20V=2E=20Dragan?= Date: Thu, 16 Jan 2025 12:58:10 +0100 Subject: [PATCH 29/57] [Security][Validators] Review translations. --- .../Core/Resources/translations/security.sl.xlf | 2 +- .../Resources/translations/validators.sl.xlf | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.sl.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.sl.xlf index 7d0514005116d..2b7a592b799c2 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.sl.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.sl.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minuto.|Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minut. + Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minuto.|Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minuti.|Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minute.|Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minut. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf index 41050a2e240c9..b89608949b50c 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf @@ -440,35 +440,35 @@ This URL is missing a top-level domain. - Temu URL manjka domena najvišje ravni. + URL-ju manjka vrhnja domena. This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Ta vrednost je prekratka. Vsebovati mora vsaj eno besedo.|Ta vrednost je prekratka. Vsebovati mora vsaj {{ min }} besed. + Ta vrednost je prekratka. Vsebovati mora vsaj eno besedo.|Ta vrednost je prekratka. Vsebovati mora vsaj {{ min }} besedi.|Ta vrednost je prekratka. Vsebovati mora vsaj {{ min }} besede.|Ta vrednost je prekratka. Vsebovati mora vsaj {{ min }} besed. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Ta vrednost je predolga. Vsebovati mora samo eno besedo.|Ta vrednost je predolga. Vsebovati mora {{ max }} besed ali manj. + Ta vrednost je predolga. Vsebovati mora največ eno besedo.|Ta vrednost je predolga. Vsebovati mora največ {{ max }}.|Ta vrednost je predolga. Vsebovati mora največ {{ max }} besede.|Ta vrednost je predolga. Vsebovati mora največ {{ max }} besed. This value does not represent a valid week in the ISO 8601 format. - Ta vrednost ne predstavlja veljavnega tedna v ISO 8601 formatu. + Ta vrednost ne predstavlja veljavnega tedna v ISO 8601 formatu. This value is not a valid week. - Ta vrednost ni veljaven teden. + Ta vrednost ni veljaven teden. This value should not be before week "{{ min }}". - Ta vrednost ne sme biti pred tednom "{{ min }}". + Ta vrednost ne sme biti pred tednom "{{ min }}". This value should not be after week "{{ max }}". - Ta vrednost ne sme biti po tednu "{{ max }}". + Ta vrednost ne sme biti po tednu "{{ max }}". This value is not a valid slug. - Ta vrednost ni veljaven slug. + Ta vrednost ni veljaven URL slug. From 8f060326e09bdcdd11b3f1a078201c91da11a6e8 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 16 Jan 2025 21:12:04 +0100 Subject: [PATCH 30/57] fix tests The files we used to download are no longer part of the WICG/sanitizer-api repository. --- .../baseline-attribute-allow-list.json | 213 ++++++++++++++++++ .../Fixtures/baseline-element-allow-list.json | 130 +++++++++++ .../Tests/Reference/W3CReferenceTest.php | 21 +- 3 files changed, 346 insertions(+), 18 deletions(-) create mode 100644 src/Symfony/Component/HtmlSanitizer/Tests/Fixtures/baseline-attribute-allow-list.json create mode 100644 src/Symfony/Component/HtmlSanitizer/Tests/Fixtures/baseline-element-allow-list.json diff --git a/src/Symfony/Component/HtmlSanitizer/Tests/Fixtures/baseline-attribute-allow-list.json b/src/Symfony/Component/HtmlSanitizer/Tests/Fixtures/baseline-attribute-allow-list.json new file mode 100644 index 0000000000000..1b7bee611fe4a --- /dev/null +++ b/src/Symfony/Component/HtmlSanitizer/Tests/Fixtures/baseline-attribute-allow-list.json @@ -0,0 +1,213 @@ +[ + "abbr", + "accept", + "accept-charset", + "accesskey", + "action", + "align", + "alink", + "allow", + "allowfullscreen", + "allowpaymentrequest", + "alt", + "anchor", + "archive", + "as", + "async", + "autocapitalize", + "autocomplete", + "autocorrect", + "autofocus", + "autopictureinpicture", + "autoplay", + "axis", + "background", + "behavior", + "bgcolor", + "border", + "bordercolor", + "capture", + "cellpadding", + "cellspacing", + "challenge", + "char", + "charoff", + "charset", + "checked", + "cite", + "class", + "classid", + "clear", + "code", + "codebase", + "codetype", + "color", + "cols", + "colspan", + "compact", + "content", + "contenteditable", + "controls", + "controlslist", + "conversiondestination", + "coords", + "crossorigin", + "csp", + "data", + "datetime", + "declare", + "decoding", + "default", + "defer", + "dir", + "direction", + "dirname", + "disabled", + "disablepictureinpicture", + "disableremoteplayback", + "disallowdocumentaccess", + "download", + "draggable", + "elementtiming", + "enctype", + "end", + "enterkeyhint", + "event", + "exportparts", + "face", + "for", + "form", + "formaction", + "formenctype", + "formmethod", + "formnovalidate", + "formtarget", + "frame", + "frameborder", + "headers", + "height", + "hidden", + "high", + "href", + "hreflang", + "hreftranslate", + "hspace", + "http-equiv", + "id", + "imagesizes", + "imagesrcset", + "importance", + "impressiondata", + "impressionexpiry", + "incremental", + "inert", + "inputmode", + "integrity", + "invisible", + "is", + "ismap", + "keytype", + "kind", + "label", + "lang", + "language", + "latencyhint", + "leftmargin", + "link", + "list", + "loading", + "longdesc", + "loop", + "low", + "lowsrc", + "manifest", + "marginheight", + "marginwidth", + "max", + "maxlength", + "mayscript", + "media", + "method", + "min", + "minlength", + "multiple", + "muted", + "name", + "nohref", + "nomodule", + "nonce", + "noresize", + "noshade", + "novalidate", + "nowrap", + "object", + "open", + "optimum", + "part", + "pattern", + "ping", + "placeholder", + "playsinline", + "policy", + "poster", + "preload", + "pseudo", + "readonly", + "referrerpolicy", + "rel", + "reportingorigin", + "required", + "resources", + "rev", + "reversed", + "role", + "rows", + "rowspan", + "rules", + "sandbox", + "scheme", + "scope", + "scopes", + "scrollamount", + "scrolldelay", + "scrolling", + "select", + "selected", + "shadowroot", + "shadowrootdelegatesfocus", + "shape", + "size", + "sizes", + "slot", + "span", + "spellcheck", + "src", + "srcdoc", + "srclang", + "srcset", + "standby", + "start", + "step", + "style", + "summary", + "tabindex", + "target", + "text", + "title", + "topmargin", + "translate", + "truespeed", + "trusttoken", + "type", + "usemap", + "valign", + "value", + "valuetype", + "version", + "virtualkeyboardpolicy", + "vlink", + "vspace", + "webkitdirectory", + "width", + "wrap" +] diff --git a/src/Symfony/Component/HtmlSanitizer/Tests/Fixtures/baseline-element-allow-list.json b/src/Symfony/Component/HtmlSanitizer/Tests/Fixtures/baseline-element-allow-list.json new file mode 100644 index 0000000000000..cf470cd3f8507 --- /dev/null +++ b/src/Symfony/Component/HtmlSanitizer/Tests/Fixtures/baseline-element-allow-list.json @@ -0,0 +1,130 @@ +[ + "a", + "abbr", + "acronym", + "address", + "area", + "article", + "aside", + "audio", + "b", + "basefont", + "bdi", + "bdo", + "bgsound", + "big", + "blockquote", + "body", + "br", + "button", + "canvas", + "caption", + "center", + "cite", + "code", + "col", + "colgroup", + "command", + "data", + "datalist", + "dd", + "del", + "details", + "dfn", + "dialog", + "dir", + "div", + "dl", + "dt", + "em", + "fieldset", + "figcaption", + "figure", + "font", + "footer", + "form", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "head", + "header", + "hgroup", + "hr", + "html", + "i", + "image", + "img", + "input", + "ins", + "kbd", + "keygen", + "label", + "layer", + "legend", + "li", + "link", + "listing", + "main", + "map", + "mark", + "marquee", + "menu", + "meta", + "meter", + "nav", + "nobr", + "ol", + "optgroup", + "option", + "output", + "p", + "picture", + "plaintext", + "popup", + "portal", + "pre", + "progress", + "q", + "rb", + "rp", + "rt", + "rtc", + "ruby", + "s", + "samp", + "section", + "select", + "selectmenu", + "slot", + "small", + "source", + "span", + "strike", + "strong", + "style", + "sub", + "summary", + "sup", + "table", + "tbody", + "td", + "template", + "textarea", + "tfoot", + "th", + "thead", + "time", + "title", + "tr", + "track", + "tt", + "u", + "ul", + "var", + "video", + "wbr", + "xmp" +] diff --git a/src/Symfony/Component/HtmlSanitizer/Tests/Reference/W3CReferenceTest.php b/src/Symfony/Component/HtmlSanitizer/Tests/Reference/W3CReferenceTest.php index 6cb67c2b0849b..51a4a7d9a21c0 100644 --- a/src/Symfony/Component/HtmlSanitizer/Tests/Reference/W3CReferenceTest.php +++ b/src/Symfony/Component/HtmlSanitizer/Tests/Reference/W3CReferenceTest.php @@ -16,39 +16,24 @@ /** * Check that the W3CReference class is up to date with the standard resources. - * - * @see https://github.com/WICG/sanitizer-api/blob/main/resources */ class W3CReferenceTest extends TestCase { - private const STANDARD_RESOURCES = [ - 'elements' => 'https://raw.githubusercontent.com/WICG/sanitizer-api/main/resources/baseline-element-allow-list.json', - 'attributes' => 'https://raw.githubusercontent.com/WICG/sanitizer-api/main/resources/baseline-attribute-allow-list.json', - ]; - public function testElements() { - if (!\in_array('https', stream_get_wrappers(), true)) { - $this->markTestSkipped('"https" stream wrapper is not enabled.'); - } - $referenceElements = array_values(array_merge(array_keys(W3CReference::HEAD_ELEMENTS), array_keys(W3CReference::BODY_ELEMENTS))); sort($referenceElements); $this->assertSame( - $this->getResourceData(self::STANDARD_RESOURCES['elements']), + $this->getResourceData(__DIR__.'/../Fixtures/baseline-element-allow-list.json'), $referenceElements ); } public function testAttributes() { - if (!\in_array('https', stream_get_wrappers(), true)) { - $this->markTestSkipped('"https" stream wrapper is not enabled.'); - } - $this->assertSame( - $this->getResourceData(self::STANDARD_RESOURCES['attributes']), + $this->getResourceData(__DIR__.'/../Fixtures/baseline-attribute-allow-list.json'), array_keys(W3CReference::ATTRIBUTES) ); } @@ -56,7 +41,7 @@ public function testAttributes() private function getResourceData(string $resource): array { return json_decode( - file_get_contents($resource, false, stream_context_create(['ssl' => ['verify_peer' => false, 'verify_peer_name' => false]])), + file_get_contents($resource), true, 512, \JSON_THROW_ON_ERROR From e444e5bb26cea22edf4a3b8d51f8c2a1ab8ec62c Mon Sep 17 00:00:00 2001 From: HypeMC Date: Thu, 16 Jan 2025 19:46:02 +0100 Subject: [PATCH 31/57] [PropertyInfo] Add missing test --- .../Tests/Extractor/ReflectionExtractorTest.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php index 45565096d9963..b2d975219b3aa 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php @@ -631,6 +631,17 @@ public static function writeMutatorProvider(): array ]; } + public function testDisabledAdderAndRemoverReturnsError() + { + $writeMutator = $this->extractor->getWriteInfo(Php71Dummy::class, 'baz', [ + 'enable_adder_remover_extraction' => false, + ]); + + self::assertNotNull($writeMutator); + self::assertSame(PropertyWriteInfo::TYPE_NONE, $writeMutator->getType()); + self::assertSame([\sprintf('The property "baz" in class "%s" can be defined with the methods "addBaz()", "removeBaz()" but the new value must be an array or an instance of \Traversable', Php71Dummy::class)], $writeMutator->getErrors()); + } + public function testGetWriteInfoReadonlyProperties() { $writeMutatorConstructor = $this->extractor->getWriteInfo(Php81Dummy::class, 'foo', ['enable_constructor_extraction' => true]); From 944b40abf6d387c1db7f1cd3bdf77ac25f2393df Mon Sep 17 00:00:00 2001 From: tito10047 Date: Fri, 17 Jan 2025 08:48:36 +0100 Subject: [PATCH 32/57] Fix #53778 --- .../Resources/translations/security.sk.xlf | 2 +- .../Resources/translations/validators.sk.xlf | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.sk.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.sk.xlf index b08757de0086f..3820bdccc7482 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.sk.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.sk.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minútu.|Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minúty.|Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minút. + Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minútu.|Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minúty.|Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minút. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf index becd9190da088..0706ed07109fc 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf @@ -192,7 +192,7 @@ No temporary folder was configured in php.ini, or the configured folder does not exist. - V php.ini nie je nastavený žiadny dočasný adresár, alebo nastavený adresár neexistuje. + V php.ini nie je nastavený žiadny dočasný adresár, alebo nastavený adresár neexistuje. Cannot write temporary file to disk. @@ -224,7 +224,7 @@ This value is not a valid International Bank Account Number (IBAN). - Táto hodnota nie je platným Medzinárodným bankovým číslom účtu (IBAN). + Táto hodnota nie je platným Medzinárodným bankovým číslom účtu (IBAN). This value is not a valid ISBN-10. @@ -312,7 +312,7 @@ This value is not a valid Business Identifier Code (BIC). - Táto hodnota nie je platným Obchodným identifikačným kódom (BIC). + Táto hodnota nie je platným Obchodným identifikačným kódom (BIC). Error @@ -320,7 +320,7 @@ This value is not a valid UUID. - Táto hodnota nie je platným UUID. + Táto hodnota nie je platné UUID. This value should be a multiple of {{ compared_value }}. @@ -436,39 +436,39 @@ This value is not a valid MAC address. - Táto hodnota nie je platnou MAC adresou. + Táto hodnota nie je platnou MAC adresou. This URL is missing a top-level domain. - Tomuto URL chýba doména najvyššej úrovne. + Tejto URL chýba doména najvyššej úrovne. This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Táto hodnota je príliš krátka. Mala by obsahovať aspoň jedno slovo.|Táto hodnota je príliš krátka. Mala by obsahovať aspoň {{ min }} slov. + Táto hodnota je príliš krátka. Mala by obsahovať aspoň jedno slovo.|Táto hodnota je príliš krátka. Mala by obsahovať aspoň {{ min }} slov. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Táto hodnota je príliš dlhá. Mala by obsahovať len jedno slovo.|Táto hodnota je príliš dlhá. Mala by obsahovať {{ max }} slov alebo menej. + Táto hodnota je príliš dlhá. Mala by obsahovať len jedno slovo.|Táto hodnota je príliš dlhá. Mala by obsahovať {{ max }} slov alebo menej. This value does not represent a valid week in the ISO 8601 format. - Táto hodnota nepredstavuje platný týždeň vo formáte ISO 8601. + Táto hodnota nepredstavuje platný týždeň vo formáte ISO 8601. This value is not a valid week. - Táto hodnota nie je platný týždeň. + Táto hodnota nie je platný týždeň. This value should not be before week "{{ min }}". - Táto hodnota by nemala byť pred týždňom "{{ min }}". + Táto hodnota by nemala byť pred týždňom "{{ min }}". This value should not be after week "{{ max }}". - Táto hodnota by nemala byť po týždni "{{ max }}". + Táto hodnota by nemala byť po týždni "{{ max }}". This value is not a valid slug. - Táto hodnota nie je platný slug. + Táto hodnota nie je platný slug. From 5288eba9074bda3bda4f127dbf16c04dcd00856f Mon Sep 17 00:00:00 2001 From: djordy Date: Tue, 14 Jan 2025 14:22:11 +0100 Subject: [PATCH 33/57] [Serializer] [ObjectNormalizer] Filter int when using FILTER_BOOL --- .../Normalizer/AbstractObjectNormalizer.php | 4 +-- .../AbstractObjectNormalizerTest.php | 31 +++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index aad68f7ba0476..1860425f9f3b5 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -569,7 +569,7 @@ private function validateAndDenormalizeLegacy(array $types, string $currentClass return (float) $data; } - if (LegacyType::BUILTIN_TYPE_BOOL === $builtinType && \is_string($data) && ($context[self::FILTER_BOOL] ?? false)) { + if (LegacyType::BUILTIN_TYPE_BOOL === $builtinType && (\is_string($data) || \is_int($data)) && ($context[self::FILTER_BOOL] ?? false)) { return filter_var($data, \FILTER_VALIDATE_BOOL, \FILTER_NULL_ON_FAILURE); } @@ -854,7 +854,7 @@ private function validateAndDenormalize(Type $type, string $currentClass, string return (float) $data; } - if (TypeIdentifier::BOOL === $typeIdentifier && \is_string($data) && ($context[self::FILTER_BOOL] ?? false)) { + if (TypeIdentifier::BOOL === $typeIdentifier && (\is_string($data) || \is_int($data)) && ($context[self::FILTER_BOOL] ?? false)) { return filter_var($data, \FILTER_VALIDATE_BOOL, \FILTER_NULL_ON_FAILURE); } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php index b4f5c103ca7d1..27f3c2084999d 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -1216,15 +1216,34 @@ public static function provideDenormalizeWithFilterBoolData(): array { return [ [['foo' => 'true'], true], + [['foo' => 'True'], true], + [['foo' => 'TRUE'], true], [['foo' => '1'], true], + [['foo' => 1], true], [['foo' => 'yes'], true], + [['foo' => 'Yes'], true], + [['foo' => 'YES'], true], + [['foo' => 'on'], true], + [['foo' => 'On'], true], + [['foo' => 'ON'], true], [['foo' => 'false'], false], + [['foo' => 'False'], false], + [['foo' => 'FALSE'], false], [['foo' => '0'], false], + [['foo' => 0], false], [['foo' => 'no'], false], + [['foo' => 'No'], false], + [['foo' => 'NO'], false], + [['foo' => 'off'], false], + [['foo' => 'Off'], false], + [['foo' => 'OFF'], false], [['foo' => ''], false], [['foo' => null], null], [['foo' => 'null'], null], [['foo' => 'something'], null], + [['foo' => 'foo'], null], + [['foo' => 1234567890], null], + [['foo' => -1234567890], null], ]; } @@ -1253,10 +1272,7 @@ protected function isAllowedAttribute($classOrObject, string $attribute, ?string public function testTemplateTypeWhenAnObjectIsPassedToDenormalize() { - $normalizer = new class ( - classMetadataFactory: new ClassMetadataFactory(new AttributeLoader()), - propertyTypeExtractor: new PropertyInfoExtractor(typeExtractors: [new PhpStanExtractor(), new ReflectionExtractor()]) - ) extends AbstractObjectNormalizerDummy { + $normalizer = new class(classMetadataFactory: new ClassMetadataFactory(new AttributeLoader()), propertyTypeExtractor: new PropertyInfoExtractor(typeExtractors: [new PhpStanExtractor(), new ReflectionExtractor()])) extends AbstractObjectNormalizerDummy { protected function isAllowedAttribute($classOrObject, string $attribute, ?string $format = null, array $context = []): bool { return true; @@ -1279,10 +1295,7 @@ public function testDenormalizeTemplateType() $this->markTestSkipped('The PropertyInfo component before Symfony 7.1 does not support template types.'); } - $normalizer = new class ( - classMetadataFactory: new ClassMetadataFactory(new AttributeLoader()), - propertyTypeExtractor: new PropertyInfoExtractor(typeExtractors: [new PhpStanExtractor(), new ReflectionExtractor()]) - ) extends AbstractObjectNormalizerDummy { + $normalizer = new class(classMetadataFactory: new ClassMetadataFactory(new AttributeLoader()), propertyTypeExtractor: new PropertyInfoExtractor(typeExtractors: [new PhpStanExtractor(), new ReflectionExtractor()])) extends AbstractObjectNormalizerDummy { protected function isAllowedAttribute($classOrObject, string $attribute, ?string $format = null, array $context = []): bool { return true; @@ -1587,7 +1600,7 @@ class TruePropertyDummy class BoolPropertyDummy { - /** @var null|bool */ + /** @var bool|null */ public $foo; } From 5356023f6137abfcade91847fb56419f0a18c1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Pillevesse?= Date: Wed, 15 Jan 2025 10:13:40 +0100 Subject: [PATCH 34/57] improve amqp connection issues --- .../Bridge/Amqp/Transport/AmqpReceiver.php | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/AmqpReceiver.php b/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/AmqpReceiver.php index 3c855e9ee46ce..48706b6432755 100644 --- a/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/AmqpReceiver.php +++ b/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/AmqpReceiver.php @@ -92,10 +92,16 @@ public function ack(Envelope $envelope): void try { $stamp = $this->findAmqpStamp($envelope); - $this->connection->ack( - $stamp->getAmqpEnvelope(), - $stamp->getQueueName() - ); + $this->connection->ack($stamp->getAmqpEnvelope(), $stamp->getQueueName()); + } catch (\AMQPConnectionException) { + try { + $stamp = $this->findAmqpStamp($envelope); + + $this->connection->queue($stamp->getQueueName())->getConnection()->reconnect(); + $this->connection->ack($stamp->getAmqpEnvelope(), $stamp->getQueueName()); + } catch (\AMQPException $exception) { + throw new TransportException($exception->getMessage(), 0, $exception); + } } catch (\AMQPException $exception) { throw new TransportException($exception->getMessage(), 0, $exception); } @@ -124,6 +130,13 @@ private function rejectAmqpEnvelope(\AMQPEnvelope $amqpEnvelope, string $queueNa { try { $this->connection->nack($amqpEnvelope, $queueName, \AMQP_NOPARAM); + } catch (\AMQPConnectionException) { + try { + $this->connection->queue($queueName)->getConnection()->reconnect(); + $this->connection->nack($amqpEnvelope, $queueName, \AMQP_NOPARAM); + } catch (\AMQPException $exception) { + throw new TransportException($exception->getMessage(), 0, $exception); + } } catch (\AMQPException $exception) { throw new TransportException($exception->getMessage(), 0, $exception); } From 66ba8dede84a71c98a7fddf030517d8243b0e4cb Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 17 Jan 2025 12:24:22 +0100 Subject: [PATCH 35/57] fix dumped markup --- src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php index cb41112792dfa..bb7b317db631f 100644 --- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php @@ -879,7 +879,7 @@ protected function style(string $style, string $value, array $attr = []): string } elseif ('meta' === $style && isset($attr['title'])) { $dumpTitle = esc($this->utf8Encode($attr['title'])); } elseif ('private' === $style) { - $dumpTitle = sprintf('Private property defined in class: `%s`"', esc($this->utf8Encode($attr['class']))); + $dumpTitle = sprintf('Private property defined in class: `%s`', esc($this->utf8Encode($attr['class']))); } if (isset($attr['ellipsis'])) { From c1d8c3900423e88c03f33062bbfee8f4678b76d6 Mon Sep 17 00:00:00 2001 From: Antoine Beyet Date: Thu, 16 Jan 2025 16:20:07 +0100 Subject: [PATCH 36/57] [HtmlSanitizer] Avoid accessing non existent array key when checking for hosts validity fix #59524 --- .../Tests/TextSanitizer/UrlSanitizerTest.php | 9 +++++++++ .../HtmlSanitizer/TextSanitizer/UrlSanitizer.php | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HtmlSanitizer/Tests/TextSanitizer/UrlSanitizerTest.php b/src/Symfony/Component/HtmlSanitizer/Tests/TextSanitizer/UrlSanitizerTest.php index c00b8f7dfbfe5..0d366b7b9848f 100644 --- a/src/Symfony/Component/HtmlSanitizer/Tests/TextSanitizer/UrlSanitizerTest.php +++ b/src/Symfony/Component/HtmlSanitizer/Tests/TextSanitizer/UrlSanitizerTest.php @@ -274,6 +274,15 @@ public static function provideSanitize(): iterable 'expected' => null, ]; + yield [ + 'input' => 'https://trusted.com/link.php', + 'allowedSchemes' => ['http', 'https'], + 'allowedHosts' => ['subdomain.trusted.com', 'trusted.com'], + 'forceHttps' => false, + 'allowRelative' => false, + 'expected' => 'https://trusted.com/link.php', + ]; + // Allow relative yield [ 'input' => '/link.php', diff --git a/src/Symfony/Component/HtmlSanitizer/TextSanitizer/UrlSanitizer.php b/src/Symfony/Component/HtmlSanitizer/TextSanitizer/UrlSanitizer.php index 05d86ba15da8e..0a65873d55577 100644 --- a/src/Symfony/Component/HtmlSanitizer/TextSanitizer/UrlSanitizer.php +++ b/src/Symfony/Component/HtmlSanitizer/TextSanitizer/UrlSanitizer.php @@ -132,7 +132,7 @@ private static function matchAllowedHostParts(array $uriParts, array $trustedPar { // Check each chunk of the domain is valid foreach ($trustedParts as $key => $trustedPart) { - if ($uriParts[$key] !== $trustedPart) { + if (!array_key_exists($key, $uriParts) || $uriParts[$key] !== $trustedPart) { return false; } } From 98550a98f74be945b06227abad2bf0e1feb868e6 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 19 Jun 2024 22:26:42 +0200 Subject: [PATCH 37/57] convert legacy types to TypeInfo types if getType() is not implemented --- .../PropertyInfoCacheExtractor.php | 36 ++++++- .../PropertyInfo/PropertyInfoExtractor.php | 19 +++- .../Tests/PropertyInfoCacheExtractorTest.php | 92 ++++++++++++++++++ .../Tests/PropertyInfoExtractorTest.php | 67 +++++++++++++ .../PropertyInfo/Util/LegacyTypeConverter.php | 94 +++++++++++++++++++ 5 files changed, 306 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/PropertyInfo/Util/LegacyTypeConverter.php diff --git a/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php b/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php index 38b9c68a2e29e..caf9bd182233f 100644 --- a/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php +++ b/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php @@ -12,6 +12,7 @@ namespace Symfony\Component\PropertyInfo; use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\PropertyInfo\Util\LegacyTypeConverter; use Symfony\Component\TypeInfo\Type; /** @@ -61,7 +62,40 @@ public function getProperties(string $class, array $context = []): ?array */ public function getType(string $class, string $property, array $context = []): ?Type { - return $this->extract('getType', [$class, $property, $context]); + try { + $serializedArguments = serialize([$class, $property, $context]); + } catch (\Exception) { + // If arguments are not serializable, skip the cache + if (method_exists($this->propertyInfoExtractor, 'getType')) { + return $this->propertyInfoExtractor->getType($class, $property, $context); + } + + return LegacyTypeConverter::toTypeInfoType($this->propertyInfoExtractor->getTypes($class, $property, $context)); + } + + // Calling rawurlencode escapes special characters not allowed in PSR-6's keys + $key = rawurlencode('getType.'.$serializedArguments); + + if (\array_key_exists($key, $this->arrayCache)) { + return $this->arrayCache[$key]; + } + + $item = $this->cacheItemPool->getItem($key); + + if ($item->isHit()) { + return $this->arrayCache[$key] = $item->get(); + } + + if (method_exists($this->propertyInfoExtractor, 'getType')) { + $value = $this->propertyInfoExtractor->getType($class, $property, $context); + } else { + $value = LegacyTypeConverter::toTypeInfoType($this->propertyInfoExtractor->getTypes($class, $property, $context)); + } + + $item->set($value); + $this->cacheItemPool->save($item); + + return $this->arrayCache[$key] = $value; } public function getTypes(string $class, string $property, array $context = []): ?array diff --git a/src/Symfony/Component/PropertyInfo/PropertyInfoExtractor.php b/src/Symfony/Component/PropertyInfo/PropertyInfoExtractor.php index 8e8952c7f4e23..b2bb878496221 100644 --- a/src/Symfony/Component/PropertyInfo/PropertyInfoExtractor.php +++ b/src/Symfony/Component/PropertyInfo/PropertyInfoExtractor.php @@ -11,6 +11,7 @@ namespace Symfony\Component\PropertyInfo; +use Symfony\Component\PropertyInfo\Util\LegacyTypeConverter; use Symfony\Component\TypeInfo\Type; /** @@ -58,7 +59,23 @@ public function getLongDescription(string $class, string $property, array $conte */ public function getType(string $class, string $property, array $context = []): ?Type { - return $this->extract($this->typeExtractors, 'getType', [$class, $property, $context]); + foreach ($this->typeExtractors as $extractor) { + if (!method_exists($extractor, 'getType')) { + $legacyTypes = $extractor->getTypes($class, $property, $context); + + if (null !== $legacyTypes) { + return LegacyTypeConverter::toTypeInfoType($legacyTypes); + } + + continue; + } + + if (null !== $value = $extractor->getType($class, $property, $context)) { + return $value; + } + } + + return null; } public function getTypes(string $class, string $property, array $context = []): ?array diff --git a/src/Symfony/Component/PropertyInfo/Tests/PropertyInfoCacheExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/PropertyInfoCacheExtractorTest.php index f9b1a8fc3358e..a594de56a5e42 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/PropertyInfoCacheExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/PropertyInfoCacheExtractorTest.php @@ -12,7 +12,13 @@ namespace Symfony\Component\PropertyInfo\Tests; use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; use Symfony\Component\PropertyInfo\PropertyInfoCacheExtractor; +use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; +use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; +use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy; +use Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy; +use Symfony\Component\TypeInfo\Type; /** * @author Kévin Dunglas @@ -76,4 +82,90 @@ public function testIsInitializable() parent::testIsInitializable(); parent::testIsInitializable(); } + + /** + * @group legacy + * + * @dataProvider provideNestedExtractorWithoutGetTypeImplementationData + */ + public function testNestedExtractorWithoutGetTypeImplementation(string $property, ?Type $expectedType) + { + $propertyInfoCacheExtractor = new PropertyInfoCacheExtractor(new class() implements PropertyInfoExtractorInterface { + private PropertyTypeExtractorInterface $propertyTypeExtractor; + + public function __construct() + { + $this->propertyTypeExtractor = new PhpDocExtractor(); + } + + public function getTypes(string $class, string $property, array $context = []): ?array + { + return $this->propertyTypeExtractor->getTypes($class, $property, $context); + } + + public function isReadable(string $class, string $property, array $context = []): ?bool + { + return null; + } + + public function isWritable(string $class, string $property, array $context = []): ?bool + { + return null; + } + + public function getShortDescription(string $class, string $property, array $context = []): ?string + { + return null; + } + + public function getLongDescription(string $class, string $property, array $context = []): ?string + { + return null; + } + + public function getProperties(string $class, array $context = []): ?array + { + return null; + } + }, new ArrayAdapter()); + + if (null === $expectedType) { + $this->assertNull($propertyInfoCacheExtractor->getType(Dummy::class, $property)); + } else { + $this->assertEquals($expectedType, $propertyInfoCacheExtractor->getType(Dummy::class, $property)); + } + } + + public function provideNestedExtractorWithoutGetTypeImplementationData() + { + yield ['bar', Type::string()]; + yield ['baz', Type::int()]; + yield ['bal', Type::object(\DateTimeImmutable::class)]; + yield ['parent', Type::object(ParentDummy::class)]; + yield ['collection', Type::array(Type::object(\DateTimeImmutable::class), Type::int())]; + yield ['nestedCollection', Type::array(Type::array(Type::string(), Type::int()), Type::int())]; + yield ['mixedCollection', Type::array()]; + yield ['B', Type::object(ParentDummy::class)]; + yield ['Id', Type::int()]; + yield ['Guid', Type::string()]; + yield ['g', Type::nullable(Type::array())]; + yield ['h', Type::nullable(Type::string())]; + yield ['i', Type::nullable(Type::union(Type::string(), Type::int()))]; + yield ['j', Type::nullable(Type::object(\DateTimeImmutable::class))]; + yield ['nullableCollectionOfNonNullableElements', Type::nullable(Type::array(Type::int(), Type::int()))]; + yield ['nonNullableCollectionOfNullableElements', Type::array(Type::nullable(Type::int()), Type::int())]; + yield ['nullableCollectionOfMultipleNonNullableElementTypes', Type::nullable(Type::array(Type::union(Type::int(), Type::string()), Type::int()))]; + yield ['xTotals', Type::array()]; + yield ['YT', Type::string()]; + yield ['emptyVar', null]; + yield ['iteratorCollection', Type::collection(Type::object(\Iterator::class), Type::string(), Type::union(Type::string(), Type::int()))]; + yield ['iteratorCollectionWithKey', Type::collection(Type::object(\Iterator::class), Type::string(), Type::int())]; + yield ['nestedIterators', Type::collection(Type::object(\Iterator::class), Type::collection(Type::object(\Iterator::class), Type::string(), Type::int()), Type::int())]; + yield ['arrayWithKeys', Type::array(Type::string(), Type::string())]; + yield ['arrayWithKeysAndComplexValue', Type::array(Type::nullable(Type::array(Type::nullable(Type::string()), Type::int())), Type::string())]; + yield ['arrayOfMixed', Type::array(Type::mixed(), Type::string())]; + yield ['noDocBlock', null]; + yield ['listOfStrings', Type::array(Type::string(), Type::int())]; + yield ['parentAnnotation', Type::object(ParentDummy::class)]; + } } diff --git a/src/Symfony/Component/PropertyInfo/Tests/PropertyInfoExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/PropertyInfoExtractorTest.php index 53c1b1d8a5c22..ed76df5695b08 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/PropertyInfoExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/PropertyInfoExtractorTest.php @@ -11,9 +11,76 @@ namespace Symfony\Component\PropertyInfo\Tests; +use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; +use Symfony\Component\PropertyInfo\PropertyInfoExtractor; +use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; +use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy; +use Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy; +use Symfony\Component\TypeInfo\Type; + /** * @author Kévin Dunglas */ class PropertyInfoExtractorTest extends AbstractPropertyInfoExtractorTest { + /** + * @group legacy + * + * @dataProvider provideNestedExtractorWithoutGetTypeImplementationData + */ + public function testNestedExtractorWithoutGetTypeImplementation(string $property, ?Type $expectedType) + { + $propertyInfoExtractor = new PropertyInfoExtractor([], [new class() implements PropertyTypeExtractorInterface { + private PropertyTypeExtractorInterface $propertyTypeExtractor; + + public function __construct() + { + $this->propertyTypeExtractor = new PhpDocExtractor(); + } + + public function getTypes(string $class, string $property, array $context = []): ?array + { + return $this->propertyTypeExtractor->getTypes($class, $property, $context); + } + }]); + + if (null === $expectedType) { + $this->assertNull($propertyInfoExtractor->getType(Dummy::class, $property)); + } else { + $this->assertEquals($expectedType, $propertyInfoExtractor->getType(Dummy::class, $property)); + } + } + + public function provideNestedExtractorWithoutGetTypeImplementationData() + { + yield ['bar', Type::string()]; + yield ['baz', Type::int()]; + yield ['bal', Type::object(\DateTimeImmutable::class)]; + yield ['parent', Type::object(ParentDummy::class)]; + yield ['collection', Type::array(Type::object(\DateTimeImmutable::class), Type::int())]; + yield ['nestedCollection', Type::array(Type::array(Type::string(), Type::int()), Type::int())]; + yield ['mixedCollection', Type::array()]; + yield ['B', Type::object(ParentDummy::class)]; + yield ['Id', Type::int()]; + yield ['Guid', Type::string()]; + yield ['g', Type::nullable(Type::array())]; + yield ['h', Type::nullable(Type::string())]; + yield ['i', Type::nullable(Type::union(Type::string(), Type::int()))]; + yield ['j', Type::nullable(Type::object(\DateTimeImmutable::class))]; + yield ['nullableCollectionOfNonNullableElements', Type::nullable(Type::array(Type::int(), Type::int()))]; + yield ['nonNullableCollectionOfNullableElements', Type::array(Type::nullable(Type::int()), Type::int())]; + yield ['nullableCollectionOfMultipleNonNullableElementTypes', Type::nullable(Type::array(Type::union(Type::int(), Type::string()), Type::int()))]; + yield ['xTotals', Type::array()]; + yield ['YT', Type::string()]; + yield ['emptyVar', null]; + yield ['iteratorCollection', Type::collection(Type::object(\Iterator::class), Type::string(), Type::union(Type::string(), Type::int()))]; + yield ['iteratorCollectionWithKey', Type::collection(Type::object(\Iterator::class), Type::string(), Type::int())]; + yield ['nestedIterators', Type::collection(Type::object(\Iterator::class), Type::collection(Type::object(\Iterator::class), Type::string(), Type::int()), Type::int())]; + yield ['arrayWithKeys', Type::array(Type::string(), Type::string())]; + yield ['arrayWithKeysAndComplexValue', Type::array(Type::nullable(Type::array(Type::nullable(Type::string()), Type::int())), Type::string())]; + yield ['arrayOfMixed', Type::array(Type::mixed(), Type::string())]; + yield ['noDocBlock', null]; + yield ['listOfStrings', Type::array(Type::string(), Type::int())]; + yield ['parentAnnotation', Type::object(ParentDummy::class)]; + } } diff --git a/src/Symfony/Component/PropertyInfo/Util/LegacyTypeConverter.php b/src/Symfony/Component/PropertyInfo/Util/LegacyTypeConverter.php new file mode 100644 index 0000000000000..24cae602aac5b --- /dev/null +++ b/src/Symfony/Component/PropertyInfo/Util/LegacyTypeConverter.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyInfo\Util; + +use Symfony\Component\PropertyInfo\Type as LegacyType; +use Symfony\Component\TypeInfo\Type; + +/** + * @internal + */ +class LegacyTypeConverter +{ + /** + * @param LegacyType[]|null $legacyTypes + */ + public static function toTypeInfoType(?array $legacyTypes): ?Type + { + if (null === $legacyTypes || [] === $legacyTypes) { + return null; + } + + $nullable = false; + $types = []; + + foreach ($legacyTypes as $legacyType) { + switch ($legacyType->getBuiltinType()) { + case LegacyType::BUILTIN_TYPE_ARRAY: + $typeInfoType = Type::array(self::toTypeInfoType($legacyType->getCollectionValueTypes()), self::toTypeInfoType($legacyType->getCollectionKeyTypes())); + break; + case LegacyType::BUILTIN_TYPE_BOOL: + $typeInfoType = Type::bool(); + break; + case LegacyType::BUILTIN_TYPE_CALLABLE: + $typeInfoType = Type::callable(); + break; + case LegacyType::BUILTIN_TYPE_FALSE: + $typeInfoType = Type::false(); + break; + case LegacyType::BUILTIN_TYPE_FLOAT: + $typeInfoType = Type::float(); + break; + case LegacyType::BUILTIN_TYPE_INT: + $typeInfoType = Type::int(); + break; + case LegacyType::BUILTIN_TYPE_ITERABLE: + $typeInfoType = Type::iterable(self::toTypeInfoType($legacyType->getCollectionValueTypes()), self::toTypeInfoType($legacyType->getCollectionKeyTypes())); + break; + case LegacyType::BUILTIN_TYPE_OBJECT: + if ($legacyType->isCollection()) { + $typeInfoType = Type::collection(Type::object($legacyType->getClassName()), self::toTypeInfoType($legacyType->getCollectionValueTypes()), self::toTypeInfoType($legacyType->getCollectionKeyTypes())); + } else { + $typeInfoType = Type::object($legacyType->getClassName()); + } + + break; + case LegacyType::BUILTIN_TYPE_RESOURCE: + $typeInfoType = Type::resource(); + break; + case LegacyType::BUILTIN_TYPE_STRING: + $typeInfoType = Type::string(); + break; + case LegacyType::BUILTIN_TYPE_TRUE: + $typeInfoType = Type::true(); + break; + default: + $typeInfoType = null; + break; + } + + if (LegacyType::BUILTIN_TYPE_NULL === $legacyType->getBuiltinType() || $legacyType->isNullable()) { + $nullable = true; + } + + if (null !== $typeInfoType) { + $types[] = $typeInfoType; + } + } + + if (1 === \count($types)) { + return $nullable ? Type::nullable($types[0]) : $types[0]; + } + + return $nullable ? Type::nullable(Type::union(...$types)) : Type::union(...$types); + } +} From f3124d18af46efafd0f5beeb88fecf0e324577c4 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 21 Jan 2025 11:50:39 +0100 Subject: [PATCH 38/57] [Validator] Fix `Url` constraint attribute assertion --- .../Component/Validator/Tests/Constraints/UrlTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UrlTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UrlTest.php index 1d641aa925077..59e626eda2c3c 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UrlTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UrlTest.php @@ -68,9 +68,9 @@ public function testAttributes() self::assertFalse($cConstraint->requireTld); [$dConstraint] = $metadata->properties['d']->getConstraints(); - self::assertSame(['http', 'https'], $aConstraint->protocols); - self::assertFalse($aConstraint->relativeProtocol); - self::assertNull($aConstraint->normalizer); + self::assertSame(['http', 'https'], $dConstraint->protocols); + self::assertFalse($dConstraint->relativeProtocol); + self::assertNull($dConstraint->normalizer); self::assertTrue($dConstraint->requireTld); } From 46dc6abf2fcbed45de08087352daf5e220cca89f Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 21 Jan 2025 11:52:27 +0100 Subject: [PATCH 39/57] [PropertyInfo] Fix `TypeTest` duplicated assert --- src/Symfony/Component/PropertyInfo/Tests/TypeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/PropertyInfo/Tests/TypeTest.php b/src/Symfony/Component/PropertyInfo/Tests/TypeTest.php index e871ed49f7b2a..87b498768d22a 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/TypeTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/TypeTest.php @@ -75,7 +75,7 @@ public function testArrayCollection() $this->assertTrue($firstValueType->isCollection()); $this->assertEquals(Type::BUILTIN_TYPE_ARRAY, $secondValueType->getBuiltinType()); $this->assertFalse($secondValueType->isNullable()); - $this->assertTrue($firstValueType->isCollection()); + $this->assertTrue($secondValueType->isCollection()); } public function testInvalidCollectionValueArgument() From d75184accc756139cad223fda3cff97bbd78ca9f Mon Sep 17 00:00:00 2001 From: Tom Korec Date: Tue, 21 Jan 2025 20:33:52 +0100 Subject: [PATCH 40/57] Mark Czech Validator translation as reviewed Addresses https://github.com/symfony/symfony/issues/59415. --- .../Validator/Resources/translations/validators.cs.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf index 3bf44da803535..b45c9c285a54c 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf @@ -468,7 +468,7 @@ This value is not a valid slug. - Tato hodnota není platný slug. + Tato hodnota není platný slug. From 19fd27d796e9671e8059f9941fdfb50d7609447c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 22 Jan 2025 12:30:12 +0100 Subject: [PATCH 41/57] [FrameworkBundle] Fix patching refs to the tmp warmup dir in files generated by optional cache warmers --- .../Command/CacheClearCommand.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index cdfc7f34f3730..eeafd1bd3ac00 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -146,6 +146,16 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $this->warmupOptionals($useBuildDir ? $realCacheDir : $warmupDir, $warmupDir, $io); } + + // fix references to cached files with the real cache directory name + $search = [$warmupDir, str_replace('/', '\\/', $warmupDir), str_replace('\\', '\\\\', $warmupDir)]; + $replace = str_replace('\\', '/', $realBuildDir); + foreach (Finder::create()->files()->in($warmupDir) as $file) { + $content = str_replace($search, $replace, file_get_contents($file), $count); + if ($count) { + file_put_contents($file, $content); + } + } } if (!$fs->exists($warmupDir.'/'.$containerDir)) { @@ -227,16 +237,6 @@ private function warmup(string $warmupDir, string $realBuildDir): void throw new \LogicException('Calling "cache:clear" with a kernel that does not implement "Symfony\Component\HttpKernel\RebootableInterface" is not supported.'); } $kernel->reboot($warmupDir); - - // fix references to cached files with the real cache directory name - $search = [$warmupDir, str_replace('\\', '\\\\', $warmupDir)]; - $replace = str_replace('\\', '/', $realBuildDir); - foreach (Finder::create()->files()->in($warmupDir) as $file) { - $content = str_replace($search, $replace, file_get_contents($file), $count); - if ($count) { - file_put_contents($file, $content); - } - } } private function warmupOptionals(string $cacheDir, string $warmupDir, SymfonyStyle $io): void From 8e820561295b28366becfddce274d7e52cf37f2a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 22 Jan 2025 14:48:49 +0100 Subject: [PATCH 42/57] [Cache] Don't clear system caches on cache:clear --- .../Tests/Functional/CachePoolsTest.php | 4 ---- .../Functional/ContainerDebugCommandTest.php | 20 +++++++++++-------- .../Functional/app/CachePools/default.yml | 5 ----- .../DependencyInjection/CachePoolPass.php | 4 ---- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php index 2608966586a78..23f4a116ef341 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php @@ -88,10 +88,6 @@ private function doTestCachePools($options, $adapterClass) $pool2 = $container->get('cache.pool2'); $pool2->save($item); - $container->get('cache_clearer.alias')->clear($container->getParameter('kernel.cache_dir')); - $item = $pool1->getItem($key); - $this->assertFalse($item->isHit()); - $item = $pool2->getItem($key); $this->assertTrue($item->isHit()); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php index 1adddd1832500..24c6faf332525 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php @@ -139,14 +139,18 @@ public function testTagsPartialSearch() $tester->setInputs(['0']); $tester->run(['command' => 'debug:container', '--tag' => 'kernel.'], ['decorated' => false]); - $this->assertStringContainsString('Select one of the following tags to display its information', $tester->getDisplay()); - $this->assertStringContainsString('[0] kernel.cache_clearer', $tester->getDisplay()); - $this->assertStringContainsString('[1] kernel.cache_warmer', $tester->getDisplay()); - $this->assertStringContainsString('[2] kernel.event_subscriber', $tester->getDisplay()); - $this->assertStringContainsString('[3] kernel.fragment_renderer', $tester->getDisplay()); - $this->assertStringContainsString('[4] kernel.locale_aware', $tester->getDisplay()); - $this->assertStringContainsString('[5] kernel.reset', $tester->getDisplay()); - $this->assertStringContainsString('Symfony Container Services Tagged with "kernel.cache_clearer" Tag', $tester->getDisplay()); + $this->assertStringMatchesFormat(<<getDisplay() + ); } public function testDescribeEnvVars() diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/default.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/default.yml index c03efedd02bf7..377d3e7852064 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/default.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/default.yml @@ -1,7 +1,2 @@ imports: - { resource: ../config/default.yml } - -services: - cache_clearer.alias: - alias: cache_clearer - public: true diff --git a/src/Symfony/Component/Cache/DependencyInjection/CachePoolPass.php b/src/Symfony/Component/Cache/DependencyInjection/CachePoolPass.php index f6622f27bdc19..90c089074ef4b 100644 --- a/src/Symfony/Component/Cache/DependencyInjection/CachePoolPass.php +++ b/src/Symfony/Component/Cache/DependencyInjection/CachePoolPass.php @@ -197,10 +197,6 @@ public function process(ContainerBuilder $container) $clearer->setArgument(0, $pools); } $clearer->addTag('cache.pool.clearer'); - - if ('cache.system_clearer' === $id) { - $clearer->addTag('kernel.cache_clearer'); - } } $allPoolsKeys = array_keys($allPools); From 5235350340dfd94dca8ac52af1eb12e238a02c50 Mon Sep 17 00:00:00 2001 From: Asis Pattisahusiwa <79239132+asispts@users.noreply.github.com> Date: Thu, 23 Jan 2025 00:19:23 +0700 Subject: [PATCH 43/57] Review translation --- .../Resources/translations/validators.id.xlf | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf index a9a4c60aeade0..bf9187b74c339 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf @@ -444,31 +444,31 @@ This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Nilai ini terlalu pendek. Seharusnya berisi setidaknya satu kata.|Nilai ini terlalu pendek. Seharusnya berisi setidaknya {{ min }} kata. + Nilai ini terlalu pendek. Seharusnya berisi setidaknya satu kata.|Nilai ini terlalu pendek. Seharusnya berisi setidaknya {{ min }} kata. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Nilai ini terlalu panjang. Seharusnya hanya berisi satu kata.|Nilai ini terlalu panjang. Seharusnya berisi {{ max }} kata atau kurang. + Nilai ini terlalu panjang. Seharusnya hanya berisi satu kata.|Nilai ini terlalu panjang. Seharusnya berisi {{ max }} kata atau kurang. This value does not represent a valid week in the ISO 8601 format. - Nilai ini tidak mewakili minggu yang valid dalam format ISO 8601. + Nilai ini tidak mewakili minggu yang valid dalam format ISO 8601. This value is not a valid week. - Nilai ini bukan minggu yang valid. + Nilai ini bukan minggu yang valid. This value should not be before week "{{ min }}". - Nilai ini tidak boleh sebelum minggu "{{ min }}". + Nilai ini tidak boleh sebelum minggu "{{ min }}". This value should not be after week "{{ max }}". - Nilai ini tidak boleh setelah minggu "{{ max }}". + Nilai ini tidak boleh setelah minggu "{{ max }}". This value is not a valid slug. - Nilai ini bukan slug yang valid. + Nilai ini bukan slug yang valid. From 5a084c449ec0116353f69f06aff99642c94c6182 Mon Sep 17 00:00:00 2001 From: Gil Hadad Date: Wed, 22 Jan 2025 22:59:03 +0200 Subject: [PATCH 44/57] Fixed mistakes in proper hebrew writing in the previous translation and confirmed the rest to be correct and in the same style. --- .../Resources/translations/security.he.xlf | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.he.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.he.xlf index b1d6afd434e8a..1cf02a4ee75e6 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.he.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.he.xlf @@ -4,15 +4,15 @@ An authentication exception occurred. - שגיאה באימות + התרחשה שגיאה באימות. Authentication credentials could not be found. - פרטי זיהוי לא נמצאו. + פרטי הזיהוי לא נמצאו. Authentication request could not be processed due to a system problem. - לא ניתן היה לעבד את בקשת אימות בגלל בעיית מערכת. + לא ניתן היה לעבד את בקשת האימות בגלל בעיית מערכת. Invalid credentials. @@ -20,7 +20,7 @@ Cookie has already been used by someone else. - עוגיה כבר שומשה. + עוגיה כבר שומשה על ידי מישהו אחר. Not privileged to request the resource. @@ -32,15 +32,15 @@ No authentication provider found to support the authentication token. - לא נמצא ספק אימות המתאימה לבקשה. + לא נמצא ספק אימות המתאים לבקשה. No session available, it either timed out or cookies are not enabled. - אין סיישן זמין, או שתם הזמן הקצוב או העוגיות אינן מופעלות. + אין מפגש זמין, תם הזמן הקצוב או שהעוגיות אינן מופעלות. No token could be found. - הטוקן לא נמצא. + אסימון לא נמצא. Username could not be found. @@ -72,11 +72,11 @@ Too many failed login attempts, please try again in %minutes% minute. - יותר מדי ניסיונות כניסה כושלים, אנא נסה שוב בוד %minutes% דקה. + יותר מדי ניסיונות כניסה כושלים, אנא נסה שוב בעוד %minutes% דקה. Too many failed login attempts, please try again in %minutes% minutes. - יותר מדי ניסיונות כניסה כושלים, אנא נסה שוב בעוד %minutes% דקות. + יותר מדי ניסיונות כניסה כושלים, אנא נסה שוב בעוד %minutes% דקות. From 973ee38f06109e850c3e0504343c161f99da6520 Mon Sep 17 00:00:00 2001 From: Abdelilah Jabri <42073961+JabriAbdelilah@users.noreply.github.com> Date: Thu, 23 Jan 2025 10:21:34 +0100 Subject: [PATCH 45/57] Review Arabic translations for the validator --- .../Resources/translations/validators.ar.xlf | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf index 96fd59f68a520..d139f1bd1abbe 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf @@ -444,31 +444,31 @@ This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - هذه القيمة قصيرة جدًا. يجب أن تحتوي على كلمة واحدة على الأقل.|هذه القيمة قصيرة جدًا. يجب أن تحتوي على {{ min }} كلمة على الأقل. + هذه القيمة قصيرة جدًا. يجب أن تحتوي على كلمة واحدة على الأقل.|هذه القيمة قصيرة جدًا. يجب أن تحتوي على {{ min }} كلمة على الأقل. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - هذه القيمة طويلة جدًا. يجب أن تحتوي على كلمة واحدة فقط.|هذه القيمة طويلة جدًا. يجب أن تحتوي على {{ max }} كلمة أو أقل. + هذه القيمة طويلة جدًا. يجب أن تحتوي على كلمة واحدة فقط.|هذه القيمة طويلة جدًا. يجب أن تحتوي على {{ max }} كلمة أو أقل. This value does not represent a valid week in the ISO 8601 format. - هذه القيمة لا تمثل أسبوعًا صالحًا في تنسيق ISO 8601. + هذه القيمة لا تمثل أسبوعًا صالحًا وفق تنسيق ISO 8601. This value is not a valid week. - هذه القيمة ليست أسبوعًا صالحًا. + هذه القيمة ليست أسبوعًا صالحًا. This value should not be before week "{{ min }}". - يجب ألا تكون هذه القيمة قبل الأسبوع "{{ min }}". + يجب ألا تكون هذه القيمة قبل الأسبوع "{{ min }}". This value should not be after week "{{ max }}". - يجب ألا تكون هذه القيمة بعد الأسبوع "{{ max }}". + يجب ألا تكون هذه القيمة بعد الأسبوع "{{ max }}". This value is not a valid slug. - هذه القيمة ليست شريحة صالحة. + هذه القيمة ليست رمزا صالحا. From 7189743853ddf103f25445d3e63abc834991fa01 Mon Sep 17 00:00:00 2001 From: InbarAbraham Date: Thu, 23 Jan 2025 12:58:09 +0200 Subject: [PATCH 46/57] translation to hebrew --- .../Resources/translations/validators.he.xlf | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf index edd8a8a4fd9f4..107051c11dfd2 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf @@ -136,7 +136,7 @@ This value is not a valid IP address. - ערך זה אינו כתובת IP תקפה. + ערך זה אינו כתובת IP תקפה. This value is not a valid language. @@ -192,7 +192,7 @@ No temporary folder was configured in php.ini, or the configured folder does not exist. - לא הוגדרה תיקייה זמנית ב-php.ini, או שהתיקייה המוגדרת אינה קיימת. + לא הוגדרה תיקייה זמנית ב-php.ini, או שהתיקייה המוגדרת אינה קיימת. Cannot write temporary file to disk. @@ -224,7 +224,7 @@ This value is not a valid International Bank Account Number (IBAN). - ערך זה אינו מספר חשבון בנק בינלאומי (IBAN) תקף. + ערך זה אינו מספר זה"ב (IBAN) תקף. This value is not a valid ISBN-10. @@ -312,7 +312,7 @@ This value is not a valid Business Identifier Code (BIC). - ערך זה אינו קוד מזהה עסקי (BIC) תקף. + ערך זה אינו קוד מזהה עסקי (BIC) תקף. Error @@ -320,7 +320,7 @@ This value is not a valid UUID. - ערך זה אינו UUID תקף. + ערך זה אינו UUID תקף. This value should be a multiple of {{ compared_value }}. @@ -404,39 +404,39 @@ The filename is too long. It should have {{ filename_max_length }} character or less.|The filename is too long. It should have {{ filename_max_length }} characters or less. - שם הקובץ ארוך מדי. עליו להכיל {{ filename_max_length }} תווים או פחות. + שם הקובץ ארוך מדי. עליו להכיל {{ filename_max_length }} תווים או פחות. The password strength is too low. Please use a stronger password. - חוזק הסיסמה נמוך מדי. אנא השתמש בסיסמה חזקה יותר. + חוזק הסיסמה נמוך מדי. אנא השתמש בסיסמה חזקה יותר. This value contains characters that are not allowed by the current restriction-level. - הערך כולל תווים שאינם מותרים על פי רמת ההגבלה הנוכחית. + הערך כולל תווים שאינם מותרים על פי רמת ההגבלה הנוכחית. Using invisible characters is not allowed. - אסור להשתמש בתווים בלתי נראים. + אסור להשתמש בתווים בלתי נראים. Mixing numbers from different scripts is not allowed. - אסור לערבב מספרים מתסריטים שונים. + אסור לערבב מספרים מסקריפטים שונים. Using hidden overlay characters is not allowed. - אסור להשתמש בתווים מוסתרים של חפיפה. + אסור להשתמש בתווים חופפים נסתרים. The extension of the file is invalid ({{ extension }}). Allowed extensions are {{ extensions }}. - סיומת הקובץ אינה תקינה ({{ extension }}). הסיומות המותרות הן {{ extensions }}. + סיומת הקובץ אינה תקינה ({{ extension }}). הסיומות המותרות הן {{ extensions }}. The detected character encoding is invalid ({{ detected }}). Allowed encodings are {{ encodings }}. - קידוד התווים שזוהה אינו חוקי ({{ detected }}). הקידודים המותרים הם {{ encodings }}. + קידוד התווים שזוהה אינו חוקי ({{ detected }}). הקידודים המותרים הם {{ encodings }}. This value is not a valid MAC address. - ערך זה אינו כתובת MAC תקפה. + ערך זה אינו כתובת MAC תקפה. This URL is missing a top-level domain. From b983d1b8d55f1b293c5c512efa9cb64ca427ad27 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Thu, 23 Jan 2025 14:10:52 +0100 Subject: [PATCH 47/57] [Mime] Fix body validity check in `Email` when using `Message::setBody()` --- src/Symfony/Component/Mime/Email.php | 2 +- .../Component/Mime/Tests/EmailTest.php | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Mime/Email.php b/src/Symfony/Component/Mime/Email.php index 346618cf252ca..797e0028f6c4f 100644 --- a/src/Symfony/Component/Mime/Email.php +++ b/src/Symfony/Component/Mime/Email.php @@ -416,7 +416,7 @@ public function ensureValidity() private function ensureBodyValid(): void { - if (null === $this->text && null === $this->html && !$this->attachments) { + if (null === $this->text && null === $this->html && !$this->attachments && null === parent::getBody()) { throw new LogicException('A message must have a text or an HTML part or attachments.'); } } diff --git a/src/Symfony/Component/Mime/Tests/EmailTest.php b/src/Symfony/Component/Mime/Tests/EmailTest.php index ae61f26f605b4..3aa86c5f94623 100644 --- a/src/Symfony/Component/Mime/Tests/EmailTest.php +++ b/src/Symfony/Component/Mime/Tests/EmailTest.php @@ -695,4 +695,60 @@ public function testEmailsWithAttachmentsWhichAreAFileInstanceCanBeUnserialized( $this->assertCount(1, $attachments); $this->assertStringContainsString('foo_bar_xyz_123', $attachments[0]->getBody()); } + + public function testInvalidBodyWithEmptyEmail() + { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('A message must have a text or an HTML part or attachments.'); + + (new Email())->ensureValidity(); + } + + public function testBodyWithTextIsValid() + { + $email = new Email(); + $email->to('test@example.com') + ->from('test@example.com') + ->text('foo'); + + $email->ensureValidity(); + + $this->expectNotToPerformAssertions(); + } + + public function testBodyWithHtmlIsValid() + { + $email = new Email(); + $email->to('test@example.com') + ->from('test@example.com') + ->html('foo'); + + $email->ensureValidity(); + + $this->expectNotToPerformAssertions(); + } + + public function testEmptyBodyWithAttachmentsIsValid() + { + $email = new Email(); + $email->to('test@example.com') + ->from('test@example.com') + ->addPart(new DataPart('foo')); + + $email->ensureValidity(); + + $this->expectNotToPerformAssertions(); + } + + public function testSetBodyIsValid() + { + $email = new Email(); + $email->to('test@example.com') + ->from('test@example.com') + ->setBody(new TextPart('foo')); + + $email->ensureValidity(); + + $this->expectNotToPerformAssertions(); + } } From 398e09a205a6c52bd1eb1bb8e0710c7606aaf78b Mon Sep 17 00:00:00 2001 From: Pavol Tuka <30590523+pavol-tuka@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:44:35 +0100 Subject: [PATCH 48/57] Fix typo in validators.sk.xlf --- .../Validator/Resources/translations/validators.sk.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf index 0706ed07109fc..d7cf634c7e909 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf @@ -336,7 +336,7 @@ This collection should contain only unique elements. - Táto kolekcia by mala obsahovať len unikátne prkvy. + Táto kolekcia by mala obsahovať len unikátne prvky. This value should be positive. From 32a7d14fd031f6f5448c6a8a9d913856ebdbab1d Mon Sep 17 00:00:00 2001 From: Kieran Brahney Date: Fri, 24 Jan 2025 15:27:15 +0000 Subject: [PATCH 49/57] Ensure TransportExceptionInterface populates stream debug data --- .../Component/Mailer/Transport/Smtp/SmtpTransport.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php b/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php index 0de38fb2ed690..7de2f91cbc132 100644 --- a/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php +++ b/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php @@ -205,11 +205,11 @@ protected function doSend(SentMessage $message): void $this->ping(); } - if (!$this->started) { - $this->start(); - } - try { + if (!$this->started) { + $this->start(); + } + $envelope = $message->getEnvelope(); $this->doMailFromCommand($envelope->getSender()->getEncodedAddress()); foreach ($envelope->getRecipients() as $recipient) { From 6c2017282bceb74ad4feb604646c6b56dc19b1d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Tue, 21 Jan 2025 22:36:59 +0100 Subject: [PATCH 50/57] Add support for doctrine/persistence 4 v4 provides a guarantee that ManagerRegistry::getManager() returns an entity manager (as opposed to null). The tests need to be adjusted to reflect the behavior of the mocked dependency more accurately, as it is throwing an exception in case of a null manager for all three supported versions of the library. --- composer.json | 2 +- .../ArgumentResolver/EntityValueResolverTest.php | 10 +++++++--- .../Constraints/UniqueEntityValidatorTest.php | 14 ++++++++++---- .../Constraints/UniqueEntityValidator.php | 8 ++++---- src/Symfony/Bridge/Doctrine/composer.json | 2 +- 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/composer.json b/composer.json index d4e6370e216e9..53f24f502f0d4 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,7 @@ "ext-xml": "*", "friendsofphp/proxy-manager-lts": "^1.0.2", "doctrine/event-manager": "^1.2|^2", - "doctrine/persistence": "^2.5|^3.1", + "doctrine/persistence": "^2.5|^3.1|^4", "twig/twig": "^2.13|^3.0.4", "psr/cache": "^2.0|^3.0", "psr/clock": "^1.0", diff --git a/src/Symfony/Bridge/Doctrine/Tests/ArgumentResolver/EntityValueResolverTest.php b/src/Symfony/Bridge/Doctrine/Tests/ArgumentResolver/EntityValueResolverTest.php index 471ab56aef337..022af885002ee 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/ArgumentResolver/EntityValueResolverTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/ArgumentResolver/EntityValueResolverTest.php @@ -415,9 +415,13 @@ private function createRegistry(?ObjectManager $manager = null): ManagerRegistry ->method('getManagerForClass') ->willReturn($manager); - $registry->expects($this->any()) - ->method('getManager') - ->willReturn($manager); + if (null === $manager) { + $registry->method('getManager') + ->willThrowException(new \InvalidArgumentException()); + } else { + $registry->method('getManager')->willReturn($manager); + } + return $registry; } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index 82c122c4ef486..efb28dbdff66c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -76,10 +76,16 @@ protected function setUp(): void protected function createRegistryMock($em = null) { $registry = $this->createMock(ManagerRegistry::class); - $registry->expects($this->any()) - ->method('getManager') - ->with($this->equalTo(self::EM_NAME)) - ->willReturn($em); + + if (null === $em) { + $registry->method('getManager') + ->with($this->equalTo(self::EM_NAME)) + ->willThrowException(new \InvalidArgumentException()); + } else { + $registry->method('getManager') + ->with($this->equalTo(self::EM_NAME)) + ->willReturn($em); + } return $registry; } diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php index 821815d055906..b356f8068c15d 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php @@ -69,10 +69,10 @@ public function validate(mixed $entity, Constraint $constraint) } if ($constraint->em) { - $em = $this->registry->getManager($constraint->em); - - if (!$em) { - throw new ConstraintDefinitionException(sprintf('Object manager "%s" does not exist.', $constraint->em)); + try { + $em = $this->registry->getManager($constraint->em); + } catch (\InvalidArgumentException $e) { + throw new ConstraintDefinitionException(sprintf('Object manager "%s" does not exist.', $constraint->em), 0, $e); } } else { $em = $this->registry->getManagerForClass($entity::class); diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 3379073eb9192..17828cabe6d66 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=8.1", "doctrine/event-manager": "^1.2|^2", - "doctrine/persistence": "^2.5|^3.1", + "doctrine/persistence": "^2.5|^3.1|^4", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", From 9a43703854c3922f8899b6434e02c2871367ef60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Andr=C3=A9?= Date: Fri, 17 Jan 2025 23:46:22 +0100 Subject: [PATCH 51/57] [AssetMapper] Fix CssCompiler matches url in comments --- .../Compiler/CssAssetUrlCompiler.php | 27 ++++++++++++++++- .../Compiler/CssAssetUrlCompilerTest.php | 30 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/AssetMapper/Compiler/CssAssetUrlCompiler.php b/src/Symfony/Component/AssetMapper/Compiler/CssAssetUrlCompiler.php index 09a8beb8b1a2c..a005256604e90 100644 --- a/src/Symfony/Component/AssetMapper/Compiler/CssAssetUrlCompiler.php +++ b/src/Symfony/Component/AssetMapper/Compiler/CssAssetUrlCompiler.php @@ -35,7 +35,32 @@ public function __construct( public function compile(string $content, MappedAsset $asset, AssetMapperInterface $assetMapper): string { - return preg_replace_callback(self::ASSET_URL_PATTERN, function ($matches) use ($asset, $assetMapper) { + preg_match_all('/\/\*|\*\//', $content, $commentMatches, \PREG_OFFSET_CAPTURE); + + $start = null; + $commentBlocks = []; + foreach ($commentMatches[0] as $match) { + if ('/*' === $match[0]) { + $start = $match[1]; + } elseif ($start) { + $commentBlocks[] = [$start, $match[1]]; + $start = null; + } + } + + return preg_replace_callback(self::ASSET_URL_PATTERN, function ($matches) use ($asset, $assetMapper, $commentBlocks) { + $matchPos = $matches[0][1]; + + // Ignore matchs inside comments + foreach ($commentBlocks as $block) { + if ($matchPos > $block[0]) { + if ($matchPos < $block[1]) { + return $matches[0][0]; + } + break; + } + } + try { $resolvedSourcePath = Path::join(\dirname($asset->sourcePath), $matches[1]); } catch (RuntimeException $e) { diff --git a/src/Symfony/Component/AssetMapper/Tests/Compiler/CssAssetUrlCompilerTest.php b/src/Symfony/Component/AssetMapper/Tests/Compiler/CssAssetUrlCompilerTest.php index 999407c81a558..067168b059a71 100644 --- a/src/Symfony/Component/AssetMapper/Tests/Compiler/CssAssetUrlCompilerTest.php +++ b/src/Symfony/Component/AssetMapper/Tests/Compiler/CssAssetUrlCompilerTest.php @@ -114,6 +114,36 @@ public static function provideCompileTests(): iterable 'expectedOutput' => 'body { background: url("https://cdn.io/images/bar.png"); }', 'expectedDependencies' => [], ]; + + yield 'ignore_comments' => [ + 'input' => 'body { background: url("images/foo.png"); /* background: url("images/bar.png"); */ }', + 'expectedOutput' => 'body { background: url("images/foo.123456.png"); /* background: url("images/bar.png"); */ }', + 'expectedDependencies' => ['images/foo.png'], + ]; + + yield 'ignore_comment_after_rule' => [ + 'input' => 'body { background: url("images/foo.png"); } /* url("images/need-ignore.png") */', + 'expectedOutput' => 'body { background: url("images/foo.123456.png"); } /* url("images/need-ignore.png") */', + 'expectedDependencies' => ['images/foo.png'], + ]; + + yield 'ignore_comment_within_rule' => [ + 'input' => 'body { background: url("images/foo.png") /* url("images/need-ignore.png") */; }', + 'expectedOutput' => 'body { background: url("images/foo.123456.png") /* url("images/need-ignore.png") */; }', + 'expectedDependencies' => ['images/foo.png'], + ]; + + yield 'ignore_multiline_comment_after_rule' => [ + 'input' => 'body { + background: url("images/foo.png"); /* + url("images/need-ignore.png") */ + }', + 'expectedOutput' => 'body { + background: url("images/foo.123456.png"); /* + url("images/need-ignore.png") */ + }', + 'expectedDependencies' => ['images/foo.png'], + ]; } public function testCompileFindsRelativeFilesViaSourcePath() From 65c214757a194d7729af457ab8ab2ad86eaa2ea8 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Mon, 27 Jan 2025 11:11:56 +0100 Subject: [PATCH 52/57] [FrameworkBundle] Add missing `not-compromised-password` entry in XSD --- .../FrameworkBundle/Resources/config/schema/symfony-1.0.xsd | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index cdc4fa5d52556..7d9828eeb2351 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -266,6 +266,7 @@ + @@ -299,6 +300,11 @@ + + + + + From cd427c310d8f7a6b722174f80d288a1e4b51c6fa Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Thu, 23 Jan 2025 09:38:36 +0100 Subject: [PATCH 53/57] [Security] Throw an explicit error when authenticating a token with a null user --- .../Http/Firewall/ContextListener.php | 4 +++ .../Tests/Firewall/ContextListenerTest.php | 25 +++++++++++++++++++ .../Http/Tests/Fixtures/NullUserToken.php | 23 +++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 src/Symfony/Component/Security/Http/Tests/Fixtures/NullUserToken.php diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index e8ad79d83cd40..d06b6d57ae32e 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -123,6 +123,10 @@ public function authenticate(RequestEvent $event): void ]); if ($token instanceof TokenInterface) { + if (!$token->getUser()) { + throw new \UnexpectedValueException(\sprintf('Cannot authenticate a "%s" token because it doesn\'t store a user.', $token::class)); + } + $originalToken = $token; $token = $this->refreshUser($token); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php index 8d0ab72658aff..8dcf96ed6fb8a 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php @@ -36,6 +36,7 @@ use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\Firewall\ContextListener; +use Symfony\Component\Security\Http\Tests\Fixtures\NullUserToken; use Symfony\Contracts\Service\ServiceLocatorTrait; class ContextListenerTest extends TestCase @@ -58,6 +59,30 @@ public function testUserProvidersNeedToImplementAnInterface() $this->handleEventWithPreviousSession([new \stdClass()]); } + public function testTokenReturnsNullUser() + { + $tokenStorage = new TokenStorage(); + $tokenStorage->setToken(new NullUserToken()); + + $session = new Session(new MockArraySessionStorage()); + $session->set('_security_context_key', serialize($tokenStorage->getToken())); + + $request = new Request(); + $request->setSession($session); + $request->cookies->set('MOCKSESSID', true); + + $listener = new ContextListener($tokenStorage, [], 'context_key'); + + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionMessage('Cannot authenticate a "Symfony\Component\Security\Http\Tests\Fixtures\NullUserToken" token because it doesn\'t store a user.'); + + $listener->authenticate(new RequestEvent( + $this->createMock(HttpKernelInterface::class), + $request, + HttpKernelInterface::MAIN_REQUEST, + )); + } + public function testOnKernelResponseWillAddSession() { $session = $this->runSessionOnKernelResponse( diff --git a/src/Symfony/Component/Security/Http/Tests/Fixtures/NullUserToken.php b/src/Symfony/Component/Security/Http/Tests/Fixtures/NullUserToken.php new file mode 100644 index 0000000000000..95048e464a3f9 --- /dev/null +++ b/src/Symfony/Component/Security/Http/Tests/Fixtures/NullUserToken.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Http\Tests\Fixtures; + +use Symfony\Component\Security\Core\Authentication\Token\AbstractToken; +use Symfony\Component\Security\Core\User\UserInterface; + +class NullUserToken extends AbstractToken +{ + public function getUser(): ?UserInterface + { + return null; + } +} From 0a4521e32f0082bb5248319839430877bc940a77 Mon Sep 17 00:00:00 2001 From: "hubert.lenoir" Date: Mon, 27 Jan 2025 14:33:54 +0100 Subject: [PATCH 54/57] [HttpClient] Fix processing a NativeResponse after its client has been reset --- .../HttpClient/Response/NativeResponse.php | 12 ++++++------ .../HttpClient/Tests/HttpClientTestCase.php | 13 +++++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/HttpClient/Response/NativeResponse.php b/src/Symfony/Component/HttpClient/Response/NativeResponse.php index 77350700ad66b..9a5184ed6f6d4 100644 --- a/src/Symfony/Component/HttpClient/Response/NativeResponse.php +++ b/src/Symfony/Component/HttpClient/Response/NativeResponse.php @@ -79,7 +79,7 @@ public function __construct(NativeClientState $multi, $context, string $url, arr }; $this->canary = new Canary(static function () use ($multi, $id) { - if (null !== ($host = $multi->openHandles[$id][6] ?? null) && 0 >= --$multi->hosts[$host]) { + if (null !== ($host = $multi->openHandles[$id][6] ?? null) && isset($multi->hosts[$host]) && 0 >= --$multi->hosts[$host]) { unset($multi->hosts[$host]); } unset($multi->openHandles[$id], $multi->handlesActivity[$id]); @@ -123,7 +123,7 @@ private function open(): void throw new TransportException($msg); } - $this->logger?->info(sprintf('%s for "%s".', $msg, $url ?? $this->url)); + $this->logger?->info(\sprintf('%s for "%s".', $msg, $url ?? $this->url)); }); try { @@ -142,7 +142,7 @@ private function open(): void $this->info['request_header'] = $this->info['url']['path'].$this->info['url']['query']; } - $this->info['request_header'] = sprintf("> %s %s HTTP/%s \r\n", $context['http']['method'], $this->info['request_header'], $context['http']['protocol_version']); + $this->info['request_header'] = \sprintf("> %s %s HTTP/%s \r\n", $context['http']['method'], $this->info['request_header'], $context['http']['protocol_version']); $this->info['request_header'] .= implode("\r\n", $context['http']['header'])."\r\n\r\n"; if (\array_key_exists('peer_name', $context['ssl']) && null === $context['ssl']['peer_name']) { @@ -159,7 +159,7 @@ private function open(): void break; } - $this->logger?->info(sprintf('Redirecting: "%s %s"', $this->info['http_code'], $url ?? $this->url)); + $this->logger?->info(\sprintf('Redirecting: "%s %s"', $this->info['http_code'], $url ?? $this->url)); } } catch (\Throwable $e) { $this->close(); @@ -294,7 +294,7 @@ private static function perform(ClientState $multi, ?array &$responses = null): if (null === $e) { if (0 < $remaining) { - $e = new TransportException(sprintf('Transfer closed with %s bytes remaining to read.', $remaining)); + $e = new TransportException(\sprintf('Transfer closed with %s bytes remaining to read.', $remaining)); } elseif (-1 === $remaining && fwrite($buffer, '-') && '' !== stream_get_contents($buffer, -1, 0)) { $e = new TransportException('Transfer closed with outstanding data remaining from chunked response.'); } @@ -302,7 +302,7 @@ private static function perform(ClientState $multi, ?array &$responses = null): $multi->handlesActivity[$i][] = null; $multi->handlesActivity[$i][] = $e; - if (null !== ($host = $multi->openHandles[$i][6] ?? null) && 0 >= --$multi->hosts[$host]) { + if (null !== ($host = $multi->openHandles[$i][6] ?? null) && isset($multi->hosts[$host]) && 0 >= --$multi->hosts[$host]) { unset($multi->hosts[$host]); } unset($multi->openHandles[$i]); diff --git a/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php b/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php index 79763bc1019f3..3b83d82b68436 100644 --- a/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php +++ b/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php @@ -695,4 +695,17 @@ public function testPostToGetRedirect(int $status) $this->assertSame('GET', $body['REQUEST_METHOD']); $this->assertSame('/', $body['REQUEST_URI']); } + + public function testResponseCanBeProcessedAfterClientReset() + { + $client = $this->getHttpClient(__FUNCTION__); + $response = $client->request('GET', 'http://127.0.0.1:8057/timeout-body'); + $stream = $client->stream($response); + + $response->getStatusCode(); + $client->reset(); + $stream->current(); + + $this->addToAssertionCount(1); + } } From 4400674a192e0967d55e7c4b354288f66e9d18e0 Mon Sep 17 00:00:00 2001 From: Valmonzo Date: Fri, 15 Nov 2024 16:13:35 +0100 Subject: [PATCH 55/57] [Serializer] fix default context in Serializer --- .../Resources/config/serializer.php | 2 +- .../DependencyInjection/SerializerPass.php | 1 + .../Component/Serializer/Serializer.php | 8 +++--- .../SerializerPassTest.php | 7 +++-- .../Serializer/Tests/SerializerTest.php | 26 +++++++++++++++++++ 5 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php index 85231d0bf3ac0..c29258d527ec3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php @@ -60,7 +60,7 @@ $container->services() ->set('serializer', Serializer::class) - ->args([[], []]) + ->args([[], [], []]) ->alias(SerializerInterface::class, 'serializer') ->alias(NormalizerInterface::class, 'serializer') diff --git a/src/Symfony/Component/Serializer/DependencyInjection/SerializerPass.php b/src/Symfony/Component/Serializer/DependencyInjection/SerializerPass.php index d0b0deb48cf6d..c2959ecdac397 100644 --- a/src/Symfony/Component/Serializer/DependencyInjection/SerializerPass.php +++ b/src/Symfony/Component/Serializer/DependencyInjection/SerializerPass.php @@ -56,6 +56,7 @@ public function process(ContainerBuilder $container) } $container->getParameterBag()->remove('serializer.default_context'); + $container->getDefinition('serializer')->setArgument('$defaultContext', $defaultContext); } if ($container->getParameter('kernel.debug') && $container->hasDefinition('serializer.data_collector')) { diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index 7044c2f207be7..e17042097fe3c 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -84,10 +84,12 @@ class Serializer implements SerializerInterface, ContextAwareNormalizerInterface /** * @param array $normalizers * @param array $encoders + * @param array $defaultContext */ public function __construct( private array $normalizers = [], array $encoders = [], + private array $defaultContext = [], ) { foreach ($normalizers as $normalizer) { if ($normalizer instanceof SerializerAwareInterface) { @@ -163,12 +165,12 @@ public function normalize(mixed $data, ?string $format = null, array $context = return $data; } - if (\is_array($data) && !$data && ($context[self::EMPTY_ARRAY_AS_OBJECT] ?? false)) { + if (\is_array($data) && !$data && ($context[self::EMPTY_ARRAY_AS_OBJECT] ?? $this->defaultContext[self::EMPTY_ARRAY_AS_OBJECT] ?? false)) { return new \ArrayObject(); } if (is_iterable($data)) { - if ($data instanceof \Countable && ($context[AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS] ?? false) && !\count($data)) { + if ($data instanceof \Countable && ($context[AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS] ?? $this->defaultContext[AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS] ?? false) && !\count($data)) { return new \ArrayObject(); } @@ -220,7 +222,7 @@ public function denormalize(mixed $data, string $type, ?string $format = null, a throw new NotNormalizableValueException(sprintf('Could not denormalize object of type "%s", no supporting normalizer found.', $type)); } - if (isset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS])) { + if (isset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS]) || isset($this->defaultContext[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS])) { unset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS]); $context['not_normalizable_value_exceptions'] = []; $errors = &$context['not_normalizable_value_exceptions']; diff --git a/src/Symfony/Component/Serializer/Tests/DependencyInjection/SerializerPassTest.php b/src/Symfony/Component/Serializer/Tests/DependencyInjection/SerializerPassTest.php index eb77263f49fc9..b2f4fa7ad6a4c 100644 --- a/src/Symfony/Component/Serializer/Tests/DependencyInjection/SerializerPassTest.php +++ b/src/Symfony/Component/Serializer/Tests/DependencyInjection/SerializerPassTest.php @@ -77,9 +77,11 @@ public function testServicesAreOrderedAccordingToPriority() public function testBindSerializerDefaultContext() { + $context = ['enable_max_depth' => true]; + $container = new ContainerBuilder(); $container->setParameter('kernel.debug', false); - $container->register('serializer')->setArguments([null, null]); + $container->register('serializer')->setArguments([null, null, []]); $container->setParameter('serializer.default_context', ['enable_max_depth' => true]); $definition = $container->register('n1')->addTag('serializer.normalizer')->addTag('serializer.encoder'); @@ -87,7 +89,8 @@ public function testBindSerializerDefaultContext() $serializerPass->process($container); $bindings = $definition->getBindings(); - $this->assertEquals($bindings['array $defaultContext'], new BoundArgument(['enable_max_depth' => true], false)); + $this->assertEquals($bindings['array $defaultContext'], new BoundArgument($context, false)); + $this->assertEquals($context, $container->getDefinition('serializer')->getArgument('$defaultContext')); } public function testNormalizersAndEncodersAreDecoredAndOrderedWhenCollectingData() diff --git a/src/Symfony/Component/Serializer/Tests/SerializerTest.php b/src/Symfony/Component/Serializer/Tests/SerializerTest.php index 8f60ae1d44258..8a8a54e98178a 100644 --- a/src/Symfony/Component/Serializer/Tests/SerializerTest.php +++ b/src/Symfony/Component/Serializer/Tests/SerializerTest.php @@ -1652,6 +1652,32 @@ public function testPartialDenormalizationWithInvalidVariadicParameter() DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true, ]); } + + public function testEmptyArrayAsObjectDefaultContext() + { + $serializer = new Serializer( + defaultContext: [Serializer::EMPTY_ARRAY_AS_OBJECT => true], + ); + $this->assertEquals(new \ArrayObject(), $serializer->normalize([])); + } + + public function testPreserveEmptyObjectsAsDefaultContext() + { + $serializer = new Serializer( + defaultContext: [AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => true], + ); + $this->assertEquals(new \ArrayObject(), $serializer->normalize(new \ArrayIterator())); + } + + public function testCollectDenormalizationErrorsDefaultContext() + { + $data = ['variadic' => ['a random string']]; + $serializer = new Serializer([new UidNormalizer(), new ObjectNormalizer()], [], [DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true]); + + $this->expectException(PartialDenormalizationException::class); + + $serializer->denormalize($data, DummyWithVariadicParameter::class); + } } class Model From a195b1370e7e7d6457b8d78908bcedd4edf1e745 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 29 Jan 2025 08:33:34 +0100 Subject: [PATCH 56/57] Update CHANGELOG for 7.1.11 --- CHANGELOG-7.1.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/CHANGELOG-7.1.md b/CHANGELOG-7.1.md index f46dc88b01503..1aae56d47c5bf 100644 --- a/CHANGELOG-7.1.md +++ b/CHANGELOG-7.1.md @@ -7,6 +7,58 @@ in 7.1 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v7.1.0...v7.1.1 +* 7.1.11 (2025-01-29) + + * bug #58889 [Serializer] Handle default context in Serializer (Valmonzo) + * bug #59631 [HttpClient] Fix processing a NativeResponse after its client has been reset (Jean-Beru) + * bug #59590 [Security] Throw an explicit error when refreshing a token with a null user (alexandre-daubois) + * bug #59625 [FrameworkBundle] Add missing `not-compromised-password` entry in XSD (alexandre-daubois) + * bug #59610 [Mailer] Ensure TransportExceptionInterface populates stream debug data (bytestream) + * bug #59598 [Mime] Fix body validity check in `Email` when using `Message::setBody()` (alexandre-daubois) + * bug #59544 [AssetMapper] Fix CssCompiler matches url in comments (smnandre) + * bug #59575 [DoctrineBridge] Add support for doctrine/persistence 4 (greg0ire) + * bug #59399 [DomCrawler] Make `ChoiceFormField::isDisabled` return `true` for unchecked disabled checkboxes (MatTheCat) + * bug #59581 [Cache] Don't clear system caches on `cache:clear` (nicolas-grekas) + * bug #59579 [FrameworkBundle] Fix patching refs to the tmp warmup dir in files generated by optional cache warmers (nicolas-grekas) + * bug #57459 [PropertyInfo] convert legacy types to TypeInfo types if getType() is not implemented (xabbuh) + * bug #59525 [HtmlSanitizer] Fix access to undefined keys in UrlSanitizer (Antoine Beyet) + * bug #59538 [VarDumper] fix dumped markup (xabbuh) + * bug #59508 [Messenger] [AMQP] Improve AMQP connection issues (AurelienPillevesse) + * bug #59501 [Serializer] [ObjectNormalizer] Filter int when using FILTER_BOOL (DjordyKoert) + * bug #59515 [FrameworkBundle] Fix wiring ConsoleProfilerListener (nicolas-grekas) + * bug #59136 [DependencyInjection] Reset env vars with `kernel.reset` (faizanakram99) + * bug #59486 [Validator] Update sr_Cyrl 120:This value is not a valid slug. (kaznovac) + * bug #59403 [FrameworkBundle][HttpFoundation] Reset Request's formats using the service resetter (nicolas-grekas) + * bug #59404 [Mailer] Fix SMTP stream EOF handling on Windows by using feof() (skmedix) + * bug #59390 [VarDumper] Fix blank strings display (MatTheCat) + * bug #59446 [Routing] Fix configuring a single route's hosts (MatTheCat) + * bug #58901 [HttpClient] Ignore RuntimeExceptions thrown when rewinding the PSR-7 created in HttplugWaitLoop::createPsr7Response (KurtThiemann) + * bug #59046 [HttpClient] Fix Undefined array key `connection` (PhilETaylor) + * bug #59055 [HttpFoundation] Fixed `IpUtils::anonymize` exception when using IPv6 link-local addresses with RFC4007 scoping (jbtronics) + * bug #59256 [Mailer] Fix Sendmail memory leak (rch7) + * bug #59375 [RemoteEvent][Webhook] fix SendgridPayloadConverter category support (ericabouaf) + * bug #59367 [PropertyInfo] Make sure that SerializerExtractor returns null for invalid class metadata (wuchen90) + * bug #59376 [RemoteEvent][Webhook] Fix `SendgridRequestParser` and `SendgridPayloadConverter` (ericabouaf) + * bug #59381 [Yaml] fix inline notation with inline comment (alexpott) + * bug #59352 [Messenger] Fix `TransportMessageIdStamp` not always added (HypeMC) + * bug #59185 [DoctrineBridge] Fix compatibility to Doctrine persistence 2.5 in Doctrine Bridge 6.4 to avoid Projects stuck on 6.3 (alexander-schranz) + * bug #59245 [PropertyInfo] Fix add missing composer conflict (mtarld) + * bug #59292 [WebProfilerBundle] Fix event delegation on links inside toggles (MatTheCat) + * bug #59362 [Doctrine][Messenger] Prevents multiple TransportMessageIdStamp being stored in envelope (rtreffler) + * bug #59323 [Serializer] Fix exception thrown by `YamlEncoder` (VincentLanglet) + * bug #59293 [AssetMapper] Fix JavaScript compiler creates self-referencing imports (smnandre) + * bug #59349 [Yaml] reject inline notations followed by invalid content (xabbuh) + * bug #59363 [VarDumper] Fix displaying closure's "this" from anonymous classes (nicolas-grekas) + * bug #59364 [ErrorHandler] Don't trigger "internal" deprecations for anonymous LazyClosure instances (nicolas-grekas) + * bug #59221 [PropertyAccess] Fix compatibility with PHP 8.4 asymmetric visibility (Florian-Merle) + * bug #59357 [HttpKernel] Don't override existing `LoggerInterface` autowiring alias in `LoggerPass` (nicolas-grekas) + * bug #59347 [Security] Fix triggering session tracking from ContextListener (nicolas-grekas) + * bug #59188 [HttpClient] Fix `reset()` not called on decorated clients (HypeMC) + * bug #59339 [SecurityBundle] Remove outdated guard from security xsd schema (chalasr) + * bug #59343 [Security] Adjust parameter order in exception message (Link1515) + * bug #59312 [Yaml] Fix parsing of unquoted strings in Parser::lexUnquotedString() to ignore spaces (Link1515) + * bug #59334 [ErrorHandler] [A11y] Simple proposal for color updates on error stack traces against colorblindness (DocFX) + * 7.1.10 (2024-12-31) * bug #59304 [PropertyInfo] Remove ``@internal`` from `PropertyReadInfo` and `PropertyWriteInfo` (Dario Guarracino) From 707560517a3cf0d5b6a3e5d0bf32f77ae5d1d592 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 29 Jan 2025 08:34:05 +0100 Subject: [PATCH 57/57] Update VERSION for 7.1.11 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 901d12bf3e838..87e663cc9d03a 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -73,12 +73,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '7.1.11-DEV'; + public const VERSION = '7.1.11'; public const VERSION_ID = 70111; public const MAJOR_VERSION = 7; public const MINOR_VERSION = 1; public const RELEASE_VERSION = 11; - public const EXTRA_VERSION = 'DEV'; + public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '01/2025'; public const END_OF_LIFE = '01/2025';