From 4d91dfc4501c0b2e21caa0ea4eb8a8dacd618872 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 16 Nov 2025 11:40:25 +0100 Subject: [PATCH 01/11] Bump version to 8.1 --- src/Symfony/Component/HttpKernel/Kernel.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 765f2c731f1d2..24b039994a8c6 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -71,15 +71,15 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '8.0.0-DEV'; - public const VERSION_ID = 80000; + public const VERSION = '8.1.0-DEV'; + public const VERSION_ID = 80100; public const MAJOR_VERSION = 8; - public const MINOR_VERSION = 0; + public const MINOR_VERSION = 1; public const RELEASE_VERSION = 0; public const EXTRA_VERSION = 'DEV'; - public const END_OF_MAINTENANCE = '07/2026'; - public const END_OF_LIFE = '07/2026'; + public const END_OF_MAINTENANCE = '01/2027'; + public const END_OF_LIFE = '01/2027'; public function __construct( protected string $environment, From 69384666ff8e46bdf35bce37ccf026deaeba8891 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 6 Nov 2025 08:56:45 +0100 Subject: [PATCH 02/11] add missing Clear-Site-Data directives --- src/Symfony/Bundle/SecurityBundle/CHANGELOG.md | 5 +++++ .../SecurityBundle/DependencyInjection/MainConfiguration.php | 2 +- src/Symfony/Component/Security/Http/CHANGELOG.md | 5 +++++ .../Http/EventListener/ClearSiteDataLogoutListener.php | 2 +- .../Tests/EventListener/ClearSiteDataLogoutListenerTest.php | 1 + 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 73ba9206d744a..a92b1800eb20f 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +8.1 +--- + + * Add support for the `clientHints`, `prefetchCache`, and `prerenderCache` `ClearSite-Data` directives + 8.0 --- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index 45476a176f69b..a8e5a6a317429 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -236,7 +236,7 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto ->beforeNormalization()->ifString()->then(static fn ($v) => $v ? array_map('trim', explode(',', $v)) : [])->end() ->enumPrototype() ->values([ - '*', 'cache', 'cookies', 'storage', 'executionContexts', + '*', 'cache', 'cookies', 'storage', 'clientHints', 'executionContexts', 'prefetchCache', 'prerenderCache', ]) ->end() ->end() diff --git a/src/Symfony/Component/Security/Http/CHANGELOG.md b/src/Symfony/Component/Security/Http/CHANGELOG.md index 7ed486f313342..1b3b9835c9bdd 100644 --- a/src/Symfony/Component/Security/Http/CHANGELOG.md +++ b/src/Symfony/Component/Security/Http/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +8.1 +--- + + * Add support for the `clientHints`, `prefetchCache`, and `prerenderCache` `ClearSite-Data` directives + 8.0 --- diff --git a/src/Symfony/Component/Security/Http/EventListener/ClearSiteDataLogoutListener.php b/src/Symfony/Component/Security/Http/EventListener/ClearSiteDataLogoutListener.php index 77ca07a642835..0c72a214bc435 100644 --- a/src/Symfony/Component/Security/Http/EventListener/ClearSiteDataLogoutListener.php +++ b/src/Symfony/Component/Security/Http/EventListener/ClearSiteDataLogoutListener.php @@ -27,7 +27,7 @@ class ClearSiteDataLogoutListener implements EventSubscriberInterface /** * @param string[] $cookieValue The value for the Clear-Site-Data header. - * Can be '*' or a subset of 'cache', 'cookies', 'storage', 'executionContexts'. + * Can be '*' or a subset of 'cache', 'cookies', 'storage', 'clientHints', 'executionContexts', 'prefetchCache', 'prerenderCache'. */ public function __construct(private readonly array $cookieValue) { diff --git a/src/Symfony/Component/Security/Http/Tests/EventListener/ClearSiteDataLogoutListenerTest.php b/src/Symfony/Component/Security/Http/Tests/EventListener/ClearSiteDataLogoutListenerTest.php index 42ceff76444da..9cf21aa36ae26 100644 --- a/src/Symfony/Component/Security/Http/Tests/EventListener/ClearSiteDataLogoutListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/EventListener/ClearSiteDataLogoutListenerTest.php @@ -43,5 +43,6 @@ public static function provideClearSiteDataConfig(): iterable { yield [['*'], '"*"']; yield [['cache', 'cookies', 'storage', 'executionContexts'], '"cache", "cookies", "storage", "executionContexts"']; + yield [['clientHints', 'executionContexts', 'prefetchCache', 'prerenderCache'], '"clientHints", "executionContexts", "prefetchCache", "prerenderCache"']; } } From b2e6fe2ca2cbde9250dd1b4d62d22f937a2be690 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Delhommeau Date: Thu, 13 Nov 2025 17:21:44 +0100 Subject: [PATCH 03/11] feat: add support to ipPoolId for infobip mailer transport --- .../Component/Mailer/Bridge/Infobip/CHANGELOG.md | 5 +++++ .../Component/Mailer/Bridge/Infobip/README.md | 3 ++- .../Tests/Transport/InfobipApiTransportTest.php | 13 +++++++++++-- .../Infobip/Transport/InfobipApiTransport.php | 1 + 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Mailer/Bridge/Infobip/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/Infobip/CHANGELOG.md index 403fbe93c4bd8..aeecb8624d328 100644 --- a/src/Symfony/Component/Mailer/Bridge/Infobip/CHANGELOG.md +++ b/src/Symfony/Component/Mailer/Bridge/Infobip/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +8.1 +--- + + * Add support of `ipPoolId` option + 7.2 --- diff --git a/src/Symfony/Component/Mailer/Bridge/Infobip/README.md b/src/Symfony/Component/Mailer/Bridge/Infobip/README.md index b260c10a74fa2..edfb5e2bd3a8e 100644 --- a/src/Symfony/Component/Mailer/Bridge/Infobip/README.md +++ b/src/Symfony/Component/Mailer/Bridge/Infobip/README.md @@ -25,8 +25,9 @@ This transport supports the following custom headers: | `X-Infobip-MessageId` | string | The ID that uniquely identifies the message sent to a recipient. | | `X-Infobip-Track` | boolean | Enable or disable open and click tracking. | | `X-Infobip-TrackingUrl` | string | The URL on your callback server on which the open and click notifications will be sent. | -| `X-Infobip-TrackClicks` | boolean | Enable or disable track click feature.. | +| `X-Infobip-TrackClicks` | boolean | Enable or disable track click feature. | | `X-Infobip-TrackOpens` | boolean | Enable or disable open click feature. | +| `X-Infobip-IpPoolId` | string | The ID of the dedicated IP pool that will be used to deliver the message. | Resources --------- diff --git a/src/Symfony/Component/Mailer/Bridge/Infobip/Tests/Transport/InfobipApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Infobip/Tests/Transport/InfobipApiTransportTest.php index aa417558c6a53..1cd48855c92a1 100644 --- a/src/Symfony/Component/Mailer/Bridge/Infobip/Tests/Transport/InfobipApiTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Infobip/Tests/Transport/InfobipApiTransportTest.php @@ -252,7 +252,8 @@ public function testSendEmailWithHeadersShouldCalledInfobipWithTheRightParameter ->addTextHeader('X-Infobip-Track', 'false') ->addTextHeader('X-Infobip-TrackingUrl', 'https://bar.foo') ->addTextHeader('X-Infobip-TrackClicks', 'true') - ->addTextHeader('X-Infobip-TrackOpens', 'true'); + ->addTextHeader('X-Infobip-TrackOpens', 'true') + ->addTextHeader('X-Infobip-IpPoolId', 'pool-123'); $this->transport->send($email); @@ -308,6 +309,12 @@ public function testSendEmailWithHeadersShouldCalledInfobipWithTheRightParameter Content-Disposition: form-data; name="trackOpens" true + --%s + Content-Type: text/plain; charset=utf-8 + Content-Transfer-Encoding: 8bit + Content-Disposition: form-data; name="ipPoolId" + + pool-123 --%s-- TXT, $options['body'] @@ -441,7 +448,8 @@ public function testSendEmailWithHeadersWithSuccess() ->addTextHeader('X-Infobip-Track', 'false') ->addTextHeader('X-Infobip-TrackingUrl', 'https://bar.foo') ->addTextHeader('X-Infobip-TrackClicks', 'true') - ->addTextHeader('X-Infobip-TrackOpens', 'true'); + ->addTextHeader('X-Infobip-TrackOpens', 'true') + ->addTextHeader('X-Infobip-IpPoolId', 'pool-123'); $sentMessage = $this->transport->send($email); @@ -457,6 +465,7 @@ public function testSendEmailWithHeadersWithSuccess() X-Infobip-TrackingUrl: https://bar.foo X-Infobip-TrackClicks: true X-Infobip-TrackOpens: true + X-Infobip-IpPoolId: pool-123 %a TXT, $sentMessage->toString() diff --git a/src/Symfony/Component/Mailer/Bridge/Infobip/Transport/InfobipApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Infobip/Transport/InfobipApiTransport.php index b2bfcc6961098..98a64f4a65f97 100644 --- a/src/Symfony/Component/Mailer/Bridge/Infobip/Transport/InfobipApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Infobip/Transport/InfobipApiTransport.php @@ -42,6 +42,7 @@ final class InfobipApiTransport extends AbstractApiTransport 'X-Infobip-TrackingUrl' => 'trackingUrl', 'X-Infobip-TrackClicks' => 'trackClicks', 'X-Infobip-TrackOpens' => 'trackOpens', + 'X-Infobip-IpPoolId' => 'ipPoolId', ]; public function __construct( From 87f5f9723f669b28be886b125b22f01cded96fe4 Mon Sep 17 00:00:00 2001 From: Mickael GOETZ Date: Wed, 7 May 2025 16:22:56 +0200 Subject: [PATCH 04/11] [Mailer][SendGrid] add support for scheduling delivery via `send_at` API parameter --- .../Component/Mailer/Bridge/Sendgrid/CHANGELOG.md | 5 +++++ .../Component/Mailer/Bridge/Sendgrid/README.md | 14 ++++++++++++++ .../Tests/Transport/SendgridApiTransportTest.php | 14 ++++++++++++++ .../Sendgrid/Transport/SendgridApiTransport.php | 12 +++++++++--- 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/Sendgrid/CHANGELOG.md index 9bcfdb33600fd..7a025a0c6b198 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/CHANGELOG.md +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +8.1 +--- + + * Add support for scheduling delivery with the `send_at` API parameter via a `Send-At` date-header + 7.4 --- diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/README.md b/src/Symfony/Component/Mailer/Bridge/Sendgrid/README.md index 33ee90ef65b3b..bf3f1ece7f81d 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/README.md +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/README.md @@ -60,6 +60,20 @@ where: - `GROUP_ID` is your Sendgrid suppression group ID - `GROUPS_TO_DISPLAY_ID` is an array of the Sendgrid suppression group IDs presented to the user +Scheduling +---------- + +When using the **API transport** (with a `sendgrid+api` DSN), you can schedule +your emails by providing a `\DateTimeInterface` object in a +`Symfony\Component\Mime\Header\DateHeader` named `Send-At`. + +```php +$email = new \Symfony\Component\Mime\Email(); +$email->getHeaders()->addDateHeader('Send-At', new \DateTimeImmutable('+3 hours')); +``` +It will be mapped to the `send_at` parameter of the `[POST] /mail/send` +[API endpoint](https://www.twilio.com/docs/sendgrid/api-reference/mail-send/mail-send#request-body) + Resources --------- diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php index 3f3814df7ba90..b5a624579f31d 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php @@ -313,4 +313,18 @@ public function testWithSuppressionGroup() $this->assertSame([1, 2, 3, 4, 5], $payload['asm']['groups_to_display']); } + + public function testSendAtHeader() + { + $email = new Email(); + $email->getHeaders()->addDateHeader('Send-At', new \DateTime('2025-05-07 16:00:00', new \DateTimeZone('Europe/Paris'))); + $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); + + $transport = new SendgridApiTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(SendgridApiTransport::class, 'getPayload'); + $payload = $method->invoke($transport, $email, $envelope); + + $this->assertArrayHasKey('send_at', $payload); + $this->assertSame(1746626400, $payload['send_at']); + } } diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php index 5492d026870fc..39028b2d53c89 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php @@ -23,6 +23,7 @@ use Symfony\Component\Mailer\Transport\AbstractApiTransport; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Header\DateHeader; use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -126,7 +127,12 @@ private function getPayload(Email $email, Envelope $envelope): array continue; } - if ($header instanceof TagHeader) { + if ('send-at' === $name) { + if (!$header instanceof DateHeader) { + throw new TransportException(\sprintf('The "Send-At" header must be a "%s" instance.', DateHeader::class)); + } + $payload['send_at'] = $header->getDateTime()->getTimestamp(); + } elseif ($header instanceof TagHeader) { if (10 === \count($categories)) { throw new TransportException(\sprintf('Too many "%s" instances present in the email headers. Sendgrid does not accept more than 10 categories on an email.', TagHeader::class)); } @@ -145,11 +151,11 @@ private function getPayload(Email $email, Envelope $envelope): array } } - if (\count($categories) > 0) { + if ($categories) { $payload['categories'] = $categories; } - if (\count($customArguments) > 0) { + if ($customArguments) { $personalization['custom_args'] = $customArguments; } From 896680d29732090e61d0ea47ae7c95bd0bbebd10 Mon Sep 17 00:00:00 2001 From: Younes ENNAJI Date: Sat, 22 Nov 2025 23:59:50 +0100 Subject: [PATCH 05/11] [DependencyInjection] Deprecate invalid options when using "from_callable" --- UPGRADE-8.1.md | 7 ++++++ .../DependencyInjection/CHANGELOG.md | 5 ++++ .../Loader/YamlFileLoader.php | 4 ++++ .../Tests/Loader/YamlFileLoaderTest.php | 24 +++++++++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 UPGRADE-8.1.md diff --git a/UPGRADE-8.1.md b/UPGRADE-8.1.md new file mode 100644 index 0000000000000..b978dd0690a1f --- /dev/null +++ b/UPGRADE-8.1.md @@ -0,0 +1,7 @@ +UPGRADE FROM 8.0 to 8.1 +======================= + +DependencyInjection +------------------- + + * Deprecate configuring options `alias`, `parent`, `synthetic`, `file`, `arguments`, `properties`, `configurator` or `calls` when using `from_callable` diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 1bb32f57a7781..8df4831011978 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +8.1 +--- + + * Deprecate configuring options `alias`, `parent`, `synthetic`, `file`, `arguments`, `properties`, `configurator` or `calls` when using `from_callable` + 8.0 --- diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index a0572b3a86091..785740df6db87 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -412,6 +412,10 @@ private function parseDefinition(string $id, array|string|null $service, string if (isset($service['factory'])) { throw new InvalidArgumentException(\sprintf('The configuration key "%s" is unsupported for the service "%s" when using "from_callable" in "%s".', $key, $id, $file)); } + + if (isset($service[$key])) { + trigger_deprecation('symfony/dependency-injection', '8.1', 'Configuring the "%s" key for the service "%s" when using "from_callable" is deprecated and will throw an "InvalidArgumentException" in 9.0.', $key, $id); + } } if ('Closure' !== $service['class'] ??= 'Closure') { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 35527e9bc34dd..f287cd3d04449 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Loader; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; use Symfony\Component\Config\Exception\LoaderLoadException; @@ -1217,4 +1218,27 @@ public function testStaticConstructor() $definition = $container->getDefinition('static_constructor'); $this->assertEquals((new Definition('stdClass'))->setFactory([null, 'create']), $definition); } + + #[IgnoreDeprecations] + #[DataProvider('provideForbiddenKeys')] + public function testFromCallableTriggersDeprecationOnForbiddenKeys(string $key, mixed $value) + { + $this->expectUserDeprecationMessage(\sprintf('Since symfony/dependency-injection 8.1: Configuring the "%s" key for the service "my_service" when using "from_callable" is deprecated and will throw an "InvalidArgumentException" in 9.0.', $key)); + + $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator()); + + $reflectionMethod = new \ReflectionMethod($loader, 'parseDefinition'); + $reflectionMethod->invoke($loader, 'my_service', ['from_callable' => 'strlen', $key => $value], 'config/services.yaml', []); + } + + public static function provideForbiddenKeys(): iterable + { + yield 'parent' => ['parent', 'App\\SomeParent']; + yield 'synthetic' => ['synthetic', true]; + yield 'file' => ['file', 'some_file.php']; + yield 'arguments' => ['arguments', []]; + yield 'properties' => ['properties', ['foo' => 'bar']]; + yield 'configurator' => ['configurator', 'some_configurator']; + yield 'calls' => ['calls', [['method' => 'setFoo', 'arguments' => ['bar']]]]; + } } From 0af0693f4e8a5729b37466edae504b3153871977 Mon Sep 17 00:00:00 2001 From: Mdsujansarkar Date: Fri, 28 Nov 2025 01:38:54 +0600 Subject: [PATCH 06/11] Fix typos in documentation --- src/Symfony/Contracts/Translation/Test/TranslatorTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Contracts/Translation/Test/TranslatorTest.php b/src/Symfony/Contracts/Translation/Test/TranslatorTest.php index 5342f5b82c341..c86efe17d1bb5 100644 --- a/src/Symfony/Contracts/Translation/Test/TranslatorTest.php +++ b/src/Symfony/Contracts/Translation/Test/TranslatorTest.php @@ -27,7 +27,7 @@ * * As mentioned by chx http://drupal.org/node/1273968 we can cover all by testing number from 0 to 199 * - * The goal to cover all languages is to far fetched so this test case is smaller. + * The goal to cover all languages is too far fetched so this test case is smaller. * * @author Clemens Tolboom clemens@build2be.nl */ @@ -349,7 +349,7 @@ public static function successLangcodes(): array * This both depends on a complete list trying to add above as understanding * the plural rules of the current failing languages. * - * @return array with nplural together with langcodes + * @return array With nplural together with langcodes */ public static function failingLangcodes(): array { From 71b4c7b9ce13bc7e7372af9288895c61f221e4ff Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 29 Nov 2025 10:41:47 +0100 Subject: [PATCH 07/11] add legacy group to test testing a deprecated feature We need this group in the future to properly skip the test in the high deps job once we start the development of Symfony 8.4. --- .../DependencyInjection/Tests/Loader/YamlFileLoaderTest.php | 2 ++ .../Component/Routing/Tests/Generator/UrlGeneratorTest.php | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index f287cd3d04449..9e9f3b911e4c9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Loader; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; @@ -1220,6 +1221,7 @@ public function testStaticConstructor() } #[IgnoreDeprecations] + #[Group('legacy')] #[DataProvider('provideForbiddenKeys')] public function testFromCallableTriggersDeprecationOnForbiddenKeys(string $key, mixed $value) { diff --git a/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php b/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php index d7dd9bb6b885d..588632a332476 100644 --- a/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php +++ b/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Routing\Tests\Generator; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; From d97d09cb1b7583c5a370046d0e311fd48f8ec452 Mon Sep 17 00:00:00 2001 From: Mathias Arlaud Date: Fri, 6 Jun 2025 10:53:37 +0200 Subject: [PATCH 08/11] [FrameworkBundle] Deprecate setting `collect_serializer_data` --- UPGRADE-8.1.md | 5 +++++ src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 5 +++++ .../FrameworkBundle/DependencyInjection/Configuration.php | 6 +++++- .../Tests/DependencyInjection/Fixtures/php/profiler.php | 1 - .../Tests/DependencyInjection/Fixtures/yml/profiler.yml | 1 - .../Tests/Functional/app/config/framework.yml | 2 -- .../Tests/Functional/app/FirewallEntryPoint/config.yml | 1 - .../Tests/Functional/app/config/framework.yml | 1 - .../Tests/Functional/WebProfilerBundleKernel.php | 2 +- 9 files changed, 16 insertions(+), 8 deletions(-) diff --git a/UPGRADE-8.1.md b/UPGRADE-8.1.md index b978dd0690a1f..4aefd06c644b8 100644 --- a/UPGRADE-8.1.md +++ b/UPGRADE-8.1.md @@ -5,3 +5,8 @@ DependencyInjection ------------------- * Deprecate configuring options `alias`, `parent`, `synthetic`, `file`, `arguments`, `properties`, `configurator` or `calls` when using `from_callable` + +FrameworkBundle +--------------- + + * Deprecate setting the `framework.profiler.collect_serializer_data` config option diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index be82a64bda2a2..914ff0d1c051b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +8.1 +--- + + * Deprecate setting the `framework.profiler.collect_serializer_data` config option + 8.0 --- diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 02f5f5bf7dce1..a01528059f1b9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -361,7 +361,11 @@ private function addProfilerSection(ArrayNodeDefinition $rootNode): void ->booleanNode('only_exceptions')->defaultFalse()->end() ->booleanNode('only_main_requests')->defaultFalse()->end() ->scalarNode('dsn')->defaultValue('file:%kernel.cache_dir%/profiler')->end() - ->enumNode('collect_serializer_data')->values([true])->defaultTrue()->end() // to be @deprecated in Symfony 8.1 + ->enumNode('collect_serializer_data') + ->values([true]) + ->defaultTrue() + ->setDeprecated('symfony/framework-bundle', '8.1', 'Setting the "%path%.%node%" configuration option is deprecated. It will be removed in version 9.0.') + ->end() ->end() ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/profiler.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/profiler.php index 56cc6a1723fa4..60d0cdf8b54e2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/profiler.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/profiler.php @@ -3,7 +3,6 @@ $container->loadFromExtension('framework', [ 'profiler' => [ 'enabled' => true, - 'collect_serializer_data' => true, ], 'serializer' => [ 'enabled' => true, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/profiler.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/profiler.yml index 8cc59ab8f46fe..1cfe686b1eb19 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/profiler.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/profiler.yml @@ -1,6 +1,5 @@ framework: profiler: enabled: true - collect_serializer_data: true serializer: enabled: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml index 7c0a1b2bcf3cc..17e9cba676fe6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml @@ -13,8 +13,6 @@ framework: storage_factory_id: session.storage.factory.mock_file cookie_secure: auto cookie_samesite: lax - profiler: - collect_serializer_data: true services: logger: { class: Psr\Log\NullLogger } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/config.yml index 0601c253a5c1c..14d47a95bb9be 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/config.yml @@ -14,7 +14,6 @@ framework: cookie_samesite: lax profiler: only_exceptions: false - collect_serializer_data: true services: logger: { class: Psr\Log\NullLogger } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml index 1b16f1f027444..38ea5de3c2659 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml @@ -15,7 +15,6 @@ framework: cookie_samesite: lax profiler: only_exceptions: false - collect_serializer_data: true services: logger: { class: Psr\Log\NullLogger } diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Functional/WebProfilerBundleKernel.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Functional/WebProfilerBundleKernel.php index 556befe105409..4915fdb176248 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Functional/WebProfilerBundleKernel.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Functional/WebProfilerBundleKernel.php @@ -52,7 +52,7 @@ protected function configureContainer(ContainerBuilder $container, LoaderInterfa { $config = [ 'secret' => 'foo-secret', - 'profiler' => ['only_exceptions' => false, 'collect_serializer_data' => true], + 'profiler' => ['only_exceptions' => false], 'session' => ['handler_id' => null, 'storage_factory_id' => 'session.storage.factory.mock_file', 'cookie-secure' => 'auto', 'cookie-samesite' => 'lax'], 'router' => ['utf8' => true], ]; From 624cdfe29bbcfebd2f40ea5244d825a423363346 Mon Sep 17 00:00:00 2001 From: Mohammad Eftekhari Date: Sat, 29 Nov 2025 13:25:33 +0100 Subject: [PATCH 09/11] [Messenger] Use clock in `DelayStamp` and `RedeliveryStamp` instead of native time classes and methods --- src/Symfony/Component/Messenger/Stamp/DelayStamp.php | 6 ++++-- src/Symfony/Component/Messenger/Stamp/RedeliveryStamp.php | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Messenger/Stamp/DelayStamp.php b/src/Symfony/Component/Messenger/Stamp/DelayStamp.php index f75a2f85e40c7..1164007d15f3a 100644 --- a/src/Symfony/Component/Messenger/Stamp/DelayStamp.php +++ b/src/Symfony/Component/Messenger/Stamp/DelayStamp.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Messenger\Stamp; +use Symfony\Component\Clock\Clock; + /** * Apply this stamp to delay delivery of your message on a transport. */ @@ -31,7 +33,7 @@ public function getDelay(): int public static function delayFor(\DateInterval $interval): self { - $now = new \DateTimeImmutable('now', new \DateTimeZone('UTC')); + $now = Clock::get()->withTimeZone(new \DateTimeZone('UTC'))->now(); $end = $now->add($interval); return new self(($end->getTimestamp() - $now->getTimestamp()) * 1000); @@ -39,6 +41,6 @@ public static function delayFor(\DateInterval $interval): self public static function delayUntil(\DateTimeInterface $dateTime): self { - return new self(($dateTime->getTimestamp() - time()) * 1000); + return new self(($dateTime->getTimestamp() - Clock::get()->now()->getTimestamp()) * 1000); } } diff --git a/src/Symfony/Component/Messenger/Stamp/RedeliveryStamp.php b/src/Symfony/Component/Messenger/Stamp/RedeliveryStamp.php index 08077e73cde5b..bd5963c3b1a5c 100644 --- a/src/Symfony/Component/Messenger/Stamp/RedeliveryStamp.php +++ b/src/Symfony/Component/Messenger/Stamp/RedeliveryStamp.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Messenger\Stamp; +use Symfony\Component\Clock\Clock; use Symfony\Component\Messenger\Envelope; /** @@ -24,7 +25,7 @@ public function __construct( private int $retryCount, ?\DateTimeInterface $redeliveredAt = null, ) { - $this->redeliveredAt = $redeliveredAt ?? new \DateTimeImmutable(); + $this->redeliveredAt = $redeliveredAt ?? Clock::get()->now(); } public static function getRetryCountFromEnvelope(Envelope $envelope): int From 4613ccfda9920000e14c027c4f651a374c7cdcd9 Mon Sep 17 00:00:00 2001 From: Nayte Date: Sun, 30 Nov 2025 01:32:33 +0100 Subject: [PATCH 10/11] [Form] Add reset button in NavigatorFlowType ResetFlowType is now conditionally rendered when displaying NavigatorFlowType. - Added an option 'with_reset' - option is false by default to respect BC - added Test class, - modified previous tests that rendered NavigatorFlowType and ResetFlowType --- src/Symfony/Component/Form/CHANGELOG.md | 5 ++ .../Form/Flow/Type/NavigatorFlowType.php | 9 ++++ .../Fixtures/Flow/LastStepSkippedType.php | 4 +- .../Fixtures/Flow/UserSignUpNavigatorType.php | 9 +++- .../Form/Tests/Flow/FormFlowTest.php | 3 +- .../Tests/Flow/Type/NavigatorFlowTypeTest.php | 49 +++++++++++++++++++ 6 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 src/Symfony/Component/Form/Tests/Flow/Type/NavigatorFlowTypeTest.php diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 7ac95ccc8db1e..238f7ca83e9ea 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +8.1 +--- + + * Add `ResetFlowType` button in `NavigatorFlowType` that you can display with `with_reset` option + 8.0 --- diff --git a/src/Symfony/Component/Form/Flow/Type/NavigatorFlowType.php b/src/Symfony/Component/Form/Flow/Type/NavigatorFlowType.php index 7dab23c35a4e0..3510c44da2ec6 100644 --- a/src/Symfony/Component/Form/Flow/Type/NavigatorFlowType.php +++ b/src/Symfony/Component/Form/Flow/Type/NavigatorFlowType.php @@ -27,6 +27,10 @@ public function buildForm(FormBuilderInterface $builder, array $options): void $builder->add('previous', PreviousFlowType::class); $builder->add('next', NextFlowType::class); $builder->add('finish', FinishFlowType::class); + + if ($options['with_reset']) { + $builder->add('reset', ResetFlowType::class); + } } public function configureOptions(OptionsResolver $resolver): void @@ -36,5 +40,10 @@ public function configureOptions(OptionsResolver $resolver): void 'mapped' => false, 'priority' => -100, ]); + + $resolver->define('with_reset') + ->allowedTypes('bool') + ->default(false) + ->info('Whether to add a reset button to restart the flow from the first step'); } } diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Flow/LastStepSkippedType.php b/src/Symfony/Component/Form/Tests/Fixtures/Flow/LastStepSkippedType.php index a4194e755bc4f..eb7e786cfff77 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Flow/LastStepSkippedType.php +++ b/src/Symfony/Component/Form/Tests/Fixtures/Flow/LastStepSkippedType.php @@ -24,7 +24,9 @@ public function buildFormFlow(FormFlowBuilderInterface $builder, array $options) $builder->addStep('step1', TextType::class); $builder->addStep('step2', skip: static fn () => true); - $builder->add('navigator', NavigatorFlowType::class); + $builder->add('navigator', NavigatorFlowType::class, [ + 'with_reset' => true, + ]); } public function configureOptions(OptionsResolver $resolver): void diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Flow/UserSignUpNavigatorType.php b/src/Symfony/Component/Form/Tests/Fixtures/Flow/UserSignUpNavigatorType.php index ed1bc31d96590..2341423947992 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Flow/UserSignUpNavigatorType.php +++ b/src/Symfony/Component/Form/Tests/Fixtures/Flow/UserSignUpNavigatorType.php @@ -14,8 +14,8 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Flow\Type\NavigatorFlowType; use Symfony\Component\Form\Flow\Type\NextFlowType; -use Symfony\Component\Form\Flow\Type\ResetFlowType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; class UserSignUpNavigatorType extends AbstractType { @@ -25,8 +25,13 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'clear_submission' => true, 'include_if' => ['professional'], ]); + } - $builder->add('reset', ResetFlowType::class); + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'with_reset' => true, + ]); } public function getParent(): string diff --git a/src/Symfony/Component/Form/Tests/Flow/FormFlowTest.php b/src/Symfony/Component/Form/Tests/Flow/FormFlowTest.php index 9d21b8d034d02..97d3c253e0af5 100644 --- a/src/Symfony/Component/Form/Tests/Flow/FormFlowTest.php +++ b/src/Symfony/Component/Form/Tests/Flow/FormFlowTest.php @@ -945,8 +945,9 @@ public function testLastStepSkippedMarkFlowAsFinished() self::assertTrue($flow->has('navigator')); $navigatorForm = $flow->get('navigator'); - self::assertCount(1, $navigatorForm->all()); + self::assertCount(2, $navigatorForm->all()); self::assertTrue($navigatorForm->has('next')); + self::assertTrue($navigatorForm->has('reset')); $flow->submit([ 'step1' => 'foo', diff --git a/src/Symfony/Component/Form/Tests/Flow/Type/NavigatorFlowTypeTest.php b/src/Symfony/Component/Form/Tests/Flow/Type/NavigatorFlowTypeTest.php new file mode 100644 index 0000000000000..6d919b8ebeb75 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Flow/Type/NavigatorFlowTypeTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Flow\Type; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Form\Flow\Type\NavigatorFlowType; +use Symfony\Component\Form\FormFactoryInterface; +use Symfony\Component\Form\Forms; + +class NavigatorFlowTypeTest extends TestCase +{ + private FormFactoryInterface $factory; + + protected function setUp(): void + { + $this->factory = Forms::createFormFactoryBuilder()->getFormFactory(); + } + + public function testDefaultOptionsDoNotIncludeReset() + { + $form = $this->factory->create(NavigatorFlowType::class); + + self::assertTrue($form->has('previous')); + self::assertTrue($form->has('next')); + self::assertTrue($form->has('finish')); + self::assertFalse($form->has('reset')); + } + + public function testWithResetOptionAddsResetButton() + { + $form = $this->factory->create(NavigatorFlowType::class, null, [ + 'with_reset' => true, + ]); + + self::assertTrue($form->has('previous')); + self::assertTrue($form->has('next')); + self::assertTrue($form->has('finish')); + self::assertTrue($form->has('reset')); + } +} From e6d890d547e2bdc022ebe4eb984ed207b4733cc1 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Sun, 14 Dec 2025 13:45:53 +0100 Subject: [PATCH 11/11] PHP CS Fixer: generic 8.1 cleanup --- .../DependencyInjection/Configuration.php | 1 - .../Component/BrowserKit/AbstractBrowser.php | 2 ++ .../Cache/Traits/Relay/Relay20Trait.php | 2 +- .../Traits/Relay/RelayCluster20Trait.php | 2 +- .../Component/Cache/Traits/ValueWrapper.php | 3 +++ .../Tests/Helper/QuestionHelperTest.php | 2 +- .../Tests/Compiler/AutowirePassTest.php | 1 - .../Tests/ContainerBuilderTest.php | 1 - .../Tests/DebugClassLoaderTest.php | 4 ++- src/Symfony/Component/Form/AbstractType.php | 2 -- .../EventListener/CacheAttributeListener.php | 2 +- .../HttpKernel/HttpKernelBrowser.php | 2 +- .../HttpKernel/Tests/HttpCache/StoreTest.php | 12 ++++----- .../Component/HttpKernel/Tests/KernelTest.php | 2 +- .../Tests/Write/StreamWriterGeneratorTest.php | 2 +- .../FailedMessagesRetryCommandTest.php | 2 +- .../Tests/Extractor/PhpDocExtractorTest.php | 3 --- .../Routing/Tests/RequestContextTest.php | 2 +- .../Runtime/Internal/ComposerPlugin.php | 4 ++- .../AccessToken/Oidc/OidcTokenGenerator.php | 25 ++++++++++--------- .../Bridge/Lokalise/LokaliseProvider.php | 2 +- src/Symfony/Component/Uid/BinaryUtil.php | 2 ++ .../Validator/Constraints/UrlValidator.php | 2 +- .../Constraints/TimezoneValidatorTest.php | 2 +- .../Tests/Caster/ReflectionCasterTest.php | 2 +- 25 files changed, 45 insertions(+), 41 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php index e085d5d7df32a..c148fe59dc7ba 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php @@ -14,7 +14,6 @@ use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Mime\HtmlToTextConverter\HtmlToTextConverterInterface; /** diff --git a/src/Symfony/Component/BrowserKit/AbstractBrowser.php b/src/Symfony/Component/BrowserKit/AbstractBrowser.php index 6d26b86987449..559365db89c7d 100644 --- a/src/Symfony/Component/BrowserKit/AbstractBrowser.php +++ b/src/Symfony/Component/BrowserKit/AbstractBrowser.php @@ -673,3 +673,5 @@ private function extractHost(string $uri): ?string return $host; } } + +// @php-cs-fixer-ignore error_suppression This file is explicitly expected to not silence each of trigger_error calls diff --git a/src/Symfony/Component/Cache/Traits/Relay/Relay20Trait.php b/src/Symfony/Component/Cache/Traits/Relay/Relay20Trait.php index 47930d5da3706..f8f818282c571 100644 --- a/src/Symfony/Component/Cache/Traits/Relay/Relay20Trait.php +++ b/src/Symfony/Component/Cache/Traits/Relay/Relay20Trait.php @@ -27,7 +27,7 @@ public function delex($key, $options = null): \Relay\Relay|false|int return $this->initializeLazyObject()->delex(...\func_get_args()); } - public function digest($key): \Relay\Relay|false|null|string + public function digest($key): \Relay\Relay|false|string|null { return $this->initializeLazyObject()->digest(...\func_get_args()); } diff --git a/src/Symfony/Component/Cache/Traits/Relay/RelayCluster20Trait.php b/src/Symfony/Component/Cache/Traits/Relay/RelayCluster20Trait.php index a196f103dc55f..cefb8af28a897 100644 --- a/src/Symfony/Component/Cache/Traits/Relay/RelayCluster20Trait.php +++ b/src/Symfony/Component/Cache/Traits/Relay/RelayCluster20Trait.php @@ -27,7 +27,7 @@ public function delex($key, $options = null): \Relay\Cluster|false|int return $this->initializeLazyObject()->delex(...\func_get_args()); } - public function digest($key): \Relay\Cluster|false|null|string + public function digest($key): \Relay\Cluster|false|string|null { return $this->initializeLazyObject()->digest(...\func_get_args()); } diff --git a/src/Symfony/Component/Cache/Traits/ValueWrapper.php b/src/Symfony/Component/Cache/Traits/ValueWrapper.php index 718a23d391efe..a97c8571c2125 100644 --- a/src/Symfony/Component/Cache/Traits/ValueWrapper.php +++ b/src/Symfony/Component/Cache/Traits/ValueWrapper.php @@ -79,3 +79,6 @@ public function __unserialize(array $data): void $this->metadata = $metadata; } } + +// @php-cs-fixer-ignore long_to_shorthand_operator To prevent false positive causing "Cannot use assign-op operators with string offsets" error +// @php-cs-fixer-ignore psr_autoloading This class is explicitly having short, special name diff --git a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php index 8d492c564a1a4..774ffc7032d69 100644 --- a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php @@ -970,7 +970,7 @@ public function testExitCommandOnInputSIGINT(string $mode) } $p = new Process( - ['php', dirname(__DIR__).'/Fixtures/application_test_sigint.php', $mode], + ['php', \dirname(__DIR__).'/Fixtures/application_test_sigint.php', $mode], timeout: 2, // the process will auto shutdown if not killed by SIGINT, to prevent blocking ); $p->setPty(true); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 6d23d45df4055..49c9caef2296f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index c801e0e89b637..3b021f7427c6b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -16,7 +16,6 @@ require_once __DIR__.'/Fixtures/includes/ProjectExtension.php'; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\FileLocator; diff --git a/src/Symfony/Component/ErrorHandler/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/ErrorHandler/Tests/DebugClassLoaderTest.php index b57530391d9c3..0f391020974e4 100644 --- a/src/Symfony/Component/ErrorHandler/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/ErrorHandler/Tests/DebugClassLoaderTest.php @@ -120,7 +120,7 @@ public function testDeprecatedSuper(string $class, string $super, string $type) { set_error_handler(fn () => false); $e = error_reporting(0); - trigger_error('', E_USER_DEPRECATED); + trigger_error('', \E_USER_DEPRECATED); class_exists('Test\\'.__NAMESPACE__.'\\'.$class, true); @@ -568,3 +568,5 @@ public function ownAbstractBaseMethod() { } } } } + +// @php-cs-fixer-ignore error_suppression This file is explicitly expected to not silence each of trigger_error calls diff --git a/src/Symfony/Component/Form/AbstractType.php b/src/Symfony/Component/Form/AbstractType.php index 3716eb1fb92c1..74548bc6024d4 100644 --- a/src/Symfony/Component/Form/AbstractType.php +++ b/src/Symfony/Component/Form/AbstractType.php @@ -37,8 +37,6 @@ public function buildView(FormView $view, FormInterface $form, array $options): { } - /** - */ public function finishView(FormView $view, FormInterface $form, array $options): void { } diff --git a/src/Symfony/Component/HttpKernel/EventListener/CacheAttributeListener.php b/src/Symfony/Component/HttpKernel/EventListener/CacheAttributeListener.php index 9dd2abda846d5..0046e4a7be6a7 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/CacheAttributeListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/CacheAttributeListener.php @@ -123,7 +123,7 @@ public function onKernelResponse(ResponseEvent $event): void // Check if the response has a Vary header that should be considered, ignoring cases where // it's only 'Accept-Language' and the request has the '_vary_by_language' attribute $hasVary = ['Accept-Language'] === $response->getVary() ? !$request->attributes->get('_vary_by_language') : $response->hasVary(); - //Check if cache-control directive was set manually in cacheControl (not auto computed) + // Check if cache-control directive was set manually in cacheControl (not auto computed) $hasCacheControlDirective = new class($response->headers) extends HeaderBag { public function __construct(private parent $headerBag) { diff --git a/src/Symfony/Component/HttpKernel/HttpKernelBrowser.php b/src/Symfony/Component/HttpKernel/HttpKernelBrowser.php index 4422bfcdd3e54..06bc420d1c33d 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernelBrowser.php +++ b/src/Symfony/Component/HttpKernel/HttpKernelBrowser.php @@ -184,7 +184,7 @@ protected function filterResponse(object $response): DomResponse ob_start(static function ($chunk) use (&$content) { $content .= $chunk; - return ''; + return ''; }); try { diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php index e8bffba48165a..76af83b0b87d6 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php @@ -350,7 +350,7 @@ public function testLoadsBodyEval() /** * Basic case when the second header has a different value. - * Both responses should be cached + * Both responses should be cached. */ public function testWriteWithMultipleVaryAndCachedAllResponse() { @@ -376,7 +376,7 @@ public function testWriteWithMultipleVaryAndCachedAllResponse() /** * Basic case when the second header has the same value on both requests. - * The last response should be cached + * The last response should be cached. */ public function testWriteWithMultipleVaryAndCachedLastResponse() { @@ -402,7 +402,7 @@ public function testWriteWithMultipleVaryAndCachedLastResponse() /** * Case when a vary value has been removed. - * Both responses should be cached + * Both responses should be cached. */ public function testWriteWithChangingVary() { @@ -425,11 +425,11 @@ public function testWriteWithChangingVary() /** * Case when a vary value has been removed and headers of the new vary list are the same. - * The last response should be cached + * The last response should be cached. */ public function testWriteWithRemoveVaryAndAllHeadersOnTheList() { - $req1 = Request::create('/foo', 'get', [], [], [], ['HTTP_FOO' => 'foo', 'HTTP_FOOBAR' => 'bar',]); + $req1 = Request::create('/foo', 'get', [], [], [], ['HTTP_FOO' => 'foo', 'HTTP_FOOBAR' => 'bar']); $content = str_repeat('a', 24).'b'.str_repeat('a', 24); $res1 = new Response($content, 200, ['vary' => ['Foo', 'bar', 'foobar'], 'X-Body-Eval' => 'SSI']); $this->store->write($req1, $res1); @@ -448,7 +448,7 @@ public function testWriteWithRemoveVaryAndAllHeadersOnTheList() /** * Case when a vary value has been added and headers of the new vary list are the same. - * The last response should be cached + * The last response should be cached. */ public function testWriteWithAddingVaryAndAllHeadersOnTheList() { diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 60043491cb762..09bdd06f48235 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -17,8 +17,8 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpFoundation\Request; diff --git a/src/Symfony/Component/JsonStreamer/Tests/Write/StreamWriterGeneratorTest.php b/src/Symfony/Component/JsonStreamer/Tests/Write/StreamWriterGeneratorTest.php index 8fd7fb3f4b412..bbc3a8fa2b3ee 100644 --- a/src/Symfony/Component/JsonStreamer/Tests/Write/StreamWriterGeneratorTest.php +++ b/src/Symfony/Component/JsonStreamer/Tests/Write/StreamWriterGeneratorTest.php @@ -24,8 +24,8 @@ use Symfony\Component\JsonStreamer\Tests\Fixtures\Mapping\SyntheticPropertyMetadataLoader; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\ClassicDummy; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithArray; -use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithList; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithDollarNamedProperties; +use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithList; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithNameAttributes; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithNestedArray; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithNestedDictDummies; diff --git a/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRetryCommandTest.php b/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRetryCommandTest.php index cbcdf34706f4b..4392495cf8703 100644 --- a/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRetryCommandTest.php +++ b/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRetryCommandTest.php @@ -226,7 +226,7 @@ public function testCompleteIdWithSpecifiedTransport() $this->assertSame(['2ab50dfa1fbf', '78c2da843723'], $suggestions); } - public function testSuccessMessageGoesToStdout() + public function testSuccessMessageGoesToStdout() { $envelope = new Envelope(new \stdClass(), [new TransportMessageIdStamp('some_id')]); $receiver = $this->createMock(ListableReceiverInterface::class); diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php index 3c76f7a9bf9a4..f3e13ebf1d15a 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php @@ -15,8 +15,6 @@ use phpDocumentor\Reflection\PseudoTypes\IntMask; use phpDocumentor\Reflection\PseudoTypes\IntMaskOf; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; use Symfony\Component\PropertyInfo\Tests\Fixtures\ConstructorDummy; @@ -31,7 +29,6 @@ use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsedInTrait; use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsingTrait; use Symfony\Component\TypeInfo\Type; -use Symfony\Component\TypeInfo\Type\NullableType; /** * @author Kévin Dunglas diff --git a/src/Symfony/Component/Routing/Tests/RequestContextTest.php b/src/Symfony/Component/Routing/Tests/RequestContextTest.php index f40045f78919d..83c2293ceaf3e 100644 --- a/src/Symfony/Component/Routing/Tests/RequestContextTest.php +++ b/src/Symfony/Component/Routing/Tests/RequestContextTest.php @@ -47,7 +47,7 @@ public function testConstruct() public function testConstructParametersBcLayer() { - $requestContext = new class() extends RequestContext { + $requestContext = new class extends RequestContext { public function __construct() { $this->setParameters(['foo' => 'bar']); diff --git a/src/Symfony/Component/Runtime/Internal/ComposerPlugin.php b/src/Symfony/Component/Runtime/Internal/ComposerPlugin.php index 92b1f3a37c714..b4cd25b8a33f6 100644 --- a/src/Symfony/Component/Runtime/Internal/ComposerPlugin.php +++ b/src/Symfony/Component/Runtime/Internal/ComposerPlugin.php @@ -82,7 +82,7 @@ public function updateAutoloadFile(): void $projectDir = substr($projectDir, 3); } - // the hack about __DIR__ is required because composer pre-processes plugins + // the hack about __DIR__ is required because Composer pre-processes plugins if (!$nestingLevel) { $projectDir = '__'.'DIR__.'.var_export('/'.$projectDir, true); } else { @@ -118,3 +118,5 @@ public static function getSubscribedEvents(): array ]; } } + +// @php-cs-fixer-ignore no_useless_concat_operator Disable to not override hack about __DIR__ and Composer pre-processes plugins diff --git a/src/Symfony/Component/Security/Http/AccessToken/Oidc/OidcTokenGenerator.php b/src/Symfony/Component/Security/Http/AccessToken/Oidc/OidcTokenGenerator.php index eaba079f68350..4f64f9880921d 100644 --- a/src/Symfony/Component/Security/Http/AccessToken/Oidc/OidcTokenGenerator.php +++ b/src/Symfony/Component/Security/Http/AccessToken/Oidc/OidcTokenGenerator.php @@ -44,19 +44,19 @@ public function generate(string $userIdentifier, ?string $algorithmAlias = null, $now = $this->clock->now(); $payload = [ $this->claim => $userIdentifier, - 'iat' => $now->getTimestamp(), # https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6 - 'aud' => $this->audience, # https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3 - 'iss' => $this->getIssuer($issuer), # https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1 + 'iat' => $now->getTimestamp(), // https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6 + 'aud' => $this->audience, // https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3 + 'iss' => $this->getIssuer($issuer), // https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1 ]; if ($ttl) { if (0 > $ttl) { throw new \InvalidArgumentException('Time to live must be a positive integer.'); } - $payload['exp'] = $now->add(new \DateInterval("PT{$ttl}S"))->getTimestamp(); # https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4 + $payload['exp'] = $now->add(new \DateInterval("PT{$ttl}S"))->getTimestamp(); // https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4 } if ($notBefore) { - $payload['nbf'] = $notBefore->getTimestamp(); # https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5 + $payload['nbf'] = $notBefore->getTimestamp(); // https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5 } $jws = $jwsBuilder @@ -74,13 +74,14 @@ private function getAlgorithm(?string $alias): Algorithm { if ($alias) { if (!$this->algorithmManager->has($alias)) { - throw new \InvalidArgumentException(sprintf('"%s" is not a valid algorithm. Available algorithms: "%s".', $alias, implode('", "', $this->algorithmManager->list()))); + throw new \InvalidArgumentException(\sprintf('"%s" is not a valid algorithm. Available algorithms: "%s".', $alias, implode('", "', $this->algorithmManager->list()))); } + return $this->algorithmManager->get($alias); } - if (1 !== count($list = $this->algorithmManager->list())) { - throw new \InvalidArgumentException(sprintf('Please choose an algorithm. Available algorithms: "%s".', implode('", "', $list))); + if (1 !== \count($list = $this->algorithmManager->list())) { + throw new \InvalidArgumentException(\sprintf('Please choose an algorithm. Available algorithms: "%s".', implode('", "', $list))); } return $this->algorithmManager->get($list[0]); @@ -89,15 +90,15 @@ private function getAlgorithm(?string $alias): Algorithm private function getIssuer(?string $issuer): string { if ($issuer) { - if (!in_array($issuer, $this->issuers, true)) { - throw new \InvalidArgumentException(sprintf('"%s" is not a valid issuer. Available issuers: "%s".', $issuer, implode('", "', $this->issuers))); + if (!\in_array($issuer, $this->issuers, true)) { + throw new \InvalidArgumentException(\sprintf('"%s" is not a valid issuer. Available issuers: "%s".', $issuer, implode('", "', $this->issuers))); } return $issuer; } - if (1 !== count($this->issuers)) { - throw new \InvalidArgumentException(sprintf('Please choose an issuer. Available issuers: "%s".', implode('", "', $this->issuers))); + if (1 !== \count($this->issuers)) { + throw new \InvalidArgumentException(\sprintf('Please choose an issuer. Available issuers: "%s".', implode('", "', $this->issuers))); } return $this->issuers[0]; diff --git a/src/Symfony/Component/Translation/Bridge/Lokalise/LokaliseProvider.php b/src/Symfony/Component/Translation/Bridge/Lokalise/LokaliseProvider.php index 1d68494c66740..18ab959238fa0 100644 --- a/src/Symfony/Component/Translation/Bridge/Lokalise/LokaliseProvider.php +++ b/src/Symfony/Component/Translation/Bridge/Lokalise/LokaliseProvider.php @@ -237,7 +237,7 @@ private function exportFilesAsync(array $locales, array $domains): array return $this->getZipContents($extractPath); } finally { - if (is_resource($h)) { + if (\is_resource($h)) { fclose($h); } @unlink($zipFile); diff --git a/src/Symfony/Component/Uid/BinaryUtil.php b/src/Symfony/Component/Uid/BinaryUtil.php index 7d1e524e5e43e..0c16b9414b19f 100644 --- a/src/Symfony/Component/Uid/BinaryUtil.php +++ b/src/Symfony/Component/Uid/BinaryUtil.php @@ -187,3 +187,5 @@ public static function dateTimeToHex(\DateTimeInterface $time): string return bin2hex($time); } } + +// @php-cs-fixer-ignore long_to_shorthand_operator To prevent false positive causing "Cannot use assign-op operators with string offsets" error diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php index ad17f5d25c110..eefdfc434f9d0 100644 --- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php @@ -83,7 +83,7 @@ public function validate(mixed $value, Constraint $constraint): void } $pattern = $constraint->relativeProtocol ? str_replace('(%s):', '(?:(%s):)?', static::PATTERN) : static::PATTERN; - $pattern = sprintf($pattern, $protocols); + $pattern = \sprintf($pattern, $protocols); if (!preg_match($pattern, $value)) { $this->context->buildViolation($constraint->message) diff --git a/src/Symfony/Component/Validator/Tests/Constraints/TimezoneValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/TimezoneValidatorTest.php index 879cee69f3706..f7b4d82e03218 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/TimezoneValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/TimezoneValidatorTest.php @@ -260,7 +260,7 @@ public function testDeprecatedTimezonesAreValidWithBC(string $timezone) { // Skip test if the timezone is not available in the current timezone database if (!\in_array($timezone, \DateTimeZone::listIdentifiers(\DateTimeZone::ALL_WITH_BC), true)) { - $this->markTestSkipped(sprintf('Timezone "%s" is not available in the current timezone database', $timezone)); + $this->markTestSkipped(\sprintf('Timezone "%s" is not available in the current timezone database', $timezone)); } $constraint = new Timezone(\DateTimeZone::ALL_WITH_BC); diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php index 0f12f14f393b3..dd35bfefa734c 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php @@ -651,7 +651,7 @@ public function testReflectionClassConstantWithAttribute() public function testReflectionParameterWithAttribute() { $var = new \ReflectionParameter([LotsOfAttributes::class, 'someMethod'], 'someParameter'); - + $this->assertDumpMatchesFormat(<<