From 90069bd83ddd0190b9b38f33c224222216c2a2c4 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 5 Apr 2026 23:33:32 +0200 Subject: [PATCH 01/17] Cleanups --- Kernel/MicroKernelTrait.php | 2 +- Tests/Functional/AbstractWebTestCase.php | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Kernel/MicroKernelTrait.php b/Kernel/MicroKernelTrait.php index bb94808b4..4f68d4eb4 100644 --- a/Kernel/MicroKernelTrait.php +++ b/Kernel/MicroKernelTrait.php @@ -47,7 +47,7 @@ trait MicroKernelTrait * * $container->parameters()->set('halloween', 'lot of fun'); */ - private function configureContainer(ContainerConfigurator $container, LoaderInterface $loader, ContainerBuilder $builder): void + private function configureContainer(ContainerConfigurator $container): void { $configDir = preg_replace('{/config$}', '/{config}', $this->getConfigDir()); diff --git a/Tests/Functional/AbstractWebTestCase.php b/Tests/Functional/AbstractWebTestCase.php index 17ff5ed73..fce333120 100644 --- a/Tests/Functional/AbstractWebTestCase.php +++ b/Tests/Functional/AbstractWebTestCase.php @@ -36,12 +36,13 @@ public static function tearDownAfterClass(): void protected static function deleteTmpDir() { - if (!file_exists($dir = sys_get_temp_dir().'/'.static::getVarDir())) { - return; + $fs = new Filesystem(); + + if (file_exists($dir = sys_get_temp_dir().'/'.static::getVarDir())) { + $fs->remove($dir); } - $fs = new Filesystem(); - $fs->remove($dir); + $fs->remove(__DIR__.'/app/config/reference.php'); } protected static function getKernelClass(): string From d9966bcd95ff0f145996ffaf0bf3cc440a044005 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 6 Apr 2026 11:26:53 +0200 Subject: [PATCH 02/17] Add deprecationTrigger ignoreUndefinedTriggers="true" in phpunit.xml.dist files --- phpunit.xml.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 067a87c3a..03797a5d9 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -22,7 +22,7 @@ - + trigger_deprecation Doctrine\Deprecations\Deprecation::trigger Doctrine\Deprecations\Deprecation::triggerIfCalledFromOutside From b99146cbf340a3979b5919b2a3c7a78f53f2ad31 Mon Sep 17 00:00:00 2001 From: Pascal CESCON - Amoifr Date: Mon, 6 Apr 2026 09:35:57 +0200 Subject: [PATCH 03/17] [ObjectMapper] Auto-inject ObjectMapper into ObjectMapperAwareInterface transforms --- .../ObjectMapper/CollectionSource.php | 28 +++++++++++++++++++ .../ObjectMapper/CollectionSourceItem.php | 28 +++++++++++++++++++ .../ObjectMapper/CollectionTarget.php | 18 ++++++++++++ .../ObjectMapper/CollectionTargetItem.php | 27 ++++++++++++++++++ Tests/Functional/ObjectMapperTest.php | 21 ++++++++++++++ 5 files changed, 122 insertions(+) create mode 100644 Tests/Fixtures/ObjectMapper/CollectionSource.php create mode 100644 Tests/Fixtures/ObjectMapper/CollectionSourceItem.php create mode 100644 Tests/Fixtures/ObjectMapper/CollectionTarget.php create mode 100644 Tests/Fixtures/ObjectMapper/CollectionTargetItem.php diff --git a/Tests/Fixtures/ObjectMapper/CollectionSource.php b/Tests/Fixtures/ObjectMapper/CollectionSource.php new file mode 100644 index 000000000..6c6fe6a5c --- /dev/null +++ b/Tests/Fixtures/ObjectMapper/CollectionSource.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Fixtures\ObjectMapper; + +use Symfony\Component\ObjectMapper\Attribute\Map; +use Symfony\Component\ObjectMapper\Transform\MapCollection; + +#[Map(target: CollectionTarget::class)] +final class CollectionSource +{ + /** + * @param CollectionSourceItem[] $items + */ + public function __construct( + #[Map(transform: MapCollection::class)] + public array $items, + ) { + } +} diff --git a/Tests/Fixtures/ObjectMapper/CollectionSourceItem.php b/Tests/Fixtures/ObjectMapper/CollectionSourceItem.php new file mode 100644 index 000000000..8b84859c3 --- /dev/null +++ b/Tests/Fixtures/ObjectMapper/CollectionSourceItem.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Fixtures\ObjectMapper; + +use Symfony\Component\ObjectMapper\Attribute\Map; + +#[Map(target: CollectionTargetItem::class)] +final class CollectionSourceItem +{ + public function __construct( + private string $name, + ) { + } + + public function getName(): string + { + return $this->name; + } +} diff --git a/Tests/Fixtures/ObjectMapper/CollectionTarget.php b/Tests/Fixtures/ObjectMapper/CollectionTarget.php new file mode 100644 index 000000000..cb5fb881b --- /dev/null +++ b/Tests/Fixtures/ObjectMapper/CollectionTarget.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Fixtures\ObjectMapper; + +final class CollectionTarget +{ + /** @var CollectionTargetItem[] */ + public array $items; +} diff --git a/Tests/Fixtures/ObjectMapper/CollectionTargetItem.php b/Tests/Fixtures/ObjectMapper/CollectionTargetItem.php new file mode 100644 index 000000000..84ade6901 --- /dev/null +++ b/Tests/Fixtures/ObjectMapper/CollectionTargetItem.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Fixtures\ObjectMapper; + +final class CollectionTargetItem +{ + private string $name; + + public function setName(string $name): void + { + $this->name = $name; + } + + public function getName(): string + { + return $this->name; + } +} diff --git a/Tests/Functional/ObjectMapperTest.php b/Tests/Functional/ObjectMapperTest.php index e314ee1b0..597abb529 100644 --- a/Tests/Functional/ObjectMapperTest.php +++ b/Tests/Functional/ObjectMapperTest.php @@ -11,6 +11,9 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\ObjectMapper\CollectionSource; +use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\ObjectMapper\CollectionSourceItem; +use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\ObjectMapper\CollectionTarget; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\ObjectMapper\ObjectMapped; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\ObjectMapper\ObjectToBeMapped; @@ -28,4 +31,22 @@ public function testObjectMapper() $mapped = $objectMapper->map(new ObjectToBeMapped()); $this->assertSame($mapped->a, 'transformed'); } + + public function testMapCollectionUsesContainerObjectMapper() + { + static::bootKernel(['test_case' => 'ObjectMapper']); + + $objectMapper = static::getContainer()->get('object_mapper.alias'); + $source = new CollectionSource([ + new CollectionSourceItem('foo'), + new CollectionSourceItem('bar'), + ]); + + /** @var CollectionTarget $mapped */ + $mapped = $objectMapper->map($source); + + $this->assertCount(2, $mapped->items); + $this->assertSame('foo', $mapped->items[0]->getName()); + $this->assertSame('bar', $mapped->items[1]->getName()); + } } From 78263b32a07a598d36409228d1786128d23a141e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 12 Apr 2026 22:27:02 +0200 Subject: [PATCH 04/17] Fix tests with 8.1 deps --- Tests/Functional/app/ObjectMapper/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/Functional/app/ObjectMapper/config.yml b/Tests/Functional/app/ObjectMapper/config.yml index 3e3bd8702..e76600505 100644 --- a/Tests/Functional/app/ObjectMapper/config.yml +++ b/Tests/Functional/app/ObjectMapper/config.yml @@ -7,3 +7,5 @@ services: public: true Symfony\Bundle\FrameworkBundle\Tests\Fixtures\ObjectMapper\TransformCallable: autoconfigure: true + Symfony\Component\ObjectMapper\Transform\MapCollection: + autoconfigure: true From 108c375df6653140546fe6d8b41e5308ed2a7457 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 13 Apr 2026 14:48:23 +0200 Subject: [PATCH 05/17] [CS] Back config from 8.1 and apply heredoc_indentation rule --- Command/AboutCommand.php | 8 +-- Command/AssetsInstallCommand.php | 22 ++++---- Command/CacheClearCommand.php | 10 ++-- Command/CachePoolClearCommand.php | 6 +-- Command/CachePoolDeleteCommand.php | 6 +-- Command/CachePoolListCommand.php | 4 +- Command/CachePoolPruneCommand.php | 6 +-- Command/CacheWarmupCommand.php | 6 +-- Command/ConfigDebugCommand.php | 22 ++++---- Command/ConfigDumpReferenceCommand.php | 22 ++++---- Command/ContainerDebugCommand.php | 52 +++++++++---------- Command/DebugAutowiringCommand.php | 12 ++--- Command/EventDispatcherDebugCommand.php | 10 ++-- Command/RouterDebugCommand.php | 6 +-- Command/RouterMatchCommand.php | 10 ++-- Command/SecretsDecryptToLocalCommand.php | 10 ++-- Command/SecretsEncryptFromLocalCommand.php | 6 +-- Command/SecretsGenerateKeysCommand.php | 14 ++--- Command/SecretsListCommand.php | 10 ++-- Command/SecretsRemoveCommand.php | 6 +-- Command/SecretsSetCommand.php | 22 ++++---- Command/TranslationDebugCommand.php | 32 ++++++------ Command/TranslationUpdateCommand.php | 34 ++++++------ Command/WorkflowDumpCommand.php | 12 ++--- Command/XliffLintCommand.php | 6 +-- Command/YamlLintCommand.php | 6 +-- KernelBrowser.php | 24 ++++----- Tests/Command/XliffLintCommandTest.php | 6 +-- Tests/Command/YamlLintCommandTest.php | 6 +-- Tests/Functional/ApiAttributesTest.php | 10 ++-- .../ConfigDumpReferenceCommandTest.php | 10 ++-- .../Functional/ContainerDebugCommandTest.php | 26 +++++----- Tests/Functional/FragmentTest.php | 16 +++--- 33 files changed, 229 insertions(+), 229 deletions(-) diff --git a/Command/AboutCommand.php b/Command/AboutCommand.php index 2c6cb440f..8a4c6dbc4 100644 --- a/Command/AboutCommand.php +++ b/Command/AboutCommand.php @@ -35,11 +35,11 @@ protected function configure(): void { $this ->setHelp(<<<'EOT' -The %command.name% command displays information about the current Symfony project. + The %command.name% command displays information about the current Symfony project. -The PHP section displays important configuration that could affect your application. The values might -be different between web and CLI. -EOT + The PHP section displays important configuration that could affect your application. The values might + be different between web and CLI. + EOT ) ; } diff --git a/Command/AssetsInstallCommand.php b/Command/AssetsInstallCommand.php index 936912876..e35b2f70e 100644 --- a/Command/AssetsInstallCommand.php +++ b/Command/AssetsInstallCommand.php @@ -62,24 +62,24 @@ protected function configure(): void ->addOption('relative', null, InputOption::VALUE_NONE, 'Make relative symlinks') ->addOption('no-cleanup', null, InputOption::VALUE_NONE, 'Do not remove the assets of the bundles that no longer exist') ->setHelp(<<<'EOT' -The %command.name% command installs bundle assets into a given -directory (e.g. the public directory). + The %command.name% command installs bundle assets into a given + directory (e.g. the public directory). - php %command.full_name% public + php %command.full_name% public -A "bundles" directory will be created inside the target directory and the -"Resources/public" directory of each bundle will be copied into it. + A "bundles" directory will be created inside the target directory and the + "Resources/public" directory of each bundle will be copied into it. -To create a symlink to each bundle instead of copying its assets, use the ---symlink option (will fall back to hard copies when symbolic links aren't possible: + To create a symlink to each bundle instead of copying its assets, use the + --symlink option (will fall back to hard copies when symbolic links aren't possible: - php %command.full_name% public --symlink + php %command.full_name% public --symlink -To make symlink relative, add the --relative option: + To make symlink relative, add the --relative option: - php %command.full_name% public --symlink --relative + php %command.full_name% public --symlink --relative -EOT + EOT ) ; } diff --git a/Command/CacheClearCommand.php b/Command/CacheClearCommand.php index df9f38a26..affa09534 100644 --- a/Command/CacheClearCommand.php +++ b/Command/CacheClearCommand.php @@ -56,12 +56,12 @@ protected function configure(): void new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), ]) ->setHelp(<<<'EOF' -The %command.name% command clears and warms up the application cache for a given environment -and debug mode: + The %command.name% command clears and warms up the application cache for a given environment + and debug mode: - php %command.full_name% --env=dev - php %command.full_name% --env=prod --no-debug -EOF + php %command.full_name% --env=dev + php %command.full_name% --env=prod --no-debug + EOF ) ; } diff --git a/Command/CachePoolClearCommand.php b/Command/CachePoolClearCommand.php index 9d1662e65..22e1a1bde 100644 --- a/Command/CachePoolClearCommand.php +++ b/Command/CachePoolClearCommand.php @@ -55,10 +55,10 @@ protected function configure(): void ->addOption('all', null, InputOption::VALUE_NONE, 'Clear all cache pools') ->addOption('exclude', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'A list of cache pools or cache pool clearers to exclude') ->setHelp(<<<'EOF' -The %command.name% command clears the given cache pools or cache pool clearers. + The %command.name% command clears the given cache pools or cache pool clearers. - %command.full_name% [...] -EOF + %command.full_name% [...] + EOF ) ; } diff --git a/Command/CachePoolDeleteCommand.php b/Command/CachePoolDeleteCommand.php index 3c5e49dbf..e34746871 100644 --- a/Command/CachePoolDeleteCommand.php +++ b/Command/CachePoolDeleteCommand.php @@ -51,10 +51,10 @@ protected function configure(): void new InputArgument('key', InputArgument::REQUIRED, 'The cache key to delete from the pool'), ]) ->setHelp(<<<'EOF' -The %command.name% deletes an item from a given cache pool. + The %command.name% deletes an item from a given cache pool. - %command.full_name% -EOF + %command.full_name% + EOF ) ; } diff --git a/Command/CachePoolListCommand.php b/Command/CachePoolListCommand.php index 2659ad8fe..0014742e2 100644 --- a/Command/CachePoolListCommand.php +++ b/Command/CachePoolListCommand.php @@ -41,8 +41,8 @@ protected function configure(): void { $this ->setHelp(<<<'EOF' -The %command.name% command lists all available cache pools. -EOF + The %command.name% command lists all available cache pools. + EOF ) ; } diff --git a/Command/CachePoolPruneCommand.php b/Command/CachePoolPruneCommand.php index ff90a9dba..3d52b1c36 100644 --- a/Command/CachePoolPruneCommand.php +++ b/Command/CachePoolPruneCommand.php @@ -42,10 +42,10 @@ protected function configure(): void { $this ->setHelp(<<<'EOF' -The %command.name% command deletes all expired items from all pruneable pools. + The %command.name% command deletes all expired items from all pruneable pools. - %command.full_name% -EOF + %command.full_name% + EOF ) ; } diff --git a/Command/CacheWarmupCommand.php b/Command/CacheWarmupCommand.php index 08e6ebc4d..f1674d439 100644 --- a/Command/CacheWarmupCommand.php +++ b/Command/CacheWarmupCommand.php @@ -47,11 +47,11 @@ protected function configure(): void new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), ]) ->setHelp(<<<'EOF' -The %command.name% command warms up the cache. + The %command.name% command warms up the cache. -Before running this command, the cache must be empty. + Before running this command, the cache must be empty. -EOF + EOF ) ; } diff --git a/Command/ConfigDebugCommand.php b/Command/ConfigDebugCommand.php index f0bcb1786..51dcc84b9 100644 --- a/Command/ConfigDebugCommand.php +++ b/Command/ConfigDebugCommand.php @@ -59,24 +59,24 @@ protected function configure(): void new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), class_exists(Yaml::class) ? 'txt' : 'json'), ]) ->setHelp(<<%command.name% command dumps the current configuration for an -extension/bundle. + The %command.name% command dumps the current configuration for an + extension/bundle. -Either the extension alias or bundle name can be used: + Either the extension alias or bundle name can be used: - php %command.full_name% framework - php %command.full_name% FrameworkBundle + php %command.full_name% framework + php %command.full_name% FrameworkBundle -The --format option specifies the format of the configuration, -these are "{$helpFormats}". + The --format option specifies the format of the configuration, + these are "{$helpFormats}". - php %command.full_name% framework --format=json + php %command.full_name% framework --format=json -For dumping a specific option, add its path as second argument: + For dumping a specific option, add its path as second argument: - php %command.full_name% framework serializer.enabled + php %command.full_name% framework serializer.enabled -EOF + EOF ) ; } diff --git a/Command/ConfigDumpReferenceCommand.php b/Command/ConfigDumpReferenceCommand.php index 27dc01b11..dea6f5746 100644 --- a/Command/ConfigDumpReferenceCommand.php +++ b/Command/ConfigDumpReferenceCommand.php @@ -49,24 +49,24 @@ protected function configure(): void new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'yaml'), ]) ->setHelp(<<%command.name% command dumps the default configuration for an -extension/bundle. + The %command.name% command dumps the default configuration for an + extension/bundle. -Either the extension alias or bundle name can be used: + Either the extension alias or bundle name can be used: - php %command.full_name% framework - php %command.full_name% FrameworkBundle + php %command.full_name% framework + php %command.full_name% FrameworkBundle -The --format option specifies the format of the configuration, -these are "{$helpFormats}". + The --format option specifies the format of the configuration, + these are "{$helpFormats}". - php %command.full_name% FrameworkBundle --format=xml + php %command.full_name% FrameworkBundle --format=xml -For dumping a specific option, add its path as second argument (only available for the yaml format): + For dumping a specific option, add its path as second argument (only available for the yaml format): - php %command.full_name% framework http_client.default_options + php %command.full_name% framework http_client.default_options -EOF + EOF ) ; } diff --git a/Command/ContainerDebugCommand.php b/Command/ContainerDebugCommand.php index 6847926ff..f54df8deb 100644 --- a/Command/ContainerDebugCommand.php +++ b/Command/ContainerDebugCommand.php @@ -57,56 +57,56 @@ protected function configure(): void new InputOption('deprecations', null, InputOption::VALUE_NONE, 'Display deprecations generated when compiling and warming up the container'), ]) ->setHelp(<<<'EOF' -The %command.name% command displays all configured public services: + The %command.name% command displays all configured public services: - php %command.full_name% + php %command.full_name% -To see deprecations generated during container compilation and cache warmup, use the --deprecations option: + To see deprecations generated during container compilation and cache warmup, use the --deprecations option: - php %command.full_name% --deprecations + php %command.full_name% --deprecations -To get specific information about a service, specify its name: + To get specific information about a service, specify its name: - php %command.full_name% validator + php %command.full_name% validator -To get specific information about a service including all its arguments, use the --show-arguments flag: + To get specific information about a service including all its arguments, use the --show-arguments flag: - php %command.full_name% validator --show-arguments + php %command.full_name% validator --show-arguments -To see available types that can be used for autowiring, use the --types flag: + To see available types that can be used for autowiring, use the --types flag: - php %command.full_name% --types + php %command.full_name% --types -To see environment variables used by the container, use the --env-vars flag: + To see environment variables used by the container, use the --env-vars flag: - php %command.full_name% --env-vars + php %command.full_name% --env-vars -Display a specific environment variable by specifying its name with the --env-var option: + Display a specific environment variable by specifying its name with the --env-var option: - php %command.full_name% --env-var=APP_ENV + php %command.full_name% --env-var=APP_ENV -Use the --tags option to display tagged public services grouped by tag: + Use the --tags option to display tagged public services grouped by tag: - php %command.full_name% --tags + php %command.full_name% --tags -Find all services with a specific tag by specifying the tag name with the --tag option: + Find all services with a specific tag by specifying the tag name with the --tag option: - php %command.full_name% --tag=form.type + php %command.full_name% --tag=form.type -Use the --parameters option to display all parameters: + Use the --parameters option to display all parameters: - php %command.full_name% --parameters + php %command.full_name% --parameters -Display a specific parameter by specifying its name with the --parameter option: + Display a specific parameter by specifying its name with the --parameter option: - php %command.full_name% --parameter=kernel.debug + php %command.full_name% --parameter=kernel.debug -By default, internal services are hidden. You can display them -using the --show-hidden flag: + By default, internal services are hidden. You can display them + using the --show-hidden flag: - php %command.full_name% --show-hidden + php %command.full_name% --show-hidden -EOF + EOF ) ; } diff --git a/Command/DebugAutowiringCommand.php b/Command/DebugAutowiringCommand.php index 3fde1407b..fdf98f908 100644 --- a/Command/DebugAutowiringCommand.php +++ b/Command/DebugAutowiringCommand.php @@ -49,16 +49,16 @@ protected function configure(): void new InputOption('all', null, InputOption::VALUE_NONE, 'Show also services that are not aliased'), ]) ->setHelp(<<<'EOF' -The %command.name% command displays the classes and interfaces that -you can use as type-hints for autowiring: + The %command.name% command displays the classes and interfaces that + you can use as type-hints for autowiring: - php %command.full_name% + php %command.full_name% -You can also pass a search term to filter the list: + You can also pass a search term to filter the list: - php %command.full_name% log + php %command.full_name% log -EOF + EOF ) ; } diff --git a/Command/EventDispatcherDebugCommand.php b/Command/EventDispatcherDebugCommand.php index b6c644499..7eb47a174 100644 --- a/Command/EventDispatcherDebugCommand.php +++ b/Command/EventDispatcherDebugCommand.php @@ -56,14 +56,14 @@ protected function configure(): void new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'), ]) ->setHelp(<<<'EOF' -The %command.name% command displays all configured listeners: + The %command.name% command displays all configured listeners: - php %command.full_name% + php %command.full_name% -To get specific listeners for an event, specify its name: + To get specific listeners for an event, specify its name: - php %command.full_name% kernel.request -EOF + php %command.full_name% kernel.request + EOF ) ; } diff --git a/Command/RouterDebugCommand.php b/Command/RouterDebugCommand.php index 9f689a142..086a572ab 100644 --- a/Command/RouterDebugCommand.php +++ b/Command/RouterDebugCommand.php @@ -61,11 +61,11 @@ protected function configure(): void new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw route(s)'), ]) ->setHelp(<<<'EOF' -The %command.name% displays the configured routes: + The %command.name% displays the configured routes: - php %command.full_name% + php %command.full_name% -EOF + EOF ) ; } diff --git a/Command/RouterMatchCommand.php b/Command/RouterMatchCommand.php index 73e5c5d0d..4dc60b7bd 100644 --- a/Command/RouterMatchCommand.php +++ b/Command/RouterMatchCommand.php @@ -57,15 +57,15 @@ protected function configure(): void new InputOption('host', null, InputOption::VALUE_REQUIRED, 'Set the URI host'), ]) ->setHelp(<<<'EOF' -The %command.name% shows which routes match a given request and which don't and for what reason: + The %command.name% shows which routes match a given request and which don't and for what reason: - php %command.full_name% /foo + php %command.full_name% /foo -or + or - php %command.full_name% /foo --method POST --scheme https --host symfony.com --verbose + php %command.full_name% /foo --method POST --scheme https --host symfony.com --verbose -EOF + EOF ) ; } diff --git a/Command/SecretsDecryptToLocalCommand.php b/Command/SecretsDecryptToLocalCommand.php index 665c5c454..72c2a0c85 100644 --- a/Command/SecretsDecryptToLocalCommand.php +++ b/Command/SecretsDecryptToLocalCommand.php @@ -44,14 +44,14 @@ protected function configure(): void $this ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force overriding of secrets that already exist in the local vault') ->setHelp(<<<'EOF' -The %command.name% command decrypts all secrets and copies them in the local vault. + The %command.name% command decrypts all secrets and copies them in the local vault. - %command.full_name% + %command.full_name% -When the --force option is provided, secrets that already exist in the local vault are overridden. + When the --force option is provided, secrets that already exist in the local vault are overridden. - %command.full_name% --force -EOF + %command.full_name% --force + EOF ) ; } diff --git a/Command/SecretsEncryptFromLocalCommand.php b/Command/SecretsEncryptFromLocalCommand.php index 0eba8956c..1f72784b7 100644 --- a/Command/SecretsEncryptFromLocalCommand.php +++ b/Command/SecretsEncryptFromLocalCommand.php @@ -42,10 +42,10 @@ protected function configure(): void { $this ->setHelp(<<<'EOF' -The %command.name% command encrypts all locally overridden secrets to the vault. + The %command.name% command encrypts all locally overridden secrets to the vault. - %command.full_name% -EOF + %command.full_name% + EOF ) ; } diff --git a/Command/SecretsGenerateKeysCommand.php b/Command/SecretsGenerateKeysCommand.php index c250258c1..f0ce10314 100644 --- a/Command/SecretsGenerateKeysCommand.php +++ b/Command/SecretsGenerateKeysCommand.php @@ -47,16 +47,16 @@ protected function configure(): void ->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.') ->addOption('rotate', 'r', InputOption::VALUE_NONE, 'Re-encrypt existing secrets with the newly generated keys.') ->setHelp(<<<'EOF' -The %command.name% command generates a new encryption key. + The %command.name% command generates a new encryption key. - %command.full_name% + %command.full_name% -If encryption keys already exist, the command must be called with -the --rotate option in order to override those keys and re-encrypt -existing secrets. + If encryption keys already exist, the command must be called with + the --rotate option in order to override those keys and re-encrypt + existing secrets. - %command.full_name% --rotate -EOF + %command.full_name% --rotate + EOF ) ; } diff --git a/Command/SecretsListCommand.php b/Command/SecretsListCommand.php index 4ba335e62..a27e0056d 100644 --- a/Command/SecretsListCommand.php +++ b/Command/SecretsListCommand.php @@ -47,14 +47,14 @@ protected function configure(): void $this ->addOption('reveal', 'r', InputOption::VALUE_NONE, 'Display decrypted values alongside names') ->setHelp(<<<'EOF' -The %command.name% command list all stored secrets. + The %command.name% command list all stored secrets. - %command.full_name% + %command.full_name% -When the option --reveal is provided, the decrypted secrets are also displayed. + When the option --reveal is provided, the decrypted secrets are also displayed. - %command.full_name% --reveal -EOF + %command.full_name% --reveal + EOF ) ; } diff --git a/Command/SecretsRemoveCommand.php b/Command/SecretsRemoveCommand.php index 3e75ba0c4..963efc522 100644 --- a/Command/SecretsRemoveCommand.php +++ b/Command/SecretsRemoveCommand.php @@ -49,10 +49,10 @@ protected function configure(): void ->addArgument('name', InputArgument::REQUIRED, 'The name of the secret') ->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.') ->setHelp(<<<'EOF' -The %command.name% command removes a secret from the vault. + The %command.name% command removes a secret from the vault. - %command.full_name% -EOF + %command.full_name% + EOF ) ; } diff --git a/Command/SecretsSetCommand.php b/Command/SecretsSetCommand.php index e2fc39e04..940e34007 100644 --- a/Command/SecretsSetCommand.php +++ b/Command/SecretsSetCommand.php @@ -52,24 +52,24 @@ protected function configure(): void ->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.') ->addOption('random', 'r', InputOption::VALUE_OPTIONAL, 'Generate a random value.', false) ->setHelp(<<<'EOF' -The %command.name% command stores a secret in the vault. + The %command.name% command stores a secret in the vault. - %command.full_name% + %command.full_name% -To reference secrets in services.yaml or any other config -files, use "%env()%". + To reference secrets in services.yaml or any other config + files, use "%env()%". -By default, the secret value should be entered interactively. -Alternatively, provide a file where to read the secret from: + By default, the secret value should be entered interactively. + Alternatively, provide a file where to read the secret from: - php %command.full_name% filename + php %command.full_name% filename -Use "-" as a file name to read from STDIN: + Use "-" as a file name to read from STDIN: - cat filename | php %command.full_name% - + cat filename | php %command.full_name% - -Use --local to override secrets for local needs. -EOF + Use --local to override secrets for local needs. + EOF ) ; } diff --git a/Command/TranslationDebugCommand.php b/Command/TranslationDebugCommand.php index 46e90ed40..7d752e2eb 100644 --- a/Command/TranslationDebugCommand.php +++ b/Command/TranslationDebugCommand.php @@ -85,35 +85,35 @@ protected function configure(): void new InputOption('all', null, InputOption::VALUE_NONE, 'Load messages from all registered bundles'), ]) ->setHelp(<<<'EOF' -The %command.name% command helps finding unused or missing translation -messages and comparing them with the fallback ones by inspecting the -templates and translation files of a given bundle or the default translations directory. + The %command.name% command helps finding unused or missing translation + messages and comparing them with the fallback ones by inspecting the + templates and translation files of a given bundle or the default translations directory. -You can display information about bundle translations in a specific locale: + You can display information about bundle translations in a specific locale: - php %command.full_name% en AcmeDemoBundle + php %command.full_name% en AcmeDemoBundle -You can also specify a translation domain for the search: + You can also specify a translation domain for the search: - php %command.full_name% --domain=messages en AcmeDemoBundle + php %command.full_name% --domain=messages en AcmeDemoBundle -You can only display missing messages: + You can only display missing messages: - php %command.full_name% --only-missing en AcmeDemoBundle + php %command.full_name% --only-missing en AcmeDemoBundle -You can only display unused messages: + You can only display unused messages: - php %command.full_name% --only-unused en AcmeDemoBundle + php %command.full_name% --only-unused en AcmeDemoBundle -You can display information about application translations in a specific locale: + You can display information about application translations in a specific locale: - php %command.full_name% en + php %command.full_name% en -You can display information about translations in all registered bundles in a specific locale: + You can display information about translations in all registered bundles in a specific locale: - php %command.full_name% --all en + php %command.full_name% --all en -EOF + EOF ) ; } diff --git a/Command/TranslationUpdateCommand.php b/Command/TranslationUpdateCommand.php index b8759bc92..8065a147f 100644 --- a/Command/TranslationUpdateCommand.php +++ b/Command/TranslationUpdateCommand.php @@ -94,33 +94,33 @@ protected function configure(): void new InputOption('as-tree', null, InputOption::VALUE_REQUIRED, 'Dump the messages as a tree-like structure: The given value defines the level where to switch to inline YAML'), ]) ->setHelp(<<<'EOF' -The %command.name% command extracts translation strings from templates -of a given bundle or the default translations directory. It can display them or merge -the new ones into the translation files. + The %command.name% command extracts translation strings from templates + of a given bundle or the default translations directory. It can display them or merge + the new ones into the translation files. -When new translation strings are found it can automatically add a prefix to the translation -message. + When new translation strings are found it can automatically add a prefix to the translation + message. -Example running against a Bundle (AcmeBundle) + Example running against a Bundle (AcmeBundle) - php %command.full_name% --dump-messages en AcmeBundle - php %command.full_name% --force --prefix="new_" fr AcmeBundle + php %command.full_name% --dump-messages en AcmeBundle + php %command.full_name% --force --prefix="new_" fr AcmeBundle -Example running against default messages directory + Example running against default messages directory - php %command.full_name% --dump-messages en - php %command.full_name% --force --prefix="new_" fr + php %command.full_name% --dump-messages en + php %command.full_name% --force --prefix="new_" fr -You can sort the output with the --sort flag: + You can sort the output with the --sort flag: - php %command.full_name% --dump-messages --sort=asc en AcmeBundle - php %command.full_name% --dump-messages --sort=desc fr + php %command.full_name% --dump-messages --sort=asc en AcmeBundle + php %command.full_name% --dump-messages --sort=desc fr -You can dump a tree-like structure using the yaml format with --as-tree flag: + You can dump a tree-like structure using the yaml format with --as-tree flag: - php %command.full_name% --force --format=yaml --as-tree=3 en AcmeBundle + php %command.full_name% --force --format=yaml --as-tree=3 en AcmeBundle -EOF + EOF ) ; } diff --git a/Command/WorkflowDumpCommand.php b/Command/WorkflowDumpCommand.php index 5abd98297..6b44f605b 100644 --- a/Command/WorkflowDumpCommand.php +++ b/Command/WorkflowDumpCommand.php @@ -77,13 +77,13 @@ protected function configure(): void new InputOption('dump-format', null, InputOption::VALUE_REQUIRED, 'The dump format ['.implode('|', self::DUMP_FORMAT_OPTIONS).']', 'dot'), ]) ->setHelp(<<<'EOF' -The %command.name% command dumps the graphical representation of a -workflow in different formats + The %command.name% command dumps the graphical representation of a + workflow in different formats -DOT: %command.full_name% | dot -Tpng > workflow.png -PUML: %command.full_name% --dump-format=puml | java -jar plantuml.jar -p > workflow.png -MERMAID: %command.full_name% --dump-format=mermaid | mmdc -o workflow.svg -EOF + DOT: %command.full_name% | dot -Tpng > workflow.png + PUML: %command.full_name% --dump-format=puml | java -jar plantuml.jar -p > workflow.png + MERMAID: %command.full_name% --dump-format=mermaid | mmdc -o workflow.svg + EOF ) ; } diff --git a/Command/XliffLintCommand.php b/Command/XliffLintCommand.php index 5b094f165..9bbe39db1 100644 --- a/Command/XliffLintCommand.php +++ b/Command/XliffLintCommand.php @@ -47,11 +47,11 @@ protected function configure(): void $this->setHelp($this->getHelp().<<<'EOF' -Or find all files in a bundle: + Or find all files in a bundle: - php %command.full_name% @AcmeDemoBundle + php %command.full_name% @AcmeDemoBundle -EOF + EOF ); } } diff --git a/Command/YamlLintCommand.php b/Command/YamlLintCommand.php index 141390812..5948add7c 100644 --- a/Command/YamlLintCommand.php +++ b/Command/YamlLintCommand.php @@ -46,11 +46,11 @@ protected function configure(): void $this->setHelp($this->getHelp().<<<'EOF' -Or find all files in a bundle: + Or find all files in a bundle: - php %command.full_name% @AcmeDemoBundle + php %command.full_name% @AcmeDemoBundle -EOF + EOF ); } } diff --git a/KernelBrowser.php b/KernelBrowser.php index cf1d1652f..f13332695 100644 --- a/KernelBrowser.php +++ b/KernelBrowser.php @@ -223,25 +223,25 @@ protected function getScript(object $request): string $profilerCode = ''; if ($this->profiler) { $profilerCode = <<<'EOF' -$container = $kernel->getContainer(); -$container = $container->has('test.service_container') ? $container->get('test.service_container') : $container; -$container->get('profiler')->enable(); -EOF; + $container = $kernel->getContainer(); + $container = $container->has('test.service_container') ? $container->get('test.service_container') : $container; + $container->get('profiler')->enable(); + EOF; } $code = <<boot(); -$profilerCode + \$kernel = unserialize($kernel); + \$kernel->boot(); + $profilerCode -\$request = unserialize($request); -EOF; + \$request = unserialize($request); + EOF; return $code.$this->getHandleScript(); } diff --git a/Tests/Command/XliffLintCommandTest.php b/Tests/Command/XliffLintCommandTest.php index 73e9574a6..6005cc54e 100644 --- a/Tests/Command/XliffLintCommandTest.php +++ b/Tests/Command/XliffLintCommandTest.php @@ -35,10 +35,10 @@ public function testGetHelp() { $command = new XliffLintCommand(); $expected = <<php %command.full_name% @AcmeDemoBundle -EOF; + php %command.full_name% @AcmeDemoBundle + EOF; $this->assertStringContainsString($expected, $command->getHelp()); } diff --git a/Tests/Command/YamlLintCommandTest.php b/Tests/Command/YamlLintCommandTest.php index 6363fb4b2..e84ef1b06 100644 --- a/Tests/Command/YamlLintCommandTest.php +++ b/Tests/Command/YamlLintCommandTest.php @@ -73,10 +73,10 @@ public function testGetHelp() { $command = new YamlLintCommand(); $expected = <<php %command.full_name% @AcmeDemoBundle -EOF; + php %command.full_name% @AcmeDemoBundle + EOF; $this->assertStringContainsString($expected, $command->getHelp()); } diff --git a/Tests/Functional/ApiAttributesTest.php b/Tests/Functional/ApiAttributesTest.php index c65fc4d3d..28fc7532f 100644 --- a/Tests/Functional/ApiAttributesTest.php +++ b/Tests/Functional/ApiAttributesTest.php @@ -356,11 +356,11 @@ public function __invoke(#[MapRequestPayload] ?RequestBody $body, Request $reque return new Response( << - {$body->comment} - {$body->approved} - - XML + + {$body->comment} + {$body->approved} + + XML ); } } diff --git a/Tests/Functional/ConfigDumpReferenceCommandTest.php b/Tests/Functional/ConfigDumpReferenceCommandTest.php index 8f5930faa..5fa061969 100644 --- a/Tests/Functional/ConfigDumpReferenceCommandTest.php +++ b/Tests/Functional/ConfigDumpReferenceCommandTest.php @@ -98,13 +98,13 @@ public function testDumpAtPath(bool $debug) $this->assertSame(0, $ret, 'Returns 0 in case of success'); $this->assertSame(<<<'EOL' -# Default configuration for extension with alias: "test" at path "array" -array: - child1: ~ - child2: ~ + # Default configuration for extension with alias: "test" at path "array" + array: + child1: ~ + child2: ~ -EOL + EOL , $tester->getDisplay(true)); } diff --git a/Tests/Functional/ContainerDebugCommandTest.php b/Tests/Functional/ContainerDebugCommandTest.php index fe0582c65..1efe5e09a 100644 --- a/Tests/Functional/ContainerDebugCommandTest.php +++ b/Tests/Functional/ContainerDebugCommandTest.php @@ -168,24 +168,24 @@ public function testDescribeEnvVars() $this->assertStringMatchesFormat(<<<'TXT' -Symfony Container Environment Variables -======================================= + Symfony Container Environment Variables + ======================================= - --------- ----------------- ------------%w - Name Default value Real value%w - --------- ----------------- ------------%w - JSON "[1, "2.5", 3]" n/a%w - REAL n/a "value"%w - UNKNOWN n/a n/a%w - --------- ----------------- ------------%w + --------- ----------------- ------------%w + Name Default value Real value%w + --------- ----------------- ------------%w + JSON "[1, "2.5", 3]" n/a%w + REAL n/a "value"%w + UNKNOWN n/a n/a%w + --------- ----------------- ------------%w - // Note real values might be different between web and CLI.%w + // Note real values might be different between web and CLI.%w - [WARNING] The following variables are missing:%w + [WARNING] The following variables are missing:%w - * UNKNOWN + * UNKNOWN -TXT + TXT , $tester->getDisplay(true)); putenv('REAL'); diff --git a/Tests/Functional/FragmentTest.php b/Tests/Functional/FragmentTest.php index 48d5c327a..deda16ac4 100644 --- a/Tests/Functional/FragmentTest.php +++ b/Tests/Functional/FragmentTest.php @@ -26,14 +26,14 @@ public function testFragment($insulate) $client->request('GET', '/fragment_home'); $this->assertEquals(<<getResponse()->getContent()); } From 48f71082983f1e9102926422fab86d9441b14978 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 13 Apr 2026 15:47:38 +0200 Subject: [PATCH 06/17] Backport some CS fixes from 7.4 --- Tests/Functional/ContainerDebugCommandTest.php | 5 +++-- Tests/Functional/FragmentTest.php | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Tests/Functional/ContainerDebugCommandTest.php b/Tests/Functional/ContainerDebugCommandTest.php index 1efe5e09a..9e09868d3 100644 --- a/Tests/Functional/ContainerDebugCommandTest.php +++ b/Tests/Functional/ContainerDebugCommandTest.php @@ -185,8 +185,9 @@ public function testDescribeEnvVars() * UNKNOWN - TXT - , $tester->getDisplay(true)); + TXT, + $tester->getDisplay(true) + ); putenv('REAL'); } diff --git a/Tests/Functional/FragmentTest.php b/Tests/Functional/FragmentTest.php index deda16ac4..f53e972f5 100644 --- a/Tests/Functional/FragmentTest.php +++ b/Tests/Functional/FragmentTest.php @@ -33,8 +33,9 @@ public function testFragment($insulate) es -- fr - TXT - , $client->getResponse()->getContent()); + TXT, + $client->getResponse()->getContent() + ); } public static function getConfigs() From 355cb4e327f5506ab03c6ab9de877db3e763cc81 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 13 Apr 2026 16:11:12 +0200 Subject: [PATCH 07/17] CS fixes - native_function_invocation & static_lambda --- CacheWarmer/AbstractPhpFileCacheWarmer.php | 2 +- CacheWarmer/AnnotationsCacheWarmer.php | 2 +- CacheWarmer/ConfigBuilderCacheWarmer.php | 2 +- CacheWarmer/ValidatorCacheWarmer.php | 2 +- Command/AbstractConfigCommand.php | 2 +- Command/AssetsInstallCommand.php | 2 +- Command/CachePoolListCommand.php | 2 +- Command/ConfigDumpReferenceCommand.php | 2 +- Command/DebugAutowiringCommand.php | 2 +- Command/SecretsListCommand.php | 2 +- Command/TranslationUpdateCommand.php | 4 +- Command/XliffLintCommand.php | 2 +- Command/YamlLintCommand.php | 2 +- Console/Descriptor/Descriptor.php | 6 +- Console/Descriptor/JsonDescriptor.php | 2 +- Console/Descriptor/MarkdownDescriptor.php | 2 +- Console/Descriptor/TextDescriptor.php | 2 +- Console/Descriptor/XmlDescriptor.php | 2 +- Controller/AbstractController.php | 2 +- DependencyInjection/Configuration.php | 206 +++++++++--------- DependencyInjection/FrameworkExtension.php | 14 +- KernelBrowser.php | 2 +- Resources/bin/check-unused-known-tags.php | 4 +- Secrets/SodiumVault.php | 2 +- .../AnnotationsCacheWarmerTest.php | 4 +- .../CacheWarmer/SerializerCacheWarmerTest.php | 2 +- .../CacheWarmer/ValidatorCacheWarmerTest.php | 2 +- .../Command/AboutCommand/AboutCommandTest.php | 8 +- .../CacheClearCommandTest.php | 2 +- .../CachePoolInvalidateTagsCommandTest.php | 2 +- .../EventDispatcherDebugCommandTest.php | 4 +- Tests/Command/RouterMatchCommandTest.php | 2 +- Tests/Command/TranslationDebugCommandTest.php | 6 +- ...TranslationUpdateCommandCompletionTest.php | 4 +- .../Command/TranslationUpdateCommandTest.php | 8 +- Tests/Console/ApplicationTest.php | 8 +- Tests/Console/Descriptor/ObjectsProvider.php | 4 +- Tests/Controller/AbstractControllerTest.php | 2 +- .../Compiler/UnusedTagsPassTest.php | 2 +- .../DependencyInjection/ConfigurationTest.php | 2 +- .../FrameworkExtensionTestCase.php | 12 +- .../PhpFrameworkExtensionTest.php | 20 +- .../KernelTestCaseFreshCacheTest.php | 2 +- Tests/Routing/RouterTest.php | 2 +- 44 files changed, 185 insertions(+), 185 deletions(-) diff --git a/CacheWarmer/AbstractPhpFileCacheWarmer.php b/CacheWarmer/AbstractPhpFileCacheWarmer.php index 98c281276..c77232060 100644 --- a/CacheWarmer/AbstractPhpFileCacheWarmer.php +++ b/CacheWarmer/AbstractPhpFileCacheWarmer.php @@ -54,7 +54,7 @@ public function warmUp(string $cacheDir /* , string $buildDir = null */): array // the ArrayAdapter stores the values serialized // to avoid mutation of the data after it was written to the cache // so here we un-serialize the values first - $values = array_map(fn ($val) => null !== $val ? unserialize($val) : null, $arrayAdapter->getValues()); + $values = array_map(static fn ($val) => null !== $val ? unserialize($val) : null, $arrayAdapter->getValues()); return $this->warmUpPhpArrayAdapter(new PhpArrayAdapter($this->phpArrayFile, new NullAdapter()), $values); } diff --git a/CacheWarmer/AnnotationsCacheWarmer.php b/CacheWarmer/AnnotationsCacheWarmer.php index 20533bb60..a29739257 100644 --- a/CacheWarmer/AnnotationsCacheWarmer.php +++ b/CacheWarmer/AnnotationsCacheWarmer.php @@ -78,7 +78,7 @@ protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter /* , st protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values): array { // make sure we don't cache null values - $values = array_filter($values, fn ($val) => null !== $val); + $values = array_filter($values, static fn ($val) => null !== $val); return parent::warmUpPhpArrayAdapter($phpArrayAdapter, $values); } diff --git a/CacheWarmer/ConfigBuilderCacheWarmer.php b/CacheWarmer/ConfigBuilderCacheWarmer.php index c43fc8af1..441ee457e 100644 --- a/CacheWarmer/ConfigBuilderCacheWarmer.php +++ b/CacheWarmer/ConfigBuilderCacheWarmer.php @@ -56,7 +56,7 @@ public function warmUp(string $cacheDir /* , string $buildDir = null */): array if ($this->kernel instanceof Kernel) { /** @var ContainerBuilder $container */ - $container = \Closure::bind(function (Kernel $kernel) { + $container = \Closure::bind(static function (Kernel $kernel) { $containerBuilder = $kernel->getContainerBuilder(); $kernel->prepareContainer($containerBuilder); diff --git a/CacheWarmer/ValidatorCacheWarmer.php b/CacheWarmer/ValidatorCacheWarmer.php index 224e90985..cf92a0630 100644 --- a/CacheWarmer/ValidatorCacheWarmer.php +++ b/CacheWarmer/ValidatorCacheWarmer.php @@ -70,7 +70,7 @@ protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter /* , st protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values): array { // make sure we don't cache null values - $values = array_filter($values, fn ($val) => null !== $val); + $values = array_filter($values, static fn ($val) => null !== $val); return parent::warmUpPhpArrayAdapter($phpArrayAdapter, $values); } diff --git a/Command/AbstractConfigCommand.php b/Command/AbstractConfigCommand.php index ac2c5c9e6..d4e4c9145 100644 --- a/Command/AbstractConfigCommand.php +++ b/Command/AbstractConfigCommand.php @@ -38,7 +38,7 @@ protected function listBundles(OutputInterface|StyleInterface $output) $rows = []; $bundles = $this->getApplication()->getKernel()->getBundles(); - usort($bundles, fn ($bundleA, $bundleB) => strcmp($bundleA->getName(), $bundleB->getName())); + usort($bundles, static fn ($bundleA, $bundleB) => strcmp($bundleA->getName(), $bundleB->getName())); foreach ($bundles as $bundle) { $extension = $bundle->getContainerExtension(); diff --git a/Command/AssetsInstallCommand.php b/Command/AssetsInstallCommand.php index e35b2f70e..3030dfe5e 100644 --- a/Command/AssetsInstallCommand.php +++ b/Command/AssetsInstallCommand.php @@ -243,7 +243,7 @@ private function symlink(string $originDir, string $targetDir, bool $relative = */ private function hardCopy(string $originDir, string $targetDir): string { - $this->filesystem->mkdir($targetDir, 0777); + $this->filesystem->mkdir($targetDir, 0o777); // We use a custom iterator to ignore VCS files $this->filesystem->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(false)->in($originDir)); diff --git a/Command/CachePoolListCommand.php b/Command/CachePoolListCommand.php index 0014742e2..281913153 100644 --- a/Command/CachePoolListCommand.php +++ b/Command/CachePoolListCommand.php @@ -51,7 +51,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); - $io->table(['Pool name'], array_map(fn ($pool) => [$pool], $this->poolNames)); + $io->table(['Pool name'], array_map(static fn ($pool) => [$pool], $this->poolNames)); return 0; } diff --git a/Command/ConfigDumpReferenceCommand.php b/Command/ConfigDumpReferenceCommand.php index dea6f5746..b083c133e 100644 --- a/Command/ConfigDumpReferenceCommand.php +++ b/Command/ConfigDumpReferenceCommand.php @@ -39,7 +39,7 @@ class ConfigDumpReferenceCommand extends AbstractConfigCommand { protected function configure(): void { - $commentedHelpFormats = array_map(fn ($format) => \sprintf('%s', $format), $this->getAvailableFormatOptions()); + $commentedHelpFormats = array_map(static fn ($format) => \sprintf('%s', $format), $this->getAvailableFormatOptions()); $helpFormats = implode('", "', $commentedHelpFormats); $this diff --git a/Command/DebugAutowiringCommand.php b/Command/DebugAutowiringCommand.php index fdf98f908..5ef1c9109 100644 --- a/Command/DebugAutowiringCommand.php +++ b/Command/DebugAutowiringCommand.php @@ -75,7 +75,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($search = $input->getArgument('search')) { $searchNormalized = preg_replace('/[^a-zA-Z0-9\x7f-\xff $]++/', '', $search); - $serviceIds = array_filter($serviceIds, fn ($serviceId) => false !== stripos(str_replace('\\', '', $serviceId), $searchNormalized) && !str_starts_with($serviceId, '.')); + $serviceIds = array_filter($serviceIds, static fn ($serviceId) => false !== stripos(str_replace('\\', '', $serviceId), $searchNormalized) && !str_starts_with($serviceId, '.')); if (!$serviceIds) { $errorIo->error(\sprintf('No autowirable classes or interfaces found matching "%s"', $search)); diff --git a/Command/SecretsListCommand.php b/Command/SecretsListCommand.php index a27e0056d..10f9d758f 100644 --- a/Command/SecretsListCommand.php +++ b/Command/SecretsListCommand.php @@ -75,7 +75,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $rows = []; $dump = new Dumper($output); - $dump = fn ($v) => null === $v ? '******' : $dump($v); + $dump = static fn ($v) => null === $v ? '******' : $dump($v); foreach ($secrets as $name => $value) { $rows[$name] = [$name, $dump($value)]; diff --git a/Command/TranslationUpdateCommand.php b/Command/TranslationUpdateCommand.php index 8065a147f..9679001bb 100644 --- a/Command/TranslationUpdateCommand.php +++ b/Command/TranslationUpdateCommand.php @@ -228,8 +228,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int $list = array_merge( array_diff($allKeys, $newKeys), - array_map(fn ($id) => \sprintf('%s', $id), $newKeys), - array_map(fn ($id) => \sprintf('%s', $id), array_keys($operation->getObsoleteMessages($domain))) + array_map(static fn ($id) => \sprintf('%s', $id), $newKeys), + array_map(static fn ($id) => \sprintf('%s', $id), array_keys($operation->getObsoleteMessages($domain))) ); $domainMessagesCount = \count($list); diff --git a/Command/XliffLintCommand.php b/Command/XliffLintCommand.php index 9bbe39db1..02cf0f527 100644 --- a/Command/XliffLintCommand.php +++ b/Command/XliffLintCommand.php @@ -36,7 +36,7 @@ public function __construct() return $default($directory); }; - $isReadableProvider = fn ($fileOrDirectory, $default) => str_starts_with($fileOrDirectory, '@') || $default($fileOrDirectory); + $isReadableProvider = static fn ($fileOrDirectory, $default) => str_starts_with($fileOrDirectory, '@') || $default($fileOrDirectory); parent::__construct(null, $directoryIteratorProvider, $isReadableProvider); } diff --git a/Command/YamlLintCommand.php b/Command/YamlLintCommand.php index 5948add7c..b2ab87423 100644 --- a/Command/YamlLintCommand.php +++ b/Command/YamlLintCommand.php @@ -35,7 +35,7 @@ public function __construct() return $default($directory); }; - $isReadableProvider = fn ($fileOrDirectory, $default) => str_starts_with($fileOrDirectory, '@') || $default($fileOrDirectory); + $isReadableProvider = static fn ($fileOrDirectory, $default) => str_starts_with($fileOrDirectory, '@') || $default($fileOrDirectory); parent::__construct(null, $directoryIteratorProvider, $isReadableProvider); } diff --git a/Console/Descriptor/Descriptor.php b/Console/Descriptor/Descriptor.php index af5c3b10a..455e61588 100644 --- a/Console/Descriptor/Descriptor.php +++ b/Console/Descriptor/Descriptor.php @@ -243,7 +243,7 @@ protected function sortTaggedServicesByPriority(array $services): array } } } - uasort($maxPriority, fn ($a, $b) => $b <=> $a); + uasort($maxPriority, static fn ($a, $b) => $b <=> $a); return array_keys($maxPriority); } @@ -260,7 +260,7 @@ protected function sortTagsByPriority(array $tags): array protected function sortByPriority(array $tag): array { - usort($tag, fn ($a, $b) => ($b['priority'] ?? 0) <=> ($a['priority'] ?? 0)); + usort($tag, static fn ($a, $b) => ($b['priority'] ?? 0) <=> ($a['priority'] ?? 0)); return $tag; } @@ -353,7 +353,7 @@ protected function getServiceEdges(ContainerBuilder $container, string $serviceI { try { return array_values(array_unique(array_map( - fn (ServiceReferenceGraphEdge $edge) => $edge->getSourceNode()->getId(), + static fn (ServiceReferenceGraphEdge $edge) => $edge->getSourceNode()->getId(), $container->getCompiler()->getServiceReferenceGraph()->getNode($serviceId)->getInEdges() ))); } catch (InvalidArgumentException $exception) { diff --git a/Console/Descriptor/JsonDescriptor.php b/Console/Descriptor/JsonDescriptor.php index 344db992f..927497c62 100644 --- a/Console/Descriptor/JsonDescriptor.php +++ b/Console/Descriptor/JsonDescriptor.php @@ -332,7 +332,7 @@ private function getEventDispatcherListenersData(EventDispatcherInterface $event $data[] = $l; } } else { - $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(fn ($event) => $eventDispatcher->getListeners($event), $options['events'])) : $eventDispatcher->getListeners(); + $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(static fn ($event) => $eventDispatcher->getListeners($event), $options['events'])) : $eventDispatcher->getListeners(); ksort($registeredListeners); foreach ($registeredListeners as $eventListened => $eventListeners) { diff --git a/Console/Descriptor/MarkdownDescriptor.php b/Console/Descriptor/MarkdownDescriptor.php index c84fd5b1c..3b647a8ad 100644 --- a/Console/Descriptor/MarkdownDescriptor.php +++ b/Console/Descriptor/MarkdownDescriptor.php @@ -327,7 +327,7 @@ protected function describeEventDispatcherListeners(EventDispatcherInterface $ev $registeredListeners = $eventDispatcher->getListeners($event); } else { // Try to see if "events" exists - $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(fn ($event) => $eventDispatcher->getListeners($event), $options['events'])) : $eventDispatcher->getListeners(); + $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(static fn ($event) => $eventDispatcher->getListeners($event), $options['events'])) : $eventDispatcher->getListeners(); } $this->write(\sprintf('# %s', $title)."\n"); diff --git a/Console/Descriptor/TextDescriptor.php b/Console/Descriptor/TextDescriptor.php index 9e05f90e3..6ab0e2130 100644 --- a/Console/Descriptor/TextDescriptor.php +++ b/Console/Descriptor/TextDescriptor.php @@ -531,7 +531,7 @@ protected function describeEventDispatcherListeners(EventDispatcherInterface $ev } else { $title .= ' Grouped by Event'; // Try to see if "events" exists - $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(fn ($event) => $eventDispatcher->getListeners($event), $options['events'])) : $eventDispatcher->getListeners(); + $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(static fn ($event) => $eventDispatcher->getListeners($event), $options['events'])) : $eventDispatcher->getListeners(); } $options['output']->title($title); diff --git a/Console/Descriptor/XmlDescriptor.php b/Console/Descriptor/XmlDescriptor.php index fb4ab11a6..a9a95fa07 100644 --- a/Console/Descriptor/XmlDescriptor.php +++ b/Console/Descriptor/XmlDescriptor.php @@ -510,7 +510,7 @@ private function getEventDispatcherListenersDocument(EventDispatcherInterface $e $this->appendEventListenerDocument($eventDispatcher, $event, $eventDispatcherXML, $registeredListeners); } else { // Try to see if "events" exists - $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(fn ($event) => $eventDispatcher->getListeners($event), $options['events'])) : $eventDispatcher->getListeners(); + $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(static fn ($event) => $eventDispatcher->getListeners($event), $options['events'])) : $eventDispatcher->getListeners(); ksort($registeredListeners); foreach ($registeredListeners as $eventListened => $eventListeners) { diff --git a/Controller/AbstractController.php b/Controller/AbstractController.php index b47449816..aaa9f258b 100644 --- a/Controller/AbstractController.php +++ b/Controller/AbstractController.php @@ -293,7 +293,7 @@ protected function stream(string $view, array $parameters = [], ?StreamedRespons $twig = $this->container->get('twig'); - $callback = function () use ($twig, $view, $parameters) { + $callback = static function () use ($twig, $view, $parameters) { $twig->display($view, $parameters); }; diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 3d3523d47..2e7667532 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -75,15 +75,15 @@ public function getConfigTreeBuilder(): TreeBuilder $rootNode ->beforeNormalization() - ->ifTrue(fn ($v) => !isset($v['assets']) && isset($v['templating']) && class_exists(Package::class)) - ->then(function ($v) { + ->ifTrue(static fn ($v) => !isset($v['assets']) && isset($v['templating']) && class_exists(Package::class)) + ->then(static function ($v) { $v['assets'] = []; return $v; }) ->end() ->validate() - ->always(function ($v) { + ->always(static function ($v) { if (!isset($v['http_method_override'])) { trigger_deprecation('symfony/framework-bundle', '6.1', 'Not setting the "framework.http_method_override" config option is deprecated. It will default to "false" in 7.0.'); @@ -123,7 +123,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->prototype('scalar')->end() ->end() ->arrayNode('trusted_hosts') - ->beforeNormalization()->ifString()->then(fn ($v) => [$v])->end() + ->beforeNormalization()->ifString()->then(static fn ($v) => [$v])->end() ->prototype('scalar')->end() ->end() ->scalarNode('trusted_proxies')->end() @@ -131,7 +131,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->fixXmlConfig('trusted_header') ->performNoDeepMerging() ->defaultValue(['x-forwarded-for', 'x-forwarded-port', 'x-forwarded-proto']) - ->beforeNormalization()->ifString()->then(fn ($v) => $v ? array_map('trim', explode(',', $v)) : [])->end() + ->beforeNormalization()->ifString()->then(static fn ($v) => $v ? array_map('trim', explode(',', $v)) : [])->end() ->enumPrototype() ->values([ 'forwarded', @@ -153,7 +153,7 @@ public function getConfigTreeBuilder(): TreeBuilder return ContainerBuilder::willBeAvailable($package, $class, $parentPackages); }; - $enableIfStandalone = fn (string $package, string $class) => !class_exists(FullStack::class) && $willBeAvailable($package, $class) ? 'canBeDisabled' : 'canBeEnabled'; + $enableIfStandalone = static fn (string $package, string $class) => !class_exists(FullStack::class) && $willBeAvailable($package, $class) ? 'canBeDisabled' : 'canBeEnabled'; $this->addCsrfSection($rootNode); $this->addFormSection($rootNode, $enableIfStandalone); @@ -420,12 +420,12 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void ->arrayNode('supports') ->beforeNormalization() ->ifString() - ->then(fn ($v) => [$v]) + ->then(static fn ($v) => [$v]) ->end() ->prototype('scalar') ->cannotBeEmpty() ->validate() - ->ifTrue(fn ($v) => !class_exists($v) && !interface_exists($v, false)) + ->ifTrue(static fn ($v) => !class_exists($v) && !interface_exists($v, false)) ->thenInvalid('The supported class or interface "%s" does not exist.') ->end() ->end() @@ -441,7 +441,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void ->variableNode('events_to_dispatch') ->defaultValue(null) ->validate() - ->ifTrue(function ($v) { + ->ifTrue(static function ($v) { if (null === $v) { return false; } @@ -468,7 +468,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void ->arrayNode('places') ->beforeNormalization() ->always() - ->then(function ($places) { + ->then(static function ($places) { if (!\is_array($places)) { throw new InvalidConfigurationException('The "places" option must be an array in workflow configuration.'); } @@ -545,7 +545,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void ->performNoDeepMerging() ->beforeNormalization() ->ifString() - ->then(fn ($v) => [$v]) + ->then(static fn ($v) => [$v]) ->end() ->requiresAtLeastOneElement() ->prototype('scalar') @@ -556,7 +556,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void ->performNoDeepMerging() ->beforeNormalization() ->ifString() - ->then(fn ($v) => [$v]) + ->then(static fn ($v) => [$v]) ->end() ->requiresAtLeastOneElement() ->prototype('scalar') @@ -584,20 +584,20 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void ->end() ->end() ->validate() - ->ifTrue(function ($v) { + ->ifTrue(static function ($v) { return $v['supports'] && isset($v['support_strategy']); }) ->thenInvalid('"supports" and "support_strategy" cannot be used together.') ->end() ->validate() - ->ifTrue(function ($v) { + ->ifTrue(static function ($v) { return !$v['supports'] && !isset($v['support_strategy']); }) ->thenInvalid('"supports" or "support_strategy" should be configured.') ->end() ->beforeNormalization() ->always() - ->then(function ($values) { + ->then(static function ($values) { // Special case to deal with XML when the user wants an empty array if (\array_key_exists('event_to_dispatch', $values) && null === $values['event_to_dispatch']) { $values['events_to_dispatch'] = []; @@ -652,7 +652,7 @@ private function addSessionSection(ArrayNodeDefinition $rootNode): void { $rootNode ->validate() - ->always(function (array $v): array { + ->always(static function (array $v): array { if ($v['session']['enabled']) { if (!\array_key_exists('cookie_secure', $v['session'])) { trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.session.cookie_secure" config option is deprecated. It will default to "auto" in 7.0.'); @@ -685,7 +685,7 @@ private function addSessionSection(ArrayNodeDefinition $rootNode): void ->scalarNode('handler_id')->end() ->scalarNode('name') ->validate() - ->ifTrue(function ($v) { + ->ifTrue(static function ($v) { parse_str($v, $parsed); return implode('&', array_keys($parsed)) !== (string) $v; @@ -735,8 +735,8 @@ private function addRequestSection(ArrayNodeDefinition $rootNode): void ->useAttributeAsKey('name') ->prototype('array') ->beforeNormalization() - ->ifTrue(fn ($v) => \is_array($v) && isset($v['mime_type'])) - ->then(fn ($v) => $v['mime_type']) + ->ifTrue(static fn ($v) => \is_array($v) && isset($v['mime_type'])) + ->then(static fn ($v) => $v['mime_type']) ->end() ->beforeNormalization()->castToArray()->end() ->prototype('scalar')->end() @@ -773,19 +773,19 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode, callable $enabl ->end() ->end() ->validate() - ->ifTrue(function ($v) { + ->ifTrue(static function ($v) { return isset($v['version_strategy']) && isset($v['version']); }) ->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets".') ->end() ->validate() - ->ifTrue(function ($v) { + ->ifTrue(static function ($v) { return isset($v['version_strategy']) && isset($v['json_manifest_path']); }) ->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets".') ->end() ->validate() - ->ifTrue(function ($v) { + ->ifTrue(static function ($v) { return isset($v['version']) && isset($v['json_manifest_path']); }) ->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets".') @@ -805,8 +805,8 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode, callable $enabl ->scalarNode('version_strategy')->defaultNull()->end() ->scalarNode('version') ->beforeNormalization() - ->ifTrue(fn ($v) => '' === $v) - ->then(fn () => null) + ->ifTrue(static fn ($v) => '' === $v) + ->then(static fn () => null) ->end() ->end() ->scalarNode('version_format')->defaultNull()->end() @@ -819,19 +819,19 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode, callable $enabl ->end() ->end() ->validate() - ->ifTrue(function ($v) { + ->ifTrue(static function ($v) { return isset($v['version_strategy']) && isset($v['version']); }) ->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets" packages.') ->end() ->validate() - ->ifTrue(function ($v) { + ->ifTrue(static function ($v) { return isset($v['version_strategy']) && isset($v['json_manifest_path']); }) ->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets" packages.') ->end() ->validate() - ->ifTrue(function ($v) { + ->ifTrue(static function ($v) { return isset($v['version']) && isset($v['json_manifest_path']); }) ->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets" packages.') @@ -864,7 +864,7 @@ private function addAssetMapperSection(ArrayNodeDefinition $rootNode, callable $ ->useAttributeAsKey('namespace') ->beforeNormalization() ->always() - ->then(function ($v) { + ->then(static function ($v) { $result = []; foreach ($v as $key => $item) { // "dir" => "namespace" @@ -963,7 +963,7 @@ private function addTranslatorSection(ArrayNodeDefinition $rootNode, callable $e ->children() ->arrayNode('fallbacks') ->info('Defaults to the value of "default_locale".') - ->beforeNormalization()->ifString()->then(fn ($v) => [$v])->end() + ->beforeNormalization()->ifString()->then(static fn ($v) => [$v])->end() ->prototype('scalar')->end() ->defaultValue([]) ->end() @@ -1024,7 +1024,7 @@ private function addValidationSection(ArrayNodeDefinition $rootNode, callable $e { $rootNode ->validate() - ->always(function ($v) { + ->always(static function ($v) { if ($v['validation']['enabled'] && !\array_key_exists('email_validation_mode', $v['validation'])) { trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.validation.email_validation_mode" config option is deprecated. It will default to "html5" in 7.0.'); } @@ -1035,8 +1035,8 @@ private function addValidationSection(ArrayNodeDefinition $rootNode, callable $e ->children() ->arrayNode('validation') ->beforeNormalization() - ->ifTrue(fn ($v) => isset($v['enable_annotations'])) - ->then(function ($v) { + ->ifTrue(static fn ($v) => isset($v['enable_annotations'])) + ->then(static function ($v) { trigger_deprecation('symfony/framework-bundle', '6.4', 'Option "enable_annotations" at "framework.validation" is deprecated. Use the "enable_attributes" option instead.'); if (isset($v['enable_attributes'])) { @@ -1093,7 +1093,7 @@ private function addValidationSection(ArrayNodeDefinition $rootNode, callable $e ->normalizeKeys(false) ->beforeNormalization() ->ifArray() - ->then(function (array $values): array { + ->then(static function (array $values): array { foreach ($values as $k => $v) { if (isset($v['service'])) { continue; @@ -1159,8 +1159,8 @@ private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $e ->children() ->arrayNode('serializer') ->beforeNormalization() - ->ifTrue(fn ($v) => isset($v['enable_annotations'])) - ->then(function ($v) { + ->ifTrue(static fn ($v) => isset($v['enable_annotations'])) + ->then(static function ($v) { trigger_deprecation('symfony/framework-bundle', '6.4', 'Option "enable_annotations" at "framework.serializer" is deprecated. Use the "enable_attributes" option instead.'); if (isset($v['enable_attributes'])) { @@ -1193,7 +1193,7 @@ private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $e ->normalizeKeys(false) ->validate() ->ifTrue(fn () => $this->debug && class_exists(JsonParser::class)) - ->then(fn (array $v) => $v + [JsonDecode::DETAILED_ERROR_MESSAGES => true]) + ->then(static fn (array $v) => $v + [JsonDecode::DETAILED_ERROR_MESSAGES => true]) ->end() ->defaultValue([]) ->prototype('variable')->end() @@ -1269,7 +1269,7 @@ private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBe ->prototype('array') ->fixXmlConfig('adapter') ->beforeNormalization() - ->ifTrue(fn ($v) => isset($v['provider']) && \is_array($v['adapters'] ?? $v['adapter'] ?? null) && 1 < \count($v['adapters'] ?? $v['adapter'])) + ->ifTrue(static fn ($v) => isset($v['provider']) && \is_array($v['adapters'] ?? $v['adapter'] ?? null) && 1 < \count($v['adapters'] ?? $v['adapter'])) ->thenInvalid('Pool cannot have a "provider" while more than one adapter is defined') ->end() ->children() @@ -1278,7 +1278,7 @@ private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBe ->info('One or more adapters to chain for creating the pool, defaults to "cache.app".') ->beforeNormalization()->castToArray()->end() ->beforeNormalization() - ->always()->then(function ($values) { + ->always()->then(static function ($values) { if ([0] === array_keys($values) && \is_array($values[0])) { return $values[0]; } @@ -1317,7 +1317,7 @@ private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBe ->end() ->end() ->validate() - ->ifTrue(fn ($v) => isset($v['cache.app']) || isset($v['cache.system'])) + ->ifTrue(static fn ($v) => isset($v['cache.app']) || isset($v['cache.system'])) ->thenInvalid('"cache.app" and "cache.system" are reserved names') ->end() ->end() @@ -1352,7 +1352,7 @@ private function addPhpErrorsSection(ArrayNodeDefinition $rootNode): void ->treatNullLike($this->debug) ->beforeNormalization() ->ifArray() - ->then(function (array $v): array { + ->then(static function (array $v): array { if (!($v[0]['type'] ?? false)) { return $v; } @@ -1368,7 +1368,7 @@ private function addPhpErrorsSection(ArrayNodeDefinition $rootNode): void }) ->end() ->validate() - ->ifTrue(fn ($v) => !(\is_int($v) || \is_bool($v) || \is_array($v))) + ->ifTrue(static fn ($v) => !(\is_int($v) || \is_bool($v) || \is_array($v))) ->thenInvalid('The "php_errors.log" parameter should be either an integer, a boolean, or an array') ->end() ->end() @@ -1396,7 +1396,7 @@ private function addExceptionsSection(ArrayNodeDefinition $rootNode): void ->beforeNormalization() // Handle legacy XML configuration ->ifArray() - ->then(function (array $v): array { + ->then(static function (array $v): array { if (!\array_key_exists('exception', $v)) { return $v; } @@ -1419,7 +1419,7 @@ private function addExceptionsSection(ArrayNodeDefinition $rootNode): void ->scalarNode('log_level') ->info('The level of log message. Null to let Symfony decide.') ->validate() - ->ifTrue(fn ($v) => null !== $v && !\in_array($v, $logLevels, true)) + ->ifTrue(static fn ($v) => null !== $v && !\in_array($v, $logLevels, true)) ->thenInvalid(\sprintf('The log level is not valid. Pick one among "%s".', implode('", "', $logLevels))) ->end() ->defaultNull() @@ -1427,11 +1427,11 @@ private function addExceptionsSection(ArrayNodeDefinition $rootNode): void ->scalarNode('status_code') ->info('The status code of the response. Null or 0 to let Symfony decide.') ->beforeNormalization() - ->ifTrue(fn ($v) => 0 === $v) - ->then(fn ($v) => null) + ->ifTrue(static fn ($v) => 0 === $v) + ->then(static fn ($v) => null) ->end() ->validate() - ->ifTrue(fn ($v) => null !== $v && ($v < 100 || $v > 599)) + ->ifTrue(static fn ($v) => null !== $v && ($v < 100 || $v > 599)) ->thenInvalid('The status code is not valid. Pick a value between 100 and 599.') ->end() ->defaultNull() @@ -1451,15 +1451,15 @@ private function addLockSection(ArrayNodeDefinition $rootNode, callable $enableI ->info('Lock configuration') ->{$enableIfStandalone('symfony/lock', Lock::class)}() ->beforeNormalization() - ->ifString()->then(fn ($v) => ['enabled' => true, 'resources' => $v]) + ->ifString()->then(static fn ($v) => ['enabled' => true, 'resources' => $v]) ->end() ->beforeNormalization() - ->ifTrue(fn ($v) => \is_array($v) && !isset($v['enabled'])) - ->then(fn ($v) => $v + ['enabled' => true]) + ->ifTrue(static fn ($v) => \is_array($v) && !isset($v['enabled'])) + ->then(static fn ($v) => $v + ['enabled' => true]) ->end() ->beforeNormalization() - ->ifTrue(fn ($v) => \is_array($v) && !isset($v['resources']) && !isset($v['resource'])) - ->then(function ($v) { + ->ifTrue(static fn ($v) => \is_array($v) && !isset($v['resources']) && !isset($v['resource'])) + ->then(static function ($v) { $e = $v['enabled']; unset($v['enabled']); @@ -1468,7 +1468,7 @@ private function addLockSection(ArrayNodeDefinition $rootNode, callable $enableI ->end() ->addDefaultsIfNotSet() ->validate() - ->ifTrue(fn ($config) => $config['enabled'] && !$config['resources']) + ->ifTrue(static fn ($config) => $config['enabled'] && !$config['resources']) ->thenInvalid('At least one resource must be defined.') ->end() ->fixXmlConfig('resource') @@ -1478,11 +1478,11 @@ private function addLockSection(ArrayNodeDefinition $rootNode, callable $enableI ->useAttributeAsKey('name') ->defaultValue(['default' => [class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphore' : 'flock']]) ->beforeNormalization() - ->ifString()->then(fn ($v) => ['default' => $v]) + ->ifString()->then(static fn ($v) => ['default' => $v]) ->end() ->beforeNormalization() - ->ifTrue(fn ($v) => \is_array($v) && array_is_list($v)) - ->then(function ($v) { + ->ifTrue(static fn ($v) => \is_array($v) && array_is_list($v)) + ->then(static function ($v) { $resources = []; foreach ($v as $resource) { $resources[] = \is_array($resource) && isset($resource['name']) @@ -1496,7 +1496,7 @@ private function addLockSection(ArrayNodeDefinition $rootNode, callable $enableI ->end() ->prototype('array') ->performNoDeepMerging() - ->beforeNormalization()->ifString()->then(fn ($v) => [$v])->end() + ->beforeNormalization()->ifString()->then(static fn ($v) => [$v])->end() ->prototype('scalar')->end() ->end() ->end() @@ -1514,15 +1514,15 @@ private function addSemaphoreSection(ArrayNodeDefinition $rootNode, callable $en ->info('Semaphore configuration') ->{$enableIfStandalone('symfony/semaphore', Semaphore::class)}() ->beforeNormalization() - ->ifString()->then(fn ($v) => ['enabled' => true, 'resources' => $v]) + ->ifString()->then(static fn ($v) => ['enabled' => true, 'resources' => $v]) ->end() ->beforeNormalization() - ->ifTrue(fn ($v) => \is_array($v) && !isset($v['enabled'])) - ->then(fn ($v) => $v + ['enabled' => true]) + ->ifTrue(static fn ($v) => \is_array($v) && !isset($v['enabled'])) + ->then(static fn ($v) => $v + ['enabled' => true]) ->end() ->beforeNormalization() - ->ifTrue(fn ($v) => \is_array($v) && !isset($v['resources']) && !isset($v['resource'])) - ->then(function ($v) { + ->ifTrue(static fn ($v) => \is_array($v) && !isset($v['resources']) && !isset($v['resource'])) + ->then(static function ($v) { $e = $v['enabled']; unset($v['enabled']); @@ -1537,11 +1537,11 @@ private function addSemaphoreSection(ArrayNodeDefinition $rootNode, callable $en ->useAttributeAsKey('name') ->requiresAtLeastOneElement() ->beforeNormalization() - ->ifString()->then(fn ($v) => ['default' => $v]) + ->ifString()->then(static fn ($v) => ['default' => $v]) ->end() ->beforeNormalization() - ->ifTrue(fn ($v) => \is_array($v) && array_is_list($v)) - ->then(function ($v) { + ->ifTrue(static fn ($v) => \is_array($v) && array_is_list($v)) + ->then(static function ($v) { $resources = []; foreach ($v as $resource) { $resources[] = \is_array($resource) && isset($resource['name']) @@ -1583,12 +1583,12 @@ private function addMessengerSection(ArrayNodeDefinition $rootNode, callable $en ->fixXmlConfig('transport') ->fixXmlConfig('bus', 'buses') ->validate() - ->ifTrue(fn ($v) => isset($v['buses']) && \count($v['buses']) > 1 && null === $v['default_bus']) + ->ifTrue(static fn ($v) => isset($v['buses']) && \count($v['buses']) > 1 && null === $v['default_bus']) ->thenInvalid('You must specify the "default_bus" if you define more than one bus.') ->end() ->validate() - ->ifTrue(fn ($v) => isset($v['buses']) && null !== $v['default_bus'] && !isset($v['buses'][$v['default_bus']])) - ->then(fn ($v) => throw new InvalidConfigurationException(\sprintf('The specified default bus "%s" is not configured. Available buses are "%s".', $v['default_bus'], implode('", "', array_keys($v['buses']))))) + ->ifTrue(static fn ($v) => isset($v['buses']) && null !== $v['default_bus'] && !isset($v['buses'][$v['default_bus']])) + ->then(static fn ($v) => throw new InvalidConfigurationException(\sprintf('The specified default bus "%s" is not configured. Available buses are "%s".', $v['default_bus'], implode('", "', array_keys($v['buses']))))) ->end() ->children() ->arrayNode('routing') @@ -1596,7 +1596,7 @@ private function addMessengerSection(ArrayNodeDefinition $rootNode, callable $en ->useAttributeAsKey('message_class') ->beforeNormalization() ->always() - ->then(function ($config) { + ->then(static function ($config) { if (!\is_array($config)) { return []; } @@ -1613,7 +1613,7 @@ private function addMessengerSection(ArrayNodeDefinition $rootNode, callable $en ]; } else { $newConfig[$v['message-class']]['senders'] = array_map( - function ($a) { + static function ($a) { return \is_string($a) ? $a : $a['service']; }, array_values($v['sender']) @@ -1662,7 +1662,7 @@ function ($a) { ->arrayPrototype() ->beforeNormalization() ->ifString() - ->then(function (string $dsn) { + ->then(static function (string $dsn) { return ['dsn' => $dsn]; }) ->end() @@ -1684,7 +1684,7 @@ function ($a) { ->arrayNode('retry_strategy') ->addDefaultsIfNotSet() ->beforeNormalization() - ->always(function ($v) { + ->always(static function ($v) { if (isset($v['service']) && (isset($v['max_retries']) || isset($v['delay']) || isset($v['multiplier']) || isset($v['max_delay']))) { throw new \InvalidArgumentException('The "service" cannot be used along with the other "retry_strategy" options.'); } @@ -1716,7 +1716,7 @@ function ($a) { ->info('Reset container services after each message.') ->setDeprecated('symfony/framework-bundle', '6.1', 'Option "%node%" at "%path%" is deprecated. It does nothing and will be removed in version 7.0.') ->validate() - ->ifTrue(fn ($v) => true !== $v) + ->ifTrue(static fn ($v) => true !== $v) ->thenInvalid('The "framework.messenger.reset_on_message" configuration option can be set to "true" only. To prevent services resetting after each message you can set the "--no-reset" option in "messenger:consume" command.') ->end() ->end() @@ -1735,8 +1735,8 @@ function ($a) { ->children() ->arrayNode('default_middleware') ->beforeNormalization() - ->ifTrue(fn ($v) => \is_string($v) || \is_bool($v)) - ->then(fn ($v) => [ + ->ifTrue(static fn ($v) => \is_string($v) || \is_bool($v)) + ->then(static fn ($v) => [ 'enabled' => 'allow_no_handlers' === $v ? true : $v, 'allow_no_handlers' => 'allow_no_handlers' === $v, 'allow_no_senders' => true, @@ -1751,14 +1751,14 @@ function ($a) { ->arrayNode('middleware') ->performNoDeepMerging() ->beforeNormalization() - ->ifTrue(fn ($v) => \is_string($v) || (\is_array($v) && !\is_int(key($v)))) - ->then(fn ($v) => [$v]) + ->ifTrue(static fn ($v) => \is_string($v) || (\is_array($v) && !\is_int(key($v)))) + ->then(static fn ($v) => [$v]) ->end() ->defaultValue([]) ->arrayPrototype() ->beforeNormalization() ->always() - ->then(function ($middleware): array { + ->then(static function ($middleware): array { if (!\is_array($middleware)) { return ['id' => $middleware]; } @@ -1829,7 +1829,7 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $e ->{$enableIfStandalone('symfony/http-client', HttpClient::class)}() ->fixXmlConfig('scoped_client') ->beforeNormalization() - ->always(function ($config) { + ->always(static function ($config) { if (empty($config['scoped_clients']) || !\is_array($config['default_options']['retry_failed'] ?? null)) { return $config; } @@ -1876,7 +1876,7 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $e ->info('Associative array: domain => IP.') ->useAttributeAsKey('host') ->beforeNormalization() - ->always(function ($config) { + ->always(static function ($config) { if (!\is_array($config)) { return []; } @@ -1960,7 +1960,7 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $e ->fixXmlConfig('header') ->beforeNormalization() ->always() - ->then(function ($config) { + ->then(static function ($config) { if (!class_exists(HttpClient::class)) { throw new LogicException('HttpClient support cannot be enabled as the component is not installed. Try running "composer require symfony/http-client".'); } @@ -1969,11 +1969,11 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $e }) ->end() ->validate() - ->ifTrue(fn ($v) => !isset($v['scope']) && !isset($v['base_uri'])) + ->ifTrue(static fn ($v) => !isset($v['scope']) && !isset($v['base_uri'])) ->thenInvalid('Either "scope" or "base_uri" should be defined.') ->end() ->validate() - ->ifTrue(fn ($v) => !empty($v['query']) && !isset($v['base_uri'])) + ->ifTrue(static fn ($v) => !empty($v['query']) && !isset($v['base_uri'])) ->thenInvalid('"query" applies to "base_uri" but no base URI is defined.') ->end() ->children() @@ -1998,7 +1998,7 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $e ->info('Associative array of query string values merged with the base URI.') ->useAttributeAsKey('key') ->beforeNormalization() - ->always(function ($config) { + ->always(static function ($config) { if (!\is_array($config)) { return []; } @@ -2028,7 +2028,7 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $e ->info('Associative array: domain => IP.') ->useAttributeAsKey('host') ->beforeNormalization() - ->always(function ($config) { + ->always(static function ($config) { if (!\is_array($config)) { return []; } @@ -2119,7 +2119,7 @@ private function createHttpClientRetrySection(): ArrayNodeDefinition ->canBeEnabled() ->addDefaultsIfNotSet() ->beforeNormalization() - ->always(function ($v) { + ->always(static function ($v) { if (isset($v['retry_strategy']) && (isset($v['http_codes']) || isset($v['delay']) || isset($v['multiplier']) || isset($v['max_delay']) || isset($v['jitter']))) { throw new \InvalidArgumentException('The "retry_strategy" option cannot be used along with the "http_codes", "delay", "multiplier", "max_delay" or "jitter" options.'); } @@ -2160,7 +2160,7 @@ private function createHttpClientRetrySection(): ArrayNodeDefinition ->arrayNode('methods') ->beforeNormalization() ->ifArray() - ->then(fn ($v) => array_map('strtoupper', $v)) + ->then(static fn ($v) => array_map('strtoupper', $v)) ->end() ->prototype('scalar')->end() ->info('A list of HTTP methods that triggers a retry for this status code. When empty, all methods are retried') @@ -2186,7 +2186,7 @@ private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enabl ->info('Mailer configuration') ->{$enableIfStandalone('symfony/mailer', Mailer::class)}() ->validate() - ->ifTrue(fn ($v) => isset($v['dsn']) && \count($v['transports'])) + ->ifTrue(static fn ($v) => isset($v['dsn']) && \count($v['transports'])) ->thenInvalid('"dsn" and "transports" cannot be used together.') ->end() ->fixXmlConfig('transport') @@ -2207,7 +2207,7 @@ private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enabl ->performNoDeepMerging() ->beforeNormalization() ->ifArray() - ->then(fn ($v) => array_filter(array_values($v))) + ->then(static fn ($v) => array_filter(array_values($v))) ->end() ->prototype('scalar')->end() ->end() @@ -2219,8 +2219,8 @@ private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enabl ->prototype('array') ->normalizeKeys(false) ->beforeNormalization() - ->ifTrue(fn ($v) => !\is_array($v) || array_keys($v) !== ['value']) - ->then(fn ($v) => ['value' => $v]) + ->ifTrue(static fn ($v) => !\is_array($v) || array_keys($v) !== ['value']) + ->then(static fn ($v) => ['value' => $v]) ->end() ->children() ->variableNode('value')->end() @@ -2264,7 +2264,7 @@ private function addNotifierSection(ArrayNodeDefinition $rootNode, callable $ena ->arrayNode('channel_policy') ->useAttributeAsKey('name') ->prototype('array') - ->beforeNormalization()->ifString()->then(fn ($v) => [$v])->end() + ->beforeNormalization()->ifString()->then(static fn ($v) => [$v])->end() ->prototype('scalar')->end() ->end() ->end() @@ -2335,8 +2335,8 @@ private function addRateLimiterSection(ArrayNodeDefinition $rootNode, callable $ ->{$enableIfStandalone('symfony/rate-limiter', TokenBucketLimiter::class)}() ->fixXmlConfig('limiter') ->beforeNormalization() - ->ifTrue(fn ($v) => \is_array($v) && !isset($v['limiters']) && !isset($v['limiter'])) - ->then(function (array $v) { + ->ifTrue(static fn ($v) => \is_array($v) && !isset($v['limiters']) && !isset($v['limiter'])) + ->then(static function (array $v) { $newV = [ 'enabled' => $v['enabled'] ?? true, ]; @@ -2386,7 +2386,7 @@ private function addRateLimiterSection(ArrayNodeDefinition $rootNode, callable $ ->end() ->end() ->validate() - ->ifTrue(fn ($v) => 'no_limit' !== $v['policy'] && !isset($v['limit'])) + ->ifTrue(static fn ($v) => 'no_limit' !== $v['policy'] && !isset($v['limit'])) ->thenInvalid('A limit must be provided when using a policy different than "no_limit".') ->end() ->end() @@ -2401,7 +2401,7 @@ private function addUidSection(ArrayNodeDefinition $rootNode, callable $enableIf { $rootNode ->validate() - ->always(function ($v) { + ->always(static function ($v) { if ($v['uid']['enabled']) { if (!\array_key_exists('default_uuid_version', $v['uid'])) { trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.uid.default_uuid_version" config option is deprecated. It will default to "7" in 7.0.'); @@ -2485,10 +2485,10 @@ private function addHtmlSanitizerSection(ArrayNodeDefinition $rootNode, callable ->useAttributeAsKey('name') ->variablePrototype() ->beforeNormalization() - ->ifArray()->then(fn ($n) => $n['attribute'] ?? $n) + ->ifArray()->then(static fn ($n) => $n['attribute'] ?? $n) ->end() ->validate() - ->ifTrue(fn ($n): bool => !\is_string($n) && !\is_array($n)) + ->ifTrue(static fn ($n): bool => !\is_string($n) && !\is_array($n)) ->thenInvalid('The value must be either a string or an array of strings.') ->end() ->end() @@ -2497,7 +2497,7 @@ private function addHtmlSanitizerSection(ArrayNodeDefinition $rootNode, callable ->info('Configures elements as blocked. Blocked elements are elements the sanitizer should remove from the input, but retain their children.') ->beforeNormalization() ->ifString() - ->then(fn (string $n): array => (array) $n) + ->then(static fn (string $n): array => (array) $n) ->end() ->scalarPrototype()->end() ->end() @@ -2505,7 +2505,7 @@ private function addHtmlSanitizerSection(ArrayNodeDefinition $rootNode, callable ->info('Configures elements as dropped. Dropped elements are elements the sanitizer should remove from the input, including their children.') ->beforeNormalization() ->ifString() - ->then(fn (string $n): array => (array) $n) + ->then(static fn (string $n): array => (array) $n) ->end() ->scalarPrototype()->end() ->end() @@ -2515,7 +2515,7 @@ private function addHtmlSanitizerSection(ArrayNodeDefinition $rootNode, callable ->useAttributeAsKey('name') ->variablePrototype() ->beforeNormalization() - ->ifArray()->then(fn ($n) => $n['element'] ?? $n) + ->ifArray()->then(static fn ($n) => $n['element'] ?? $n) ->end() ->end() ->end() @@ -2525,7 +2525,7 @@ private function addHtmlSanitizerSection(ArrayNodeDefinition $rootNode, callable ->useAttributeAsKey('name') ->variablePrototype() ->beforeNormalization() - ->ifArray()->then(fn ($n) => $n['element'] ?? $n) + ->ifArray()->then(static fn ($n) => $n['element'] ?? $n) ->end() ->end() ->end() @@ -2551,7 +2551,7 @@ private function addHtmlSanitizerSection(ArrayNodeDefinition $rootNode, callable ->info('Allows only a given list of hosts to be used in links href attributes.') ->defaultValue(null) ->validate() - ->ifTrue(fn ($v) => !\is_array($v) && null !== $v) + ->ifTrue(static fn ($v) => !\is_array($v) && null !== $v) ->thenInvalid('The "allowed_link_hosts" parameter must be an array or null') ->end() ->end() @@ -2567,7 +2567,7 @@ private function addHtmlSanitizerSection(ArrayNodeDefinition $rootNode, callable ->info('Allows only a given list of hosts to be used in media source attributes (img, audio, video, ...).') ->defaultValue(null) ->validate() - ->ifTrue(fn ($v) => !\is_array($v) && null !== $v) + ->ifTrue(static fn ($v) => !\is_array($v) && null !== $v) ->thenInvalid('The "allowed_media_hosts" parameter must be an array or null') ->end() ->end() diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index ec962ff98..5bc39bf3d 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -1067,7 +1067,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $validator = new Workflow\Validator\WorkflowValidator(); } - $trs = array_map(fn (Reference $ref): Workflow\Transition => $container->get((string) $ref), $transitions); + $trs = array_map(static fn (Reference $ref): Workflow\Transition => $container->get((string) $ref), $transitions); $realDefinition = new Workflow\Definition($places, $trs, $initialMarking); $validator->validate($realDefinition, $name); @@ -1554,7 +1554,7 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder $finder = Finder::create() ->followLinks() ->files() - ->filter(fn (\SplFileInfo $file) => 2 <= substr_count($file->getBasename(), '.') && preg_match('/\.\w+$/', $file->getBasename())) + ->filter(static fn (\SplFileInfo $file) => 2 <= substr_count($file->getBasename(), '.') && preg_match('/\.\w+$/', $file->getBasename())) ->in($dir) ->sortByName() ; @@ -1577,7 +1577,7 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder 'resource_files' => $files, 'scanned_directories' => $scannedDirectories = array_merge($dirs, $nonExistingDirs), 'cache_vary' => [ - 'scanned_directories' => array_map(fn ($dir) => str_starts_with($dir, $projectDir.'/') ? substr($dir, 1 + \strlen($projectDir)) : $dir, $scannedDirectories), + 'scanned_directories' => array_map(static fn ($dir) => str_starts_with($dir, $projectDir.'/') ? substr($dir, 1 + \strlen($projectDir)) : $dir, $scannedDirectories), ], ] ); @@ -1720,7 +1720,7 @@ private function registerValidationConfiguration(array $config, ContainerBuilder private function registerValidatorMapping(ContainerBuilder $container, array $config, array &$files): void { - $fileRecorder = function ($extension, $path) use (&$files) { + $fileRecorder = static function ($extension, $path) use (&$files) { $files['yaml' === $extension ? 'yml' : $extension][] = $path; }; @@ -1810,7 +1810,7 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde $cacheService = 'annotations.filesystem_cache_adapter'; $cacheDir = $container->getParameterBag()->resolveValue($config['file_cache_dir']); - if (!is_dir($cacheDir) && false === @mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) { + if (!is_dir($cacheDir) && false === @mkdir($cacheDir, 0o777, true) && !is_dir($cacheDir)) { throw new \RuntimeException(\sprintf('Could not create cache directory "%s".', $cacheDir)); } @@ -1961,7 +1961,7 @@ interface_exists(CacheableSupportsMethodInterface::class) ? [new Reference('anno $serializerLoaders[] = $annotationLoader; } - $fileRecorder = function ($extension, $path) use (&$serializerLoaders) { + $fileRecorder = static function ($extension, $path) use (&$serializerLoaders) { $definition = new Definition(\in_array($extension, ['yaml', 'yml']) ? YamlFileLoader::class : XmlFileLoader::class, [$path]); $serializerLoaders[] = $definition; }; @@ -2344,7 +2344,7 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder } } - $failureTransportReferencesByTransportName = array_map(fn ($failureTransportName) => $senderReferences[$failureTransportName], $failureTransportsByName); + $failureTransportReferencesByTransportName = array_map(static fn ($failureTransportName) => $senderReferences[$failureTransportName], $failureTransportsByName); $messageToSendersMapping = []; foreach ($config['routing'] as $message => $messageConfiguration) { diff --git a/KernelBrowser.php b/KernelBrowser.php index f13332695..401ba26b2 100644 --- a/KernelBrowser.php +++ b/KernelBrowser.php @@ -142,7 +142,7 @@ public function loginUser(object $user, string $firewallContext = 'main'/* , arr $session->set('_security_'.$firewallContext, serialize($token)); $session->save(); - $domains = array_unique(array_map(fn (Cookie $cookie) => $cookie->getName() === $session->getName() ? $cookie->getDomain() : '', $this->getCookieJar()->all())) ?: ['']; + $domains = array_unique(array_map(static fn (Cookie $cookie) => $cookie->getName() === $session->getName() ? $cookie->getDomain() : '', $this->getCookieJar()->all())) ?: ['']; foreach ($domains as $domain) { $cookie = new Cookie($session->getName(), $session->getId(), null, null, $domain); $this->getCookieJar()->set($cookie); diff --git a/Resources/bin/check-unused-known-tags.php b/Resources/bin/check-unused-known-tags.php index 55658f5b1..5e020b051 100644 --- a/Resources/bin/check-unused-known-tags.php +++ b/Resources/bin/check-unused-known-tags.php @@ -13,11 +13,11 @@ throw new Exception('This script must be run from the command line.'); } -require dirname(__DIR__, 6).'/vendor/autoload.php'; +require \dirname(__DIR__, 6).'/vendor/autoload.php'; use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\UnusedTagsPassUtils; -$target = dirname(__DIR__, 2).'/DependencyInjection/Compiler/UnusedTagsPass.php'; +$target = \dirname(__DIR__, 2).'/DependencyInjection/Compiler/UnusedTagsPass.php'; $contents = file_get_contents($target); $contents = preg_replace('{private const KNOWN_TAGS = \[(.+?)\];}sm', "private const KNOWN_TAGS = [\n '".implode("',\n '", UnusedTagsPassUtils::getDefinedTags())."',\n ];", $contents); file_put_contents($target, $contents); diff --git a/Secrets/SodiumVault.php b/Secrets/SodiumVault.php index 1aa03ac51..c2a64db36 100644 --- a/Secrets/SodiumVault.php +++ b/Secrets/SodiumVault.php @@ -220,7 +220,7 @@ private function export(string $filename, string $data): void private function createSecretsDir(): void { - if ($this->secretsDir && !is_dir($this->secretsDir) && !@mkdir($this->secretsDir, 0777, true) && !is_dir($this->secretsDir)) { + if ($this->secretsDir && !is_dir($this->secretsDir) && !@mkdir($this->secretsDir, 0o777, true) && !is_dir($this->secretsDir)) { throw new \RuntimeException(\sprintf('Unable to create the secrets directory (%s).', $this->secretsDir)); } diff --git a/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php b/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php index bd3a60d8a..5f5fd0627 100644 --- a/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php +++ b/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php @@ -108,7 +108,7 @@ public function testClassAutoloadException() $this->expectDeprecation('Since symfony/framework-bundle 6.4: The "Symfony\Bundle\FrameworkBundle\CacheWarmer\AnnotationsCacheWarmer" class is deprecated without replacement.'); $warmer = new AnnotationsCacheWarmer(new AnnotationReader(), tempnam($this->cacheDir, __FUNCTION__)); - spl_autoload_register($classLoader = function ($class) use ($annotatedClass) { + spl_autoload_register($classLoader = static function ($class) use ($annotatedClass) { if ($class === $annotatedClass) { throw new \DomainException('This exception should be caught by the warmer.'); } @@ -155,7 +155,7 @@ public function testWarmupRemoveCacheMisses() ->onlyMethods(['doWarmUp']) ->getMock(); - $warmer->method('doWarmUp')->willReturnCallback(function ($cacheDir, ArrayAdapter $arrayAdapter) { + $warmer->method('doWarmUp')->willReturnCallback(static function ($cacheDir, ArrayAdapter $arrayAdapter) { $arrayAdapter->getItem('foo_miss'); $item = $arrayAdapter->getItem('bar_hit'); diff --git a/Tests/CacheWarmer/SerializerCacheWarmerTest.php b/Tests/CacheWarmer/SerializerCacheWarmerTest.php index 5feb0c8ec..b0ae324c6 100644 --- a/Tests/CacheWarmer/SerializerCacheWarmerTest.php +++ b/Tests/CacheWarmer/SerializerCacheWarmerTest.php @@ -81,7 +81,7 @@ public function testClassAutoloadException() $warmer = new SerializerCacheWarmer([new YamlFileLoader(__DIR__.'/../Fixtures/Serialization/Resources/does_not_exist.yaml')], tempnam(sys_get_temp_dir(), __FUNCTION__)); - spl_autoload_register($classLoader = function ($class) use ($mappedClass) { + spl_autoload_register($classLoader = static function ($class) use ($mappedClass) { if ($class === $mappedClass) { throw new \DomainException('This exception should be caught by the warmer.'); } diff --git a/Tests/CacheWarmer/ValidatorCacheWarmerTest.php b/Tests/CacheWarmer/ValidatorCacheWarmerTest.php index cc471e43f..49014f4b2 100644 --- a/Tests/CacheWarmer/ValidatorCacheWarmerTest.php +++ b/Tests/CacheWarmer/ValidatorCacheWarmerTest.php @@ -89,7 +89,7 @@ public function testClassAutoloadException() $validatorBuilder->addYamlMapping(__DIR__.'/../Fixtures/Validation/Resources/does_not_exist.yaml'); $warmer = new ValidatorCacheWarmer($validatorBuilder, tempnam(sys_get_temp_dir(), __FUNCTION__)); - spl_autoload_register($classloader = function ($class) use ($mappedClass) { + spl_autoload_register($classloader = static function ($class) use ($mappedClass) { if ($class === $mappedClass) { throw new \DomainException('This exception should be caught by the warmer.'); } diff --git a/Tests/Command/AboutCommand/AboutCommandTest.php b/Tests/Command/AboutCommand/AboutCommandTest.php index bcf3c7fe0..48c2e5312 100644 --- a/Tests/Command/AboutCommand/AboutCommandTest.php +++ b/Tests/Command/AboutCommand/AboutCommandTest.php @@ -34,7 +34,7 @@ public function testAboutWithReadableFiles() $this->fs->mkdir($kernel->getProjectDir()); $this->fs->dumpFile($kernel->getCacheDir().'/readable_file', 'The file content.'); - $this->fs->chmod($kernel->getCacheDir().'/readable_file', 0777); + $this->fs->chmod($kernel->getCacheDir().'/readable_file', 0o777); $tester = $this->createCommandTester($kernel); $ret = $tester->execute([]); @@ -43,7 +43,7 @@ public function testAboutWithReadableFiles() $this->assertStringContainsString('Cache directory', $tester->getDisplay()); $this->assertStringContainsString('Log directory', $tester->getDisplay()); - $this->fs->chmod($kernel->getCacheDir().'/readable_file', 0777); + $this->fs->chmod($kernel->getCacheDir().'/readable_file', 0o777); try { $this->fs->remove($kernel->getProjectDir()); @@ -62,7 +62,7 @@ public function testAboutWithUnreadableFiles() } $this->fs->dumpFile($kernel->getCacheDir().'/unreadable_file', 'The file content.'); - $this->fs->chmod($kernel->getCacheDir().'/unreadable_file', 0222); + $this->fs->chmod($kernel->getCacheDir().'/unreadable_file', 0o222); $tester = $this->createCommandTester($kernel); $ret = $tester->execute([]); @@ -71,7 +71,7 @@ public function testAboutWithUnreadableFiles() $this->assertStringContainsString('Cache directory', $tester->getDisplay()); $this->assertStringContainsString('Log directory', $tester->getDisplay()); - $this->fs->chmod($kernel->getCacheDir().'/unreadable_file', 0777); + $this->fs->chmod($kernel->getCacheDir().'/unreadable_file', 0o777); try { $this->fs->remove($kernel->getProjectDir()); diff --git a/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index 8decaa1a5..6dfb9c6fb 100644 --- a/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -121,7 +121,7 @@ public function testCacheIsWarmedWithOldContainer() // BUT without "kernel.build_dir" parameter (like an old dumped container) $kernel->boot(); $container = $kernel->getContainer(); - \Closure::bind(function (Container $class) { + \Closure::bind(static function (Container $class) { unset($class->loadedDynamicParameters['kernel.build_dir']); unset($class->parameters['kernel.build_dir']); }, null, $container::class)($container); diff --git a/Tests/Command/CachePoolInvalidateTagsCommandTest.php b/Tests/Command/CachePoolInvalidateTagsCommandTest.php index d0286b7e1..e78f3ad28 100644 --- a/Tests/Command/CachePoolInvalidateTagsCommandTest.php +++ b/Tests/Command/CachePoolInvalidateTagsCommandTest.php @@ -132,7 +132,7 @@ public function testCommandFailsIfInvalidatingTagsFails() private function createCommand(array $services): CachePoolInvalidateTagsCommand { return new CachePoolInvalidateTagsCommand( - new ServiceLocator(array_map(fn ($service) => fn () => $service, $services)) + new ServiceLocator(array_map(static fn ($service) => static fn () => $service, $services)) ); } } diff --git a/Tests/Command/EventDispatcherDebugCommandTest.php b/Tests/Command/EventDispatcherDebugCommandTest.php index 359196e11..8bd0b1552 100644 --- a/Tests/Command/EventDispatcherDebugCommandTest.php +++ b/Tests/Command/EventDispatcherDebugCommandTest.php @@ -43,14 +43,14 @@ public static function provideCompletionSuggestions(): iterable private function createCommandCompletionTester(): CommandCompletionTester { $dispatchers = new ServiceLocator([ - 'event_dispatcher' => function () { + 'event_dispatcher' => static function () { $dispatcher = new EventDispatcher(); $dispatcher->addListener(MessageEvent::class, 'var_dump'); $dispatcher->addListener('console.command', 'var_dump'); return $dispatcher; }, - 'other_event_dispatcher' => function () { + 'other_event_dispatcher' => static function () { $dispatcher = new EventDispatcher(); $dispatcher->addListener('other_event', 'var_dump'); $dispatcher->addListener('App\OtherEvent', 'var_dump'); diff --git a/Tests/Command/RouterMatchCommandTest.php b/Tests/Command/RouterMatchCommandTest.php index d9accce1e..bda4f218e 100644 --- a/Tests/Command/RouterMatchCommandTest.php +++ b/Tests/Command/RouterMatchCommandTest.php @@ -74,7 +74,7 @@ private function getKernel() $container ->expects($this->atLeastOnce()) ->method('has') - ->willReturnCallback(fn ($id) => 'console.command_loader' !== $id) + ->willReturnCallback(static fn ($id) => 'console.command_loader' !== $id) ; $container ->expects($this->any()) diff --git a/Tests/Command/TranslationDebugCommandTest.php b/Tests/Command/TranslationDebugCommandTest.php index ae5dc7c09..fd4fbad9f 100644 --- a/Tests/Command/TranslationDebugCommandTest.php +++ b/Tests/Command/TranslationDebugCommandTest.php @@ -175,7 +175,7 @@ private function createCommand(array $extractedMessages = [], array $loadedMessa $extractor ->method('extract') ->willReturnCallback( - function ($path, $catalogue) use ($extractedMessages) { + static function ($path, $catalogue) use ($extractedMessages) { $catalogue->add($extractedMessages); } ); @@ -185,7 +185,7 @@ function ($path, $catalogue) use ($extractedMessages) { $loader ->method('read') ->willReturnCallback( - function ($path, $catalogue) use ($loadedMessages) { + static function ($path, $catalogue) use ($loadedMessages) { $catalogue->add($loadedMessages); } ); @@ -249,7 +249,7 @@ public function testComplete(array $input, array $expectedSuggestions) $extractor ->method('extract') ->willReturnCallback( - function ($path, $catalogue) use ($extractedMessagesWithDomains) { + static function ($path, $catalogue) use ($extractedMessagesWithDomains) { foreach ($extractedMessagesWithDomains as $domain => $message) { $catalogue->add($message, $domain); } diff --git a/Tests/Command/TranslationUpdateCommandCompletionTest.php b/Tests/Command/TranslationUpdateCommandCompletionTest.php index 2050a631f..700e41b50 100644 --- a/Tests/Command/TranslationUpdateCommandCompletionTest.php +++ b/Tests/Command/TranslationUpdateCommandCompletionTest.php @@ -76,7 +76,7 @@ private function createCommandCompletionTester($extractedMessages = [], $loadedM $extractor ->method('extract') ->willReturnCallback( - function ($path, $catalogue) use ($extractedMessages) { + static function ($path, $catalogue) use ($extractedMessages) { foreach ($extractedMessages as $domain => $messages) { $catalogue->add($messages, $domain); } @@ -87,7 +87,7 @@ function ($path, $catalogue) use ($extractedMessages) { $loader ->method('read') ->willReturnCallback( - function ($path, $catalogue) use ($loadedMessages) { + static function ($path, $catalogue) use ($loadedMessages) { $catalogue->add($loadedMessages); } ); diff --git a/Tests/Command/TranslationUpdateCommandTest.php b/Tests/Command/TranslationUpdateCommandTest.php index 624ca39e4..0bbaee5e8 100644 --- a/Tests/Command/TranslationUpdateCommandTest.php +++ b/Tests/Command/TranslationUpdateCommandTest.php @@ -156,12 +156,12 @@ public function testFilterDuplicateTransPaths() if (preg_match('/\.[a-z]+$/', $transPath)) { if (!realpath(\dirname($transPath))) { - mkdir(\dirname($transPath), 0777, true); + mkdir(\dirname($transPath), 0o777, true); } touch($transPath); } else { - mkdir($transPath, 0777, true); + mkdir($transPath, 0o777, true); } } @@ -201,7 +201,7 @@ private function createCommandTester($extractedMessages = [], $loadedMessages = $extractor ->method('extract') ->willReturnCallback( - function ($path, $catalogue) use ($extractedMessages) { + static function ($path, $catalogue) use ($extractedMessages) { foreach ($extractedMessages as $domain => $messages) { $catalogue->add($messages, $domain); } @@ -212,7 +212,7 @@ function ($path, $catalogue) use ($extractedMessages) { $loader ->method('read') ->willReturnCallback( - function ($path, $catalogue) use ($loadedMessages) { + static function ($path, $catalogue) use ($loadedMessages) { $catalogue->add($loadedMessages); } ); diff --git a/Tests/Console/ApplicationTest.php b/Tests/Console/ApplicationTest.php index 66cd8de8f..53621d517 100644 --- a/Tests/Console/ApplicationTest.php +++ b/Tests/Console/ApplicationTest.php @@ -135,7 +135,7 @@ public function testRunOnlyWarnsOnUnregistrableCommand() $kernel ->method('getBundles') ->willReturn([$this->createBundleMock( - [(new Command('fine'))->setCode(function (InputInterface $input, OutputInterface $output) { $output->write('fine'); })] + [(new Command('fine'))->setCode(static function (InputInterface $input, OutputInterface $output) { $output->write('fine'); })] )]); $kernel ->method('getContainer') @@ -163,7 +163,7 @@ public function testRegistrationErrorsAreDisplayedOnCommandNotFound() $kernel ->method('getBundles') ->willReturn([$this->createBundleMock( - [(new Command(null))->setCode(function (InputInterface $input, OutputInterface $output) { $output->write('fine'); })] + [(new Command(null))->setCode(static function (InputInterface $input, OutputInterface $output) { $output->write('fine'); })] )]); $kernel ->method('getContainer') @@ -193,7 +193,7 @@ public function testRunOnlyWarnsOnUnregistrableCommandAtTheEnd() $kernel ->method('getBundles') ->willReturn([$this->createBundleMock( - [(new Command('fine'))->setCode(function (InputInterface $input, OutputInterface $output) { $output->write('fine'); })] + [(new Command('fine'))->setCode(static function (InputInterface $input, OutputInterface $output) { $output->write('fine'); })] )]); $kernel ->method('getContainer') @@ -314,7 +314,7 @@ private function createBundleMock(array $commands) $bundle ->expects($this->once()) ->method('registerCommands') - ->willReturnCallback(function (Application $application) use ($commands) { + ->willReturnCallback(static function (Application $application) use ($commands) { $application->addCommands($commands); }) ; diff --git a/Tests/Console/Descriptor/ObjectsProvider.php b/Tests/Console/Descriptor/ObjectsProvider.php index 84adc4ac9..33f2760e1 100644 --- a/Tests/Console/Descriptor/ObjectsProvider.php +++ b/Tests/Console/Descriptor/ObjectsProvider.php @@ -255,7 +255,7 @@ public static function getEventDispatchers() $eventDispatcher = new EventDispatcher(); $eventDispatcher->addListener('event1', 'var_dump', 255); - $eventDispatcher->addListener('event1', fn () => 'Closure', -1); + $eventDispatcher->addListener('event1', static fn () => 'Closure', -1); $eventDispatcher->addListener('event2', new CallableClass()); return ['event_dispatcher_1' => $eventDispatcher]; @@ -268,7 +268,7 @@ public static function getCallables(): array 'callable_2' => ['Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\CallableClass', 'staticMethod'], 'callable_3' => [new CallableClass(), 'method'], 'callable_4' => 'Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\CallableClass::staticMethod', - 'callable_6' => fn () => 'Closure', + 'callable_6' => static fn () => 'Closure', 'callable_7' => new CallableClass(), 'callable_from_callable' => (new CallableClass())(...), ]; diff --git a/Tests/Controller/AbstractControllerTest.php b/Tests/Controller/AbstractControllerTest.php index b59c5ecec..e83e80f5c 100644 --- a/Tests/Controller/AbstractControllerTest.php +++ b/Tests/Controller/AbstractControllerTest.php @@ -114,7 +114,7 @@ public function testForward() $requestStack->push($request); $kernel = $this->createMock(HttpKernelInterface::class); - $kernel->expects($this->once())->method('handle')->willReturnCallback(fn (Request $request) => new Response($request->getRequestFormat().'--'.$request->getLocale())); + $kernel->expects($this->once())->method('handle')->willReturnCallback(static fn (Request $request) => new Response($request->getRequestFormat().'--'.$request->getLocale())); $container = new Container(); $container->set('request_stack', $requestStack); diff --git a/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php b/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php index b6021fbdd..0951fc209 100644 --- a/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php +++ b/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php @@ -44,7 +44,7 @@ public function testMissingKnownTags() private function getKnownTags(): array { $tags = \Closure::bind( - fn () => UnusedTagsPass::KNOWN_TAGS, + static fn () => UnusedTagsPass::KNOWN_TAGS, null, UnusedTagsPass::class )(); diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index 8c938afc5..bf0a314f6 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -235,7 +235,7 @@ public function testInvalidAssetsConfiguration(array $assetConfig, $expectedMess public static function provideInvalidAssetConfigurationTests(): iterable { // helper to turn config into embedded package config - $createPackageConfig = fn (array $packageConfig) => [ + $createPackageConfig = static fn (array $packageConfig) => [ 'base_urls' => '//example.com', 'version' => 1, 'packages' => [ diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 946074005..a22e2e8df 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -843,7 +843,7 @@ public function testMessengerServicesRemovedWhenDisabled() $container = $this->createContainerFromFile('messenger_disabled'); $messengerDefinitions = array_filter( $container->getDefinitions(), - fn ($name) => str_starts_with($name, 'messenger.'), + static fn ($name) => str_starts_with($name, 'messenger.'), \ARRAY_FILTER_USE_KEY ); @@ -965,7 +965,7 @@ public function testMessengerMultipleFailureTransports() 'transport_3' => new Reference('messenger.transport.failure_transport_3'), ]; - $failureTransportsReferences = array_map(function (ServiceClosureArgument $serviceClosureArgument) { + $failureTransportsReferences = array_map(static function (ServiceClosureArgument $serviceClosureArgument) { $values = $serviceClosureArgument->getValues(); return array_shift($values); @@ -1006,7 +1006,7 @@ public function testMessengerMultipleFailureTransportsWithGlobalFailureTransport 'transport_3' => new Reference('messenger.transport.failure_transport_3'), ]; - $failureTransportsReferences = array_map(function (ServiceClosureArgument $serviceClosureArgument) { + $failureTransportsReferences = array_map(static function (ServiceClosureArgument $serviceClosureArgument) { $values = $serviceClosureArgument->getValues(); return array_shift($values); @@ -1080,7 +1080,7 @@ public function testMessengerTransports() 'schedule' => new Reference('messenger.transport.failed'), ]; - $failureTransportsReferences = array_map(function (ServiceClosureArgument $serviceClosureArgument) { + $failureTransportsReferences = array_map(static function (ServiceClosureArgument $serviceClosureArgument) { $values = $serviceClosureArgument->getValues(); return array_shift($values); @@ -1280,7 +1280,7 @@ public function testTranslator() $nonExistingDirectories = array_filter( $options['scanned_directories'], - fn ($directory) => !file_exists($directory) + static fn ($directory) => !file_exists($directory) ); $this->assertNotEmpty($nonExistingDirectories, 'FrameworkBundle should pass non existing directories to Translator'); @@ -2342,7 +2342,7 @@ public function testLocaleSwitcherServiceRegistered() $this->assertSame('kernel.locale_aware', $switcherDef->getArgument(1)->getTag()); $this->assertEquals(new Reference('router.request_context', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE), $switcherDef->getArgument(2)); - $localeAwareServices = array_map(fn (Reference $r) => (string) $r, $switcherDef->getArgument(1)->getValues()); + $localeAwareServices = array_map(static fn (Reference $r) => (string) $r, $switcherDef->getArgument(1)->getValues()); $this->assertNotContains('translation.locale_switcher', $localeAwareServices); } diff --git a/Tests/DependencyInjection/PhpFrameworkExtensionTest.php b/Tests/DependencyInjection/PhpFrameworkExtensionTest.php index bd455d648..6fc8c42f6 100644 --- a/Tests/DependencyInjection/PhpFrameworkExtensionTest.php +++ b/Tests/DependencyInjection/PhpFrameworkExtensionTest.php @@ -31,7 +31,7 @@ protected function loadFromFile(ContainerBuilder $container, $file) public function testAssetsCannotHavePathAndUrl() { $this->expectException(\LogicException::class); - $this->createContainerFromClosure(function ($container) { + $this->createContainerFromClosure(static function ($container) { $container->loadFromExtension('framework', [ 'annotations' => false, 'http_method_override' => false, @@ -48,7 +48,7 @@ public function testAssetsCannotHavePathAndUrl() public function testAssetPackageCannotHavePathAndUrl() { $this->expectException(\LogicException::class); - $this->createContainerFromClosure(function ($container) { + $this->createContainerFromClosure(static function ($container) { $container->loadFromExtension('framework', [ 'annotations' => false, 'http_method_override' => false, @@ -70,7 +70,7 @@ public function testWorkflowValidationPlacesIsArray() { $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage('The "places" option must be an array in workflow configuration.'); - $this->createContainerFromClosure(function ($container) { + $this->createContainerFromClosure(static function ($container) { $container->loadFromExtension('framework', [ 'workflows' => [ 'article' => [ @@ -85,7 +85,7 @@ public function testWorkflowValidationTransitonsIsArray() { $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage('The "transitions" option must be an array in workflow configuration.'); - $this->createContainerFromClosure(function ($container) { + $this->createContainerFromClosure(static function ($container) { $container->loadFromExtension('framework', [ 'workflows' => [ 'article' => [ @@ -100,7 +100,7 @@ public function testWorkflowValidationStateMachine() { $this->expectException(InvalidDefinitionException::class); $this->expectExceptionMessage('A transition from a place/state must have an unique name. Multiple transitions named "a_to_b" from place/state "a" were found on StateMachine "article".'); - $this->createContainerFromClosure(function ($container) { + $this->createContainerFromClosure(static function ($container) { $container->loadFromExtension('framework', [ 'annotations' => false, 'http_method_override' => false, @@ -131,7 +131,7 @@ public function testWorkflowValidationStateMachine() public function testWorkflowDefaultMarkingStoreDefinition() { - $container = $this->createContainerFromClosure(function ($container) { + $container = $this->createContainerFromClosure(static function ($container) { $container->loadFromExtension('framework', [ 'annotations' => false, 'http_method_override' => false, @@ -192,7 +192,7 @@ public function testWorkflowDefaultMarkingStoreDefinition() public function testRateLimiterWithLockFactory() { try { - $this->createContainerFromClosure(function (ContainerBuilder $container) { + $this->createContainerFromClosure(static function (ContainerBuilder $container) { $container->loadFromExtension('framework', [ 'annotations' => false, 'http_method_override' => false, @@ -210,7 +210,7 @@ public function testRateLimiterWithLockFactory() $this->assertEquals('Rate limiter "with_lock" requires the Lock component to be configured.', $e->getMessage()); } - $container = $this->createContainerFromClosure(function (ContainerBuilder $container) { + $container = $this->createContainerFromClosure(static function (ContainerBuilder $container) { $container->loadFromExtension('framework', [ 'annotations' => false, 'http_method_override' => false, @@ -229,7 +229,7 @@ public function testRateLimiterWithLockFactory() public function testRateLimiterLockFactory() { - $container = $this->createContainerFromClosure(function (ContainerBuilder $container) { + $container = $this->createContainerFromClosure(static function (ContainerBuilder $container) { $container->loadFromExtension('framework', [ 'annotations' => false, 'http_method_override' => false, @@ -254,7 +254,7 @@ public function testValidatorEmailValidationMode(string $mode) { $this->expectNotToPerformAssertions(); - $this->createContainerFromClosure(function (ContainerBuilder $container) use ($mode) { + $this->createContainerFromClosure(static function (ContainerBuilder $container) use ($mode) { $container->loadFromExtension('framework', [ 'annotations' => false, 'http_method_override' => false, diff --git a/Tests/Functional/KernelTestCaseFreshCacheTest.php b/Tests/Functional/KernelTestCaseFreshCacheTest.php index a65f68833..fd9f4d224 100644 --- a/Tests/Functional/KernelTestCaseFreshCacheTest.php +++ b/Tests/Functional/KernelTestCaseFreshCacheTest.php @@ -43,7 +43,7 @@ public function testContainerIsRebuiltWhenTrackedFileAppears() static::ensureKernelShutdown(); // Create the tracked file between boots - @mkdir(\dirname(self::$trackedFile), 0777, true); + @mkdir(\dirname(self::$trackedFile), 0o777, true); file_put_contents(self::$trackedFile, 'placeholder'); // Reboot: should detect the resource change and rebuild the container diff --git a/Tests/Routing/RouterTest.php b/Tests/Routing/RouterTest.php index 5765356b5..abd0e8489 100644 --- a/Tests/Routing/RouterTest.php +++ b/Tests/Routing/RouterTest.php @@ -653,7 +653,7 @@ private function getParameterBag(array $params = []): ContainerInterface $bag ->expects($this->any()) ->method('get') - ->willReturnCallback(fn ($key) => $params[$key] ?? null) + ->willReturnCallback(static fn ($key) => $params[$key] ?? null) ; return $bag; From bb645bec6065b41ea7b7cbdc7dfff98146a9cefd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 13 Apr 2026 16:47:07 +0200 Subject: [PATCH 08/17] Fix merge --- CacheWarmer/AnnotationsCacheWarmer.php | 117 ----------- .../AnnotationsCacheWarmerTest.php | 191 ------------------ 2 files changed, 308 deletions(-) delete mode 100644 CacheWarmer/AnnotationsCacheWarmer.php delete mode 100644 Tests/CacheWarmer/AnnotationsCacheWarmerTest.php diff --git a/CacheWarmer/AnnotationsCacheWarmer.php b/CacheWarmer/AnnotationsCacheWarmer.php deleted file mode 100644 index a29739257..000000000 --- a/CacheWarmer/AnnotationsCacheWarmer.php +++ /dev/null @@ -1,117 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Doctrine\Common\Annotations\AnnotationException; -use Doctrine\Common\Annotations\PsrCachedReader; -use Doctrine\Common\Annotations\Reader; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; - -/** - * Warms up annotation caches for classes found in composer's autoload class map - * and declared in DI bundle extensions using the addAnnotatedClassesToCache method. - * - * @author Titouan Galopin - * - * @deprecated since Symfony 6.4 without replacement - */ -class AnnotationsCacheWarmer extends AbstractPhpFileCacheWarmer -{ - /** - * @param string $phpArrayFile The PHP file where annotations are cached - */ - public function __construct( - private readonly Reader $annotationReader, - string $phpArrayFile, - private readonly ?string $excludeRegexp = null, - private readonly bool $debug = false, - /* bool $triggerDeprecation = true, */ - ) { - if (\func_num_args() < 5 || func_get_arg(4)) { - trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s" class is deprecated without replacement.', __CLASS__); - } - - parent::__construct($phpArrayFile); - } - - /** - * @param string|null $buildDir - */ - protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter /* , string $buildDir = null */): bool - { - $annotatedClassPatterns = $cacheDir.'/annotations.map'; - - if (!is_file($annotatedClassPatterns)) { - return true; - } - - $annotatedClasses = include $annotatedClassPatterns; - $reader = new PsrCachedReader($this->annotationReader, $arrayAdapter, $this->debug); - - foreach ($annotatedClasses as $class) { - if (null !== $this->excludeRegexp && preg_match($this->excludeRegexp, $class)) { - continue; - } - try { - $this->readAllComponents($reader, $class); - } catch (\Exception $e) { - $this->ignoreAutoloadException($class, $e); - } - } - - return true; - } - - /** - * @return string[] A list of classes to preload on PHP 7.4+ - */ - protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values): array - { - // make sure we don't cache null values - $values = array_filter($values, static fn ($val) => null !== $val); - - return parent::warmUpPhpArrayAdapter($phpArrayAdapter, $values); - } - - private function readAllComponents(Reader $reader, string $class): void - { - $reflectionClass = new \ReflectionClass($class); - - try { - $reader->getClassAnnotations($reflectionClass); - } catch (AnnotationException) { - /* - * Ignore any AnnotationException to not break the cache warming process if an Annotation is badly - * configured or could not be found / read / etc. - * - * In particular cases, an Annotation in your code can be used and defined only for a specific - * environment but is always added to the annotations.map file by some Symfony default behaviors, - * and you always end up with a not found Annotation. - */ - } - - foreach ($reflectionClass->getMethods() as $reflectionMethod) { - try { - $reader->getMethodAnnotations($reflectionMethod); - } catch (AnnotationException) { - } - } - - foreach ($reflectionClass->getProperties() as $reflectionProperty) { - try { - $reader->getPropertyAnnotations($reflectionProperty); - } catch (AnnotationException) { - } - } - } -} diff --git a/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php b/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php deleted file mode 100644 index 5f5fd0627..000000000 --- a/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php +++ /dev/null @@ -1,191 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Tests\CacheWarmer; - -use Doctrine\Common\Annotations\AnnotationReader; -use Doctrine\Common\Annotations\PsrCachedReader; -use Doctrine\Common\Annotations\Reader; -use PHPUnit\Framework\MockObject\MockObject; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; -use Symfony\Bundle\FrameworkBundle\CacheWarmer\AnnotationsCacheWarmer; -use Symfony\Bundle\FrameworkBundle\Tests\TestCase; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\NullAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; -use Symfony\Component\Filesystem\Filesystem; - -/** - * @group legacy - */ -class AnnotationsCacheWarmerTest extends TestCase -{ - use ExpectDeprecationTrait; - - private string $cacheDir; - - protected function setUp(): void - { - $this->cacheDir = sys_get_temp_dir().'/'.uniqid('', true); - $fs = new Filesystem(); - $fs->mkdir($this->cacheDir); - parent::setUp(); - } - - protected function tearDown(): void - { - $fs = new Filesystem(); - $fs->remove($this->cacheDir); - parent::tearDown(); - } - - public function testAnnotationsCacheWarmerWithDebugDisabled() - { - file_put_contents($this->cacheDir.'/annotations.map', \sprintf('cacheDir, __FUNCTION__); - $reader = new AnnotationReader(); - - $this->expectDeprecation('Since symfony/framework-bundle 6.4: The "Symfony\Bundle\FrameworkBundle\CacheWarmer\AnnotationsCacheWarmer" class is deprecated without replacement.'); - $warmer = new AnnotationsCacheWarmer($reader, $cacheFile); - - $warmer->warmUp($this->cacheDir); - $this->assertFileExists($cacheFile); - - // Assert cache is valid - $reader = new PsrCachedReader( - $this->getReadOnlyReader(), - new PhpArrayAdapter($cacheFile, new NullAdapter()) - ); - $refClass = new \ReflectionClass($this); - $reader->getClassAnnotations($refClass); - $reader->getMethodAnnotations($refClass->getMethod(__FUNCTION__)); - $reader->getPropertyAnnotations($refClass->getProperty('cacheDir')); - } - - public function testAnnotationsCacheWarmerWithDebugEnabled() - { - file_put_contents($this->cacheDir.'/annotations.map', \sprintf('cacheDir, __FUNCTION__); - $reader = new AnnotationReader(); - - $this->expectDeprecation('Since symfony/framework-bundle 6.4: The "Symfony\Bundle\FrameworkBundle\CacheWarmer\AnnotationsCacheWarmer" class is deprecated without replacement.'); - $warmer = new AnnotationsCacheWarmer($reader, $cacheFile, null, true); - - $warmer->warmUp($this->cacheDir); - $this->assertFileExists($cacheFile); - - // Assert cache is valid - $phpArrayAdapter = new PhpArrayAdapter($cacheFile, new NullAdapter()); - $reader = new PsrCachedReader( - $this->getReadOnlyReader(), - $phpArrayAdapter, - true - ); - $refClass = new \ReflectionClass($this); - $reader->getClassAnnotations($refClass); - $reader->getMethodAnnotations($refClass->getMethod(__FUNCTION__)); - $reader->getPropertyAnnotations($refClass->getProperty('cacheDir')); - } - - /** - * Test that the cache warming process is not broken if a class loader - * throws an exception (on class / file not found for example). - */ - public function testClassAutoloadException() - { - $this->assertFalse(class_exists($annotatedClass = 'C\C\C', false)); - - file_put_contents($this->cacheDir.'/annotations.map', \sprintf('expectDeprecation('Since symfony/framework-bundle 6.4: The "Symfony\Bundle\FrameworkBundle\CacheWarmer\AnnotationsCacheWarmer" class is deprecated without replacement.'); - $warmer = new AnnotationsCacheWarmer(new AnnotationReader(), tempnam($this->cacheDir, __FUNCTION__)); - - spl_autoload_register($classLoader = static function ($class) use ($annotatedClass) { - if ($class === $annotatedClass) { - throw new \DomainException('This exception should be caught by the warmer.'); - } - }, true, true); - - $warmer->warmUp($this->cacheDir); - - spl_autoload_unregister($classLoader); - } - - /** - * Test that the cache warming process is broken if a class loader throws an - * exception but that is unrelated to the class load. - */ - public function testClassAutoloadExceptionWithUnrelatedException() - { - $this->expectException(\DomainException::class); - $this->expectExceptionMessage('This exception should not be caught by the warmer.'); - - $this->assertFalse(class_exists($annotatedClass = 'AClassThatDoesNotExist_FWB_CacheWarmer_AnnotationsCacheWarmerTest', false)); - - file_put_contents($this->cacheDir.'/annotations.map', \sprintf('expectDeprecation('Since symfony/framework-bundle 6.4: The "Symfony\Bundle\FrameworkBundle\CacheWarmer\AnnotationsCacheWarmer" class is deprecated without replacement.'); - $warmer = new AnnotationsCacheWarmer(new AnnotationReader(), tempnam($this->cacheDir, __FUNCTION__)); - - spl_autoload_register($classLoader = function ($class) use ($annotatedClass) { - if ($class === $annotatedClass) { - eval('class '.$annotatedClass.'{}'); - throw new \DomainException('This exception should not be caught by the warmer.'); - } - }, true, true); - - $warmer->warmUp($this->cacheDir); - - spl_autoload_unregister($classLoader); - } - - public function testWarmupRemoveCacheMisses() - { - $cacheFile = tempnam($this->cacheDir, __FUNCTION__); - $this->expectDeprecation('Since symfony/framework-bundle 6.4: The "Symfony\Bundle\FrameworkBundle\CacheWarmer\AnnotationsCacheWarmer" class is deprecated without replacement.'); - $warmer = $this->getMockBuilder(AnnotationsCacheWarmer::class) - ->setConstructorArgs([new AnnotationReader(), $cacheFile]) - ->onlyMethods(['doWarmUp']) - ->getMock(); - - $warmer->method('doWarmUp')->willReturnCallback(static function ($cacheDir, ArrayAdapter $arrayAdapter) { - $arrayAdapter->getItem('foo_miss'); - - $item = $arrayAdapter->getItem('bar_hit'); - $item->set('data'); - $arrayAdapter->save($item); - - $item = $arrayAdapter->getItem('baz_hit_null'); - $item->set(null); - $arrayAdapter->save($item); - - return true; - }); - - $warmer->warmUp($this->cacheDir); - $data = include $cacheFile; - - $this->assertCount(1, $data[0]); - $this->assertTrue(isset($data[0]['bar_hit'])); - } - - private function getReadOnlyReader(): MockObject&Reader - { - $readerMock = $this->createMock(Reader::class); - $readerMock->expects($this->exactly(0))->method('getClassAnnotations'); - $readerMock->expects($this->exactly(0))->method('getClassAnnotation'); - $readerMock->expects($this->exactly(0))->method('getMethodAnnotations'); - $readerMock->expects($this->exactly(0))->method('getMethodAnnotation'); - $readerMock->expects($this->exactly(0))->method('getPropertyAnnotations'); - $readerMock->expects($this->exactly(0))->method('getPropertyAnnotation'); - - return $readerMock; - } -} From 337b4b442e8996b5be0fa2a277d27eed20bc274d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 13 Apr 2026 17:27:04 +0200 Subject: [PATCH 09/17] More CS fixes --- Controller/ControllerResolver.php | 3 +- DependencyInjection/Configuration.php | 40 +++++-------------- Resources/bin/check-unused-known-tags.php | 4 +- .../ConfigDumpReferenceCommandTest.php | 5 ++- 4 files changed, 16 insertions(+), 36 deletions(-) diff --git a/Controller/ControllerResolver.php b/Controller/ControllerResolver.php index 8d7613d41..60fdf28ca 100644 --- a/Controller/ControllerResolver.php +++ b/Controller/ControllerResolver.php @@ -32,9 +32,8 @@ protected function instantiateController(string $class): object if ($controller instanceof AbstractController) { if (null === $previousContainer = $controller->setContainer($this->container)) { throw new \LogicException(\sprintf('"%s" has no container set, did you forget to define it as a service subscriber?', $class)); - } else { - $controller->setContainer($previousContainer); } + $controller->setContainer($previousContainer); } return $controller; diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 2e7667532..b176ba155 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -584,15 +584,11 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void ->end() ->end() ->validate() - ->ifTrue(static function ($v) { - return $v['supports'] && isset($v['support_strategy']); - }) + ->ifTrue(static fn ($v) => $v['supports'] && isset($v['support_strategy'])) ->thenInvalid('"supports" and "support_strategy" cannot be used together.') ->end() ->validate() - ->ifTrue(static function ($v) { - return !$v['supports'] && !isset($v['support_strategy']); - }) + ->ifTrue(static fn ($v) => !$v['supports'] && !isset($v['support_strategy'])) ->thenInvalid('"supports" or "support_strategy" should be configured.') ->end() ->beforeNormalization() @@ -773,21 +769,15 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode, callable $enabl ->end() ->end() ->validate() - ->ifTrue(static function ($v) { - return isset($v['version_strategy']) && isset($v['version']); - }) + ->ifTrue(static fn ($v) => isset($v['version_strategy']) && isset($v['version'])) ->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets".') ->end() ->validate() - ->ifTrue(static function ($v) { - return isset($v['version_strategy']) && isset($v['json_manifest_path']); - }) + ->ifTrue(static fn ($v) => isset($v['version_strategy']) && isset($v['json_manifest_path'])) ->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets".') ->end() ->validate() - ->ifTrue(static function ($v) { - return isset($v['version']) && isset($v['json_manifest_path']); - }) + ->ifTrue(static fn ($v) => isset($v['version']) && isset($v['json_manifest_path'])) ->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets".') ->end() ->fixXmlConfig('package') @@ -819,21 +809,15 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode, callable $enabl ->end() ->end() ->validate() - ->ifTrue(static function ($v) { - return isset($v['version_strategy']) && isset($v['version']); - }) + ->ifTrue(static fn ($v) => isset($v['version_strategy']) && isset($v['version'])) ->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets" packages.') ->end() ->validate() - ->ifTrue(static function ($v) { - return isset($v['version_strategy']) && isset($v['json_manifest_path']); - }) + ->ifTrue(static fn ($v) => isset($v['version_strategy']) && isset($v['json_manifest_path'])) ->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets" packages.') ->end() ->validate() - ->ifTrue(static function ($v) { - return isset($v['version']) && isset($v['json_manifest_path']); - }) + ->ifTrue(static fn ($v) => isset($v['version']) && isset($v['json_manifest_path'])) ->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets" packages.') ->end() ->end() @@ -1613,9 +1597,7 @@ private function addMessengerSection(ArrayNodeDefinition $rootNode, callable $en ]; } else { $newConfig[$v['message-class']]['senders'] = array_map( - static function ($a) { - return \is_string($a) ? $a : $a['service']; - }, + static fn ($a) => \is_string($a) ? $a : $a['service'], array_values($v['sender']) ); } @@ -1662,9 +1644,7 @@ static function ($a) { ->arrayPrototype() ->beforeNormalization() ->ifString() - ->then(static function (string $dsn) { - return ['dsn' => $dsn]; - }) + ->then(static fn (string $dsn) => ['dsn' => $dsn]) ->end() ->fixXmlConfig('option') ->children() diff --git a/Resources/bin/check-unused-known-tags.php b/Resources/bin/check-unused-known-tags.php index 5e020b051..55658f5b1 100644 --- a/Resources/bin/check-unused-known-tags.php +++ b/Resources/bin/check-unused-known-tags.php @@ -13,11 +13,11 @@ throw new Exception('This script must be run from the command line.'); } -require \dirname(__DIR__, 6).'/vendor/autoload.php'; +require dirname(__DIR__, 6).'/vendor/autoload.php'; use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\UnusedTagsPassUtils; -$target = \dirname(__DIR__, 2).'/DependencyInjection/Compiler/UnusedTagsPass.php'; +$target = dirname(__DIR__, 2).'/DependencyInjection/Compiler/UnusedTagsPass.php'; $contents = file_get_contents($target); $contents = preg_replace('{private const KNOWN_TAGS = \[(.+?)\];}sm', "private const KNOWN_TAGS = [\n '".implode("',\n '", UnusedTagsPassUtils::getDefinedTags())."',\n ];", $contents); file_put_contents($target, $contents); diff --git a/Tests/Functional/ConfigDumpReferenceCommandTest.php b/Tests/Functional/ConfigDumpReferenceCommandTest.php index 5fa061969..1966688ae 100644 --- a/Tests/Functional/ConfigDumpReferenceCommandTest.php +++ b/Tests/Functional/ConfigDumpReferenceCommandTest.php @@ -104,8 +104,9 @@ public function testDumpAtPath(bool $debug) child2: ~ - EOL - , $tester->getDisplay(true)); + EOL, + $tester->getDisplay(true) + ); } /** From 093b137079dbaa71ae00c71be1d7c904c1c41bfd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 13 Apr 2026 17:40:04 +0200 Subject: [PATCH 10/17] CS fixes --- DependencyInjection/Configuration.php | 4 +--- Resources/config/routing/errors.php | 2 +- Resources/config/routing/webhook.php | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 195fbb6e0..e329277a3 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -2452,9 +2452,7 @@ private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enabl }) ->end() ->validate() - ->ifTrue(static function ($v) { - return \extension_loaded('openssl') && null !== $v && !\defined('OPENSSL_CIPHER_'.$v); - }) + ->ifTrue(static fn ($v) => \extension_loaded('openssl') && null !== $v && !\defined('OPENSSL_CIPHER_'.$v)) ->thenInvalid('You must provide a valid cipher.') ->end() ->end() diff --git a/Resources/config/routing/errors.php b/Resources/config/routing/errors.php index 3c3c6cc94..724f7bf52 100644 --- a/Resources/config/routing/errors.php +++ b/Resources/config/routing/errors.php @@ -15,7 +15,7 @@ return static function (RoutingConfigurator $routes): void { foreach (debug_backtrace() as $trace) { if (isset($trace['object']) && $trace['object'] instanceof XmlFileLoader && 'doImport' === $trace['function']) { - if (__DIR__ === \dirname(realpath($trace['args'][3]))) { + if (__DIR__ === dirname(realpath($trace['args'][3]))) { trigger_deprecation('symfony/routing', '7.3', 'The "errors.xml" routing configuration file is deprecated, import "errors.php" instead.'); break; diff --git a/Resources/config/routing/webhook.php b/Resources/config/routing/webhook.php index df7e7a20f..dc07d7f93 100644 --- a/Resources/config/routing/webhook.php +++ b/Resources/config/routing/webhook.php @@ -15,7 +15,7 @@ return static function (RoutingConfigurator $routes): void { foreach (debug_backtrace() as $trace) { if (isset($trace['object']) && $trace['object'] instanceof XmlFileLoader && 'doImport' === $trace['function']) { - if (__DIR__ === \dirname(realpath($trace['args'][3]))) { + if (__DIR__ === dirname(realpath($trace['args'][3]))) { trigger_deprecation('symfony/routing', '7.3', 'The "webhook.xml" routing configuration file is deprecated, import "webhook.php" instead.'); break; From 80c0374cc4dbfc31da71784a160474e64f52dddd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 18 Apr 2026 15:16:27 +0200 Subject: [PATCH 11/17] Update XSD references in phpunit.xml.dist files --- phpunit.xml.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 03797a5d9..a7cde67a2 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,7 +1,7 @@ Date: Sat, 18 Apr 2026 16:18:42 +0000 Subject: [PATCH 12/17] [FrameworkBundle] Strip --no-fill marker from every translation domain --- Command/TranslationExtractCommand.php | 8 +++-- .../Command/TranslationExtractCommandTest.php | 36 +++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/Command/TranslationExtractCommand.php b/Command/TranslationExtractCommand.php index e5129c5c3..83e8eed79 100644 --- a/Command/TranslationExtractCommand.php +++ b/Command/TranslationExtractCommand.php @@ -494,9 +494,11 @@ private function getRootCodePaths(KernelInterface $kernel): array private function removeNoFillTranslations(MessageCatalogueInterface $operation): void { - foreach ($operation->all('messages') as $key => $message) { - if (str_starts_with($message, self::NO_FILL_PREFIX)) { - $operation->set($key, '', 'messages'); + foreach ($operation->getDomains() as $domain) { + foreach ($operation->all($domain) as $key => $message) { + if (str_starts_with($message, self::NO_FILL_PREFIX)) { + $operation->set($key, '', $domain); + } } } } diff --git a/Tests/Command/TranslationExtractCommandTest.php b/Tests/Command/TranslationExtractCommandTest.php index 33807338a..79a425b5a 100644 --- a/Tests/Command/TranslationExtractCommandTest.php +++ b/Tests/Command/TranslationExtractCommandTest.php @@ -183,6 +183,9 @@ public function testRemoveNoFillTranslationsMethod($noFillCounter, $messages) { // Preparing mock $operation = $this->createMock(MessageCatalogueInterface::class); + $operation + ->method('getDomains') + ->willReturn(['messages']); $operation ->method('all') ->willReturnMap([ @@ -199,6 +202,39 @@ public function testRemoveNoFillTranslationsMethod($noFillCounter, $messages) $method->invokeArgs($translationUpdate, [$operation]); } + public function testRemoveNoFillTranslationsAcrossAllDomains() + { + $operation = $this->createMock(MessageCatalogueInterface::class); + $operation + ->method('getDomains') + ->willReturn(['messages', 'validators', 'validators+intl-icu']); + $operation + ->method('all') + ->willReturnMap([ + ['messages', ['greeting' => "\0NoFill\0Hello"]], + ['validators', ['err' => 'plain error']], + ['validators+intl-icu', ['desc' => "\0NoFill\0Description is mandatory"]], + ]); + + $calls = []; + $operation + ->expects($this->exactly(2)) + ->method('set') + ->willReturnCallback(static function ($id, $translation, $domain) use (&$calls): void { + $calls[] = [$id, $translation, $domain]; + }); + + $translationUpdate = $this->createStub(TranslationExtractCommand::class); + $reflection = new \ReflectionObject($translationUpdate); + $method = $reflection->getMethod('removeNoFillTranslations'); + $method->invokeArgs($translationUpdate, [$operation]); + + $this->assertSame([ + ['greeting', '', 'messages'], + ['desc', '', 'validators+intl-icu'], + ], $calls); + } + public static function removeNoFillProvider(): array { return [ From b10e4e740c5342d93ebeefcf77991221861361ac Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sun, 19 Apr 2026 20:33:56 +0200 Subject: [PATCH 13/17] [7.4] Remove usages of named arguments in tests --- Tests/Controller/AbstractControllerTest.php | 4 ++-- Tests/Controller/TemplateControllerTest.php | 4 ++-- Tests/Functional/CacheAttributeListenerTest.php | 4 ++-- Tests/Functional/HttpClientTest.php | 12 ++++++------ 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Tests/Controller/AbstractControllerTest.php b/Tests/Controller/AbstractControllerTest.php index eaded24a2..acb31b02f 100644 --- a/Tests/Controller/AbstractControllerTest.php +++ b/Tests/Controller/AbstractControllerTest.php @@ -689,8 +689,8 @@ public function testSendEarlyHints() $controller->setContainer($container); $response = $controller->sendEarlyHints([ - (new Link(href: '/style.css'))->withAttribute('as', 'stylesheet'), - (new Link(href: '/script.js'))->withAttribute('as', 'script'), + (new Link(null, '/style.css'))->withAttribute('as', 'stylesheet'), + (new Link(null, '/script.js'))->withAttribute('as', 'script'), ]); $this->assertSame('; rel="preload"; as="stylesheet",; rel="preload"; as="script"', $response->headers->get('Link')); diff --git a/Tests/Controller/TemplateControllerTest.php b/Tests/Controller/TemplateControllerTest.php index 1d98f4f8e..34ce1d4ed 100644 --- a/Tests/Controller/TemplateControllerTest.php +++ b/Tests/Controller/TemplateControllerTest.php @@ -111,8 +111,8 @@ public function testHeaders() $twig = new Environment($loader); $controller = new TemplateController($twig); - $this->assertSame('image/svg+xml', $controller->templateAction($templateName, headers: ['Content-Type' => 'image/svg+xml'])->headers->get('Content-Type')); - $this->assertSame('image/svg+xml', $controller($templateName, headers: ['Content-Type' => 'image/svg+xml'])->headers->get('Content-Type')); + $this->assertSame('image/svg+xml', $controller->templateAction($templateName, null, null, null, [], 200, ['Content-Type' => 'image/svg+xml'])->headers->get('Content-Type')); + $this->assertSame('image/svg+xml', $controller($templateName, null, null, null, [], 200, ['Content-Type' => 'image/svg+xml'])->headers->get('Content-Type')); $this->assertNull($controller->templateAction($templateName)->headers->get('Content-Type')); $this->assertNull($controller($templateName)->headers->get('Content-Type')); diff --git a/Tests/Functional/CacheAttributeListenerTest.php b/Tests/Functional/CacheAttributeListenerTest.php index e6eb93eba..69b37743d 100644 --- a/Tests/Functional/CacheAttributeListenerTest.php +++ b/Tests/Functional/CacheAttributeListenerTest.php @@ -25,7 +25,7 @@ public function testAnonimousUserWithEtag() { $client = self::createClient(['test_case' => 'CacheAttributeListener']); - $client->request('GET', '/', server: ['HTTP_IF_NONE_MATCH' => \sprintf('"%s"', hash('sha256', '12345'))]); + $client->request('GET', '/', [], [], ['HTTP_IF_NONE_MATCH' => \sprintf('"%s"', hash('sha256', '12345'))]); self::assertTrue($client->getResponse()->isRedirect('http://localhost/login')); } @@ -44,7 +44,7 @@ public function testLoggedInUserWithEtag() $client = self::createClient(['test_case' => 'CacheAttributeListener']); $client->loginUser(new InMemoryUser('the-username', 'the-password', ['ROLE_USER'])); - $client->request('GET', '/', server: ['HTTP_IF_NONE_MATCH' => \sprintf('"%s"', hash('sha256', '12345'))]); + $client->request('GET', '/', [], [], ['HTTP_IF_NONE_MATCH' => \sprintf('"%s"', hash('sha256', '12345'))]); $response = $client->getResponse(); diff --git a/Tests/Functional/HttpClientTest.php b/Tests/Functional/HttpClientTest.php index fcce53704..5280e5de7 100644 --- a/Tests/Functional/HttpClientTest.php +++ b/Tests/Functional/HttpClientTest.php @@ -24,13 +24,13 @@ public function testHttpClientAssertions() $client->request('GET', '/http_client_call'); $this->assertHttpClientRequest('https://symfony.com/'); - $this->assertHttpClientRequest('https://symfony.com/', httpClientId: 'symfony.http_client'); - $this->assertHttpClientRequest('https://symfony.com/', 'POST', 'foo', httpClientId: 'symfony.http_client'); - $this->assertHttpClientRequest('https://symfony.com/', 'POST', ['foo' => 'bar'], httpClientId: 'symfony.http_client'); - $this->assertHttpClientRequest('https://symfony.com/', 'POST', ['foo' => 'bar'], httpClientId: 'symfony.http_client'); + $this->assertHttpClientRequest('https://symfony.com/', 'GET', null, [], 'symfony.http_client'); + $this->assertHttpClientRequest('https://symfony.com/', 'POST', 'foo', [], 'symfony.http_client'); + $this->assertHttpClientRequest('https://symfony.com/', 'POST', ['foo' => 'bar'], [], 'symfony.http_client'); + $this->assertHttpClientRequest('https://symfony.com/', 'POST', ['foo' => 'bar'], [], 'symfony.http_client'); $this->assertHttpClientRequest('https://symfony.com/', 'POST', ['foo' => 'bar'], ['X-Test-Header' => 'foo'], 'symfony.http_client'); - $this->assertHttpClientRequest('https://symfony.com/doc/current/index.html', httpClientId: 'symfony.http_client'); - $this->assertNotHttpClientRequest('https://laravel.com', httpClientId: 'symfony.http_client'); + $this->assertHttpClientRequest('https://symfony.com/doc/current/index.html', 'GET', null, [], 'symfony.http_client'); + $this->assertNotHttpClientRequest('https://laravel.com', 'GET', 'symfony.http_client'); $this->assertHttpClientRequestCount(6, 'symfony.http_client'); } From b620ee89245004139f3b4d48d2aef51fd788e542 Mon Sep 17 00:00:00 2001 From: lacatoire Date: Thu, 23 Apr 2026 14:49:37 +0200 Subject: [PATCH 14/17] [FrameworkBundle] Fix mailer package check for bridges whose composer name does not match the service id --- DependencyInjection/FrameworkExtension.php | 76 ++++++++++------------ 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 00333c517..48a253a0d 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -3056,56 +3056,52 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co } $classToServices = [ - MailerBridge\AhaSend\Transport\AhaSendTransportFactory::class => 'mailer.transport_factory.ahasend', - MailerBridge\Azure\Transport\AzureTransportFactory::class => 'mailer.transport_factory.azure', - MailerBridge\Brevo\Transport\BrevoTransportFactory::class => 'mailer.transport_factory.brevo', - MailerBridge\Google\Transport\GmailTransportFactory::class => 'mailer.transport_factory.gmail', - MailerBridge\Infobip\Transport\InfobipTransportFactory::class => 'mailer.transport_factory.infobip', - MailerBridge\MailerSend\Transport\MailerSendTransportFactory::class => 'mailer.transport_factory.mailersend', - MailerBridge\Mailgun\Transport\MailgunTransportFactory::class => 'mailer.transport_factory.mailgun', - MailerBridge\Mailjet\Transport\MailjetTransportFactory::class => 'mailer.transport_factory.mailjet', - MailerBridge\Mailomat\Transport\MailomatTransportFactory::class => 'mailer.transport_factory.mailomat', - MailerBridge\MailPace\Transport\MailPaceTransportFactory::class => 'mailer.transport_factory.mailpace', - MailerBridge\Mailchimp\Transport\MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp', - MailerBridge\MicrosoftGraph\Transport\MicrosoftGraphTransportFactory::class => 'mailer.transport_factory.microsoftgraph', - MailerBridge\Postal\Transport\PostalTransportFactory::class => 'mailer.transport_factory.postal', - MailerBridge\Postmark\Transport\PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', - MailerBridge\Mailtrap\Transport\MailtrapTransportFactory::class => 'mailer.transport_factory.mailtrap', - MailerBridge\Resend\Transport\ResendTransportFactory::class => 'mailer.transport_factory.resend', - MailerBridge\Scaleway\Transport\ScalewayTransportFactory::class => 'mailer.transport_factory.scaleway', - MailerBridge\Sendgrid\Transport\SendgridTransportFactory::class => 'mailer.transport_factory.sendgrid', - MailerBridge\Amazon\Transport\SesTransportFactory::class => 'mailer.transport_factory.amazon', - MailerBridge\Sweego\Transport\SweegoTransportFactory::class => 'mailer.transport_factory.sweego', + MailerBridge\AhaSend\Transport\AhaSendTransportFactory::class => ['symfony/aha-send-mailer', 'mailer.transport_factory.ahasend'], + MailerBridge\Azure\Transport\AzureTransportFactory::class => ['symfony/azure-mailer', 'mailer.transport_factory.azure'], + MailerBridge\Brevo\Transport\BrevoTransportFactory::class => ['symfony/brevo-mailer', 'mailer.transport_factory.brevo'], + MailerBridge\Google\Transport\GmailTransportFactory::class => ['symfony/google-mailer', 'mailer.transport_factory.gmail'], + MailerBridge\Infobip\Transport\InfobipTransportFactory::class => ['symfony/infobip-mailer', 'mailer.transport_factory.infobip'], + MailerBridge\MailerSend\Transport\MailerSendTransportFactory::class => ['symfony/mailer-send-mailer', 'mailer.transport_factory.mailersend'], + MailerBridge\Mailgun\Transport\MailgunTransportFactory::class => ['symfony/mailgun-mailer', 'mailer.transport_factory.mailgun'], + MailerBridge\Mailjet\Transport\MailjetTransportFactory::class => ['symfony/mailjet-mailer', 'mailer.transport_factory.mailjet'], + MailerBridge\Mailomat\Transport\MailomatTransportFactory::class => ['symfony/mailomat-mailer', 'mailer.transport_factory.mailomat'], + MailerBridge\MailPace\Transport\MailPaceTransportFactory::class => ['symfony/mail-pace-mailer', 'mailer.transport_factory.mailpace'], + MailerBridge\Mailchimp\Transport\MandrillTransportFactory::class => ['symfony/mailchimp-mailer', 'mailer.transport_factory.mailchimp'], + MailerBridge\MicrosoftGraph\Transport\MicrosoftGraphTransportFactory::class => ['symfony/microsoft-graph-mailer', 'mailer.transport_factory.microsoftgraph'], + MailerBridge\Postal\Transport\PostalTransportFactory::class => ['symfony/postal-mailer', 'mailer.transport_factory.postal'], + MailerBridge\Postmark\Transport\PostmarkTransportFactory::class => ['symfony/postmark-mailer', 'mailer.transport_factory.postmark'], + MailerBridge\Mailtrap\Transport\MailtrapTransportFactory::class => ['symfony/mailtrap-mailer', 'mailer.transport_factory.mailtrap'], + MailerBridge\Resend\Transport\ResendTransportFactory::class => ['symfony/resend-mailer', 'mailer.transport_factory.resend'], + MailerBridge\Scaleway\Transport\ScalewayTransportFactory::class => ['symfony/scaleway-mailer', 'mailer.transport_factory.scaleway'], + MailerBridge\Sendgrid\Transport\SendgridTransportFactory::class => ['symfony/sendgrid-mailer', 'mailer.transport_factory.sendgrid'], + MailerBridge\Amazon\Transport\SesTransportFactory::class => ['symfony/amazon-mailer', 'mailer.transport_factory.amazon'], + MailerBridge\Sweego\Transport\SweegoTransportFactory::class => ['symfony/sweego-mailer', 'mailer.transport_factory.sweego'], ]; - foreach ($classToServices as $class => $service) { - $package = substr($service, \strlen('mailer.transport_factory.')); - - if (!ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-mailer', 'gmail' === $package ? 'google' : $package), $class, ['symfony/framework-bundle', 'symfony/mailer'])) { + foreach ($classToServices as $class => [$package, $service]) { + if (!ContainerBuilder::willBeAvailable($package, $class, ['symfony/framework-bundle', 'symfony/mailer'])) { $container->removeDefinition($service); } } if ($webhookEnabled) { $webhookRequestParsers = [ - MailerBridge\AhaSend\Webhook\AhaSendRequestParser::class => 'mailer.webhook.request_parser.ahasend', - MailerBridge\Brevo\Webhook\BrevoRequestParser::class => 'mailer.webhook.request_parser.brevo', - MailerBridge\MailerSend\Webhook\MailerSendRequestParser::class => 'mailer.webhook.request_parser.mailersend', - MailerBridge\Mailchimp\Webhook\MailchimpRequestParser::class => 'mailer.webhook.request_parser.mailchimp', - MailerBridge\Mailgun\Webhook\MailgunRequestParser::class => 'mailer.webhook.request_parser.mailgun', - MailerBridge\Mailjet\Webhook\MailjetRequestParser::class => 'mailer.webhook.request_parser.mailjet', - MailerBridge\Mailomat\Webhook\MailomatRequestParser::class => 'mailer.webhook.request_parser.mailomat', - MailerBridge\Postmark\Webhook\PostmarkRequestParser::class => 'mailer.webhook.request_parser.postmark', - MailerBridge\Mailtrap\Webhook\MailtrapRequestParser::class => 'mailer.webhook.request_parser.mailtrap', - MailerBridge\Resend\Webhook\ResendRequestParser::class => 'mailer.webhook.request_parser.resend', - MailerBridge\Sendgrid\Webhook\SendgridRequestParser::class => 'mailer.webhook.request_parser.sendgrid', - MailerBridge\Sweego\Webhook\SweegoRequestParser::class => 'mailer.webhook.request_parser.sweego', + MailerBridge\AhaSend\Webhook\AhaSendRequestParser::class => ['symfony/aha-send-mailer', 'mailer.webhook.request_parser.ahasend'], + MailerBridge\Brevo\Webhook\BrevoRequestParser::class => ['symfony/brevo-mailer', 'mailer.webhook.request_parser.brevo'], + MailerBridge\MailerSend\Webhook\MailerSendRequestParser::class => ['symfony/mailer-send-mailer', 'mailer.webhook.request_parser.mailersend'], + MailerBridge\Mailchimp\Webhook\MailchimpRequestParser::class => ['symfony/mailchimp-mailer', 'mailer.webhook.request_parser.mailchimp'], + MailerBridge\Mailgun\Webhook\MailgunRequestParser::class => ['symfony/mailgun-mailer', 'mailer.webhook.request_parser.mailgun'], + MailerBridge\Mailjet\Webhook\MailjetRequestParser::class => ['symfony/mailjet-mailer', 'mailer.webhook.request_parser.mailjet'], + MailerBridge\Mailomat\Webhook\MailomatRequestParser::class => ['symfony/mailomat-mailer', 'mailer.webhook.request_parser.mailomat'], + MailerBridge\Postmark\Webhook\PostmarkRequestParser::class => ['symfony/postmark-mailer', 'mailer.webhook.request_parser.postmark'], + MailerBridge\Mailtrap\Webhook\MailtrapRequestParser::class => ['symfony/mailtrap-mailer', 'mailer.webhook.request_parser.mailtrap'], + MailerBridge\Resend\Webhook\ResendRequestParser::class => ['symfony/resend-mailer', 'mailer.webhook.request_parser.resend'], + MailerBridge\Sendgrid\Webhook\SendgridRequestParser::class => ['symfony/sendgrid-mailer', 'mailer.webhook.request_parser.sendgrid'], + MailerBridge\Sweego\Webhook\SweegoRequestParser::class => ['symfony/sweego-mailer', 'mailer.webhook.request_parser.sweego'], ]; - foreach ($webhookRequestParsers as $class => $service) { - $package = substr($service, \strlen('mailer.webhook.request_parser.')); - - if (!ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-mailer', 'gmail' === $package ? 'google' : $package), $class, ['symfony/framework-bundle', 'symfony/mailer'])) { + foreach ($webhookRequestParsers as $class => [$package, $service]) { + if (!ContainerBuilder::willBeAvailable($package, $class, ['symfony/framework-bundle', 'symfony/mailer'])) { $container->removeDefinition($service); } } From bee8c3f0a8f7e08e6b940f62a3d248b4d13fbc7f Mon Sep 17 00:00:00 2001 From: Ousama Ben Younes Date: Sat, 25 Apr 2026 20:58:41 +0000 Subject: [PATCH 15/17] [FrameworkBundle] Apply tagged MIME type guessers in File::getMimeType() --- FrameworkBundle.php | 6 +++ .../MimeType/CustomMimeTypeGuesser.php | 29 ++++++++++++ Tests/Functional/MimeTypeGuesserBootTest.php | 47 +++++++++++++++++++ Tests/Functional/app/MimeType/bundles.php | 18 +++++++ Tests/Functional/app/MimeType/config.yml | 3 ++ Tests/Functional/app/MimeType/services.yml | 6 +++ 6 files changed, 109 insertions(+) create mode 100644 Tests/Functional/Bundle/TestBundle/MimeType/CustomMimeTypeGuesser.php create mode 100644 Tests/Functional/MimeTypeGuesserBootTest.php create mode 100644 Tests/Functional/app/MimeType/bundles.php create mode 100644 Tests/Functional/app/MimeType/config.yml create mode 100644 Tests/Functional/app/MimeType/services.yml diff --git a/FrameworkBundle.php b/FrameworkBundle.php index c371d10db..bfecc96f9 100644 --- a/FrameworkBundle.php +++ b/FrameworkBundle.php @@ -123,6 +123,12 @@ public function boot() if ($this->container->hasParameter('kernel.trust_x_sendfile_type_header') && $this->container->getParameter('kernel.trust_x_sendfile_type_header')) { BinaryFileResponse::trustXSendfileTypeHeader(); } + + // Instantiate the mime_types service so its setDefault() call fires. + // The service is made public by AddMimeTypeGuesserPass only when custom guessers are tagged. + if ($this->container->has('mime_types')) { + $this->container->get('mime_types'); + } } /** diff --git a/Tests/Functional/Bundle/TestBundle/MimeType/CustomMimeTypeGuesser.php b/Tests/Functional/Bundle/TestBundle/MimeType/CustomMimeTypeGuesser.php new file mode 100644 index 000000000..97451a7ef --- /dev/null +++ b/Tests/Functional/Bundle/TestBundle/MimeType/CustomMimeTypeGuesser.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\MimeType; + +use Symfony\Component\Mime\MimeTypeGuesserInterface; + +class CustomMimeTypeGuesser implements MimeTypeGuesserInterface +{ + public const FAKE_MIME_TYPE = 'application/x-test-custom-guesser'; + + public function isGuesserSupported(): bool + { + return true; + } + + public function guessMimeType(string $path): ?string + { + return self::FAKE_MIME_TYPE; + } +} diff --git a/Tests/Functional/MimeTypeGuesserBootTest.php b/Tests/Functional/MimeTypeGuesserBootTest.php new file mode 100644 index 000000000..4cf170842 --- /dev/null +++ b/Tests/Functional/MimeTypeGuesserBootTest.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; + +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\MimeType\CustomMimeTypeGuesser; +use Symfony\Component\Mime\MimeTypes; + +/** + * @group functional + */ +class MimeTypeGuesserBootTest extends AbstractWebTestCase +{ + /** + * Verifies that booting the kernel eagerly instantiates the "mime_types" service, + * so that MimeTypes::setDefault() fires before any code calls MimeTypes::getDefault(). + * + * Without this, File::getMimeType() (and any other static call site) silently + * falls back to a fresh, default-only MimeTypes instance, dropping every guesser + * tagged "mime.mime_type_guesser" in the container. + */ + public function testCustomGuesserIsAppliedAfterKernelBootEvenWithoutExplicitContainerLookup() + { + // Reset the MimeTypes static default so any prior test cannot leak its instance + // into this one. Replace it with a fresh, default-only MimeTypes — mimicking the + // "no DI container has touched it yet" runtime state described in the bug report. + $defaultProperty = new \ReflectionProperty(MimeTypes::class, 'default'); + $defaultProperty->setValue(null, new MimeTypes()); + + $kernel = static::createKernel(['test_case' => 'MimeType', 'root_config' => 'config.yml']); + $kernel->boot(); + + // Intentionally do NOT call $kernel->getContainer()->get('mime_types') — + // the bug being covered is that nothing in the request lifecycle fetches + // it, leaving MimeTypes::getDefault() pointing at a fresh, default-only + // instance that ignores every container-tagged guesser. + $this->assertSame(CustomMimeTypeGuesser::FAKE_MIME_TYPE, MimeTypes::getDefault()->guessMimeType(__FILE__)); + } +} diff --git a/Tests/Functional/app/MimeType/bundles.php b/Tests/Functional/app/MimeType/bundles.php new file mode 100644 index 000000000..15ff182c6 --- /dev/null +++ b/Tests/Functional/app/MimeType/bundles.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle; + +return [ + new FrameworkBundle(), + new TestBundle(), +]; diff --git a/Tests/Functional/app/MimeType/config.yml b/Tests/Functional/app/MimeType/config.yml new file mode 100644 index 000000000..0074474a0 --- /dev/null +++ b/Tests/Functional/app/MimeType/config.yml @@ -0,0 +1,3 @@ +imports: + - { resource: ../config/default.yml } + - { resource: services.yml } diff --git a/Tests/Functional/app/MimeType/services.yml b/Tests/Functional/app/MimeType/services.yml new file mode 100644 index 000000000..d6c7e3846 --- /dev/null +++ b/Tests/Functional/app/MimeType/services.yml @@ -0,0 +1,6 @@ +services: + _defaults: + public: true + + Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\MimeType\CustomMimeTypeGuesser: + tags: ['mime.mime_type_guesser'] From b147918db04b0d823e551b01a7a4f342e415baa5 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 29 Apr 2026 19:11:44 +0200 Subject: [PATCH 16/17] [FrameworkBundle][TwigBridge] Bump symfony/mime requirement --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index c3aab8455..242009a7c 100644 --- a/composer.json +++ b/composer.json @@ -53,7 +53,7 @@ "symfony/lock": "^5.4|^6.0|^7.0", "symfony/mailer": "^5.4|^6.0|^7.0", "symfony/messenger": "^6.3|^7.0", - "symfony/mime": "^6.4|^7.0", + "symfony/mime": "^6.4.37|^7.4.9", "symfony/notifier": "^5.4|^6.0|^7.0", "symfony/process": "^5.4|^6.0|^7.0", "symfony/rate-limiter": "^5.4|^6.0|^7.0", @@ -90,7 +90,7 @@ "symfony/lock": "<5.4", "symfony/mailer": "<5.4", "symfony/messenger": "<6.3", - "symfony/mime": "<6.4", + "symfony/mime": "<6.4.37|>=7.0,<7.4.9", "symfony/property-info": "<5.4", "symfony/property-access": "<5.4", "symfony/runtime": "<5.4.45|>=6.0,<6.4.13|>=7.0,<7.1.6", From 601423cc0af2eb5e8c4acdf21fed553d456ff802 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 30 Apr 2026 10:56:51 +0200 Subject: [PATCH 17/17] [FrameworkBundle] Declare composer package next to notifier services Mirrors PR #64023 for the mailer: the composer package name is now declared explicitly alongside each notifier service id instead of being derived from the service id, guarding against future drift between service ids and bridge package names. --- DependencyInjection/FrameworkExtension.php | 188 ++++++++++----------- 1 file changed, 92 insertions(+), 96 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 48a253a0d..7fd6b1dea 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -3241,105 +3241,103 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ ->addTag('texter.transport_factory'); $classToServices = [ - NotifierBridge\AllMySms\AllMySmsTransportFactory::class => 'notifier.transport_factory.all-my-sms', - NotifierBridge\AmazonSns\AmazonSnsTransportFactory::class => 'notifier.transport_factory.amazon-sns', - NotifierBridge\Bandwidth\BandwidthTransportFactory::class => 'notifier.transport_factory.bandwidth', - NotifierBridge\Bluesky\BlueskyTransportFactory::class => 'notifier.transport_factory.bluesky', - NotifierBridge\Brevo\BrevoTransportFactory::class => 'notifier.transport_factory.brevo', - NotifierBridge\Chatwork\ChatworkTransportFactory::class => 'notifier.transport_factory.chatwork', - NotifierBridge\Clickatell\ClickatellTransportFactory::class => 'notifier.transport_factory.clickatell', - NotifierBridge\ClickSend\ClickSendTransportFactory::class => 'notifier.transport_factory.click-send', - NotifierBridge\ContactEveryone\ContactEveryoneTransportFactory::class => 'notifier.transport_factory.contact-everyone', - NotifierBridge\Discord\DiscordTransportFactory::class => 'notifier.transport_factory.discord', - NotifierBridge\Engagespot\EngagespotTransportFactory::class => 'notifier.transport_factory.engagespot', - NotifierBridge\Esendex\EsendexTransportFactory::class => 'notifier.transport_factory.esendex', - NotifierBridge\Expo\ExpoTransportFactory::class => 'notifier.transport_factory.expo', - NotifierBridge\Firebase\FirebaseTransportFactory::class => 'notifier.transport_factory.firebase', - NotifierBridge\FortySixElks\FortySixElksTransportFactory::class => 'notifier.transport_factory.forty-six-elks', - NotifierBridge\FreeMobile\FreeMobileTransportFactory::class => 'notifier.transport_factory.free-mobile', - NotifierBridge\GatewayApi\GatewayApiTransportFactory::class => 'notifier.transport_factory.gateway-api', - NotifierBridge\GoIp\GoIpTransportFactory::class => 'notifier.transport_factory.go-ip', - NotifierBridge\GoogleChat\GoogleChatTransportFactory::class => 'notifier.transport_factory.google-chat', - NotifierBridge\Infobip\InfobipTransportFactory::class => 'notifier.transport_factory.infobip', - NotifierBridge\Iqsms\IqsmsTransportFactory::class => 'notifier.transport_factory.iqsms', - NotifierBridge\Isendpro\IsendproTransportFactory::class => 'notifier.transport_factory.isendpro', - NotifierBridge\JoliNotif\JoliNotifTransportFactory::class => 'notifier.transport_factory.joli-notif', - NotifierBridge\KazInfoTeh\KazInfoTehTransportFactory::class => 'notifier.transport_factory.kaz-info-teh', - NotifierBridge\LightSms\LightSmsTransportFactory::class => 'notifier.transport_factory.light-sms', - NotifierBridge\LineBot\LineBotTransportFactory::class => 'notifier.transport_factory.line-bot', - NotifierBridge\LineNotify\LineNotifyTransportFactory::class => 'notifier.transport_factory.line-notify', - NotifierBridge\LinkedIn\LinkedInTransportFactory::class => 'notifier.transport_factory.linked-in', - NotifierBridge\Lox24\Lox24TransportFactory::class => 'notifier.transport_factory.lox24', - NotifierBridge\Mailjet\MailjetTransportFactory::class => 'notifier.transport_factory.mailjet', - NotifierBridge\Mastodon\MastodonTransportFactory::class => 'notifier.transport_factory.mastodon', - NotifierBridge\Matrix\MatrixTransportFactory::class => 'notifier.transport_factory.matrix', - NotifierBridge\Mattermost\MattermostTransportFactory::class => 'notifier.transport_factory.mattermost', - NotifierBridge\Mercure\MercureTransportFactory::class => 'notifier.transport_factory.mercure', - NotifierBridge\MessageBird\MessageBirdTransportFactory::class => 'notifier.transport_factory.message-bird', - NotifierBridge\MessageMedia\MessageMediaTransportFactory::class => 'notifier.transport_factory.message-media', - NotifierBridge\MicrosoftTeams\MicrosoftTeamsTransportFactory::class => 'notifier.transport_factory.microsoft-teams', - NotifierBridge\Mobyt\MobytTransportFactory::class => 'notifier.transport_factory.mobyt', - NotifierBridge\Novu\NovuTransportFactory::class => 'notifier.transport_factory.novu', - NotifierBridge\Ntfy\NtfyTransportFactory::class => 'notifier.transport_factory.ntfy', - NotifierBridge\Octopush\OctopushTransportFactory::class => 'notifier.transport_factory.octopush', - NotifierBridge\OneSignal\OneSignalTransportFactory::class => 'notifier.transport_factory.one-signal', - NotifierBridge\OrangeSms\OrangeSmsTransportFactory::class => 'notifier.transport_factory.orange-sms', - NotifierBridge\OvhCloud\OvhCloudTransportFactory::class => 'notifier.transport_factory.ovh-cloud', - NotifierBridge\PagerDuty\PagerDutyTransportFactory::class => 'notifier.transport_factory.pager-duty', - NotifierBridge\Plivo\PlivoTransportFactory::class => 'notifier.transport_factory.plivo', - NotifierBridge\Primotexto\PrimotextoTransportFactory::class => 'notifier.transport_factory.primotexto', - NotifierBridge\Pushover\PushoverTransportFactory::class => 'notifier.transport_factory.pushover', - NotifierBridge\Pushy\PushyTransportFactory::class => 'notifier.transport_factory.pushy', - NotifierBridge\Redlink\RedlinkTransportFactory::class => 'notifier.transport_factory.redlink', - NotifierBridge\RingCentral\RingCentralTransportFactory::class => 'notifier.transport_factory.ring-central', - NotifierBridge\RocketChat\RocketChatTransportFactory::class => 'notifier.transport_factory.rocket-chat', - NotifierBridge\Sendberry\SendberryTransportFactory::class => 'notifier.transport_factory.sendberry', - NotifierBridge\Sipgate\SipgateTransportFactory::class => 'notifier.transport_factory.sipgate', - NotifierBridge\SimpleTextin\SimpleTextinTransportFactory::class => 'notifier.transport_factory.simple-textin', - NotifierBridge\Sevenio\SevenIoTransportFactory::class => 'notifier.transport_factory.sevenio', - NotifierBridge\Sinch\SinchTransportFactory::class => 'notifier.transport_factory.sinch', - NotifierBridge\Slack\SlackTransportFactory::class => 'notifier.transport_factory.slack', - NotifierBridge\Sms77\Sms77TransportFactory::class => 'notifier.transport_factory.sms77', - NotifierBridge\Smsapi\SmsapiTransportFactory::class => 'notifier.transport_factory.smsapi', - NotifierBridge\SmsBiuras\SmsBiurasTransportFactory::class => 'notifier.transport_factory.sms-biuras', - NotifierBridge\Smsbox\SmsboxTransportFactory::class => 'notifier.transport_factory.smsbox', - NotifierBridge\Smsc\SmscTransportFactory::class => 'notifier.transport_factory.smsc', - NotifierBridge\SmsFactor\SmsFactorTransportFactory::class => 'notifier.transport_factory.sms-factor', - NotifierBridge\Smsmode\SmsmodeTransportFactory::class => 'notifier.transport_factory.smsmode', - NotifierBridge\SmsSluzba\SmsSluzbaTransportFactory::class => 'notifier.transport_factory.sms-sluzba', - NotifierBridge\Smsense\SmsenseTransportFactory::class => 'notifier.transport_factory.smsense', - NotifierBridge\SpotHit\SpotHitTransportFactory::class => 'notifier.transport_factory.spot-hit', - NotifierBridge\Sweego\SweegoTransportFactory::class => 'notifier.transport_factory.sweego', - NotifierBridge\Telegram\TelegramTransportFactory::class => 'notifier.transport_factory.telegram', - NotifierBridge\Telnyx\TelnyxTransportFactory::class => 'notifier.transport_factory.telnyx', - NotifierBridge\Termii\TermiiTransportFactory::class => 'notifier.transport_factory.termii', - NotifierBridge\TurboSms\TurboSmsTransportFactory::class => 'notifier.transport_factory.turbo-sms', - NotifierBridge\Twilio\TwilioTransportFactory::class => 'notifier.transport_factory.twilio', - NotifierBridge\Twitter\TwitterTransportFactory::class => 'notifier.transport_factory.twitter', - NotifierBridge\Unifonic\UnifonicTransportFactory::class => 'notifier.transport_factory.unifonic', - NotifierBridge\Vonage\VonageTransportFactory::class => 'notifier.transport_factory.vonage', - NotifierBridge\Yunpian\YunpianTransportFactory::class => 'notifier.transport_factory.yunpian', - NotifierBridge\Zendesk\ZendeskTransportFactory::class => 'notifier.transport_factory.zendesk', - NotifierBridge\Zulip\ZulipTransportFactory::class => 'notifier.transport_factory.zulip', + NotifierBridge\AllMySms\AllMySmsTransportFactory::class => ['symfony/all-my-sms-notifier', 'notifier.transport_factory.all-my-sms'], + NotifierBridge\AmazonSns\AmazonSnsTransportFactory::class => ['symfony/amazon-sns-notifier', 'notifier.transport_factory.amazon-sns'], + NotifierBridge\Bandwidth\BandwidthTransportFactory::class => ['symfony/bandwidth-notifier', 'notifier.transport_factory.bandwidth'], + NotifierBridge\Bluesky\BlueskyTransportFactory::class => ['symfony/bluesky-notifier', 'notifier.transport_factory.bluesky'], + NotifierBridge\Brevo\BrevoTransportFactory::class => ['symfony/brevo-notifier', 'notifier.transport_factory.brevo'], + NotifierBridge\Chatwork\ChatworkTransportFactory::class => ['symfony/chatwork-notifier', 'notifier.transport_factory.chatwork'], + NotifierBridge\Clickatell\ClickatellTransportFactory::class => ['symfony/clickatell-notifier', 'notifier.transport_factory.clickatell'], + NotifierBridge\ClickSend\ClickSendTransportFactory::class => ['symfony/click-send-notifier', 'notifier.transport_factory.click-send'], + NotifierBridge\ContactEveryone\ContactEveryoneTransportFactory::class => ['symfony/contact-everyone-notifier', 'notifier.transport_factory.contact-everyone'], + NotifierBridge\Discord\DiscordTransportFactory::class => ['symfony/discord-notifier', 'notifier.transport_factory.discord'], + NotifierBridge\Engagespot\EngagespotTransportFactory::class => ['symfony/engagespot-notifier', 'notifier.transport_factory.engagespot'], + NotifierBridge\Esendex\EsendexTransportFactory::class => ['symfony/esendex-notifier', 'notifier.transport_factory.esendex'], + NotifierBridge\Expo\ExpoTransportFactory::class => ['symfony/expo-notifier', 'notifier.transport_factory.expo'], + NotifierBridge\Firebase\FirebaseTransportFactory::class => ['symfony/firebase-notifier', 'notifier.transport_factory.firebase'], + NotifierBridge\FortySixElks\FortySixElksTransportFactory::class => ['symfony/forty-six-elks-notifier', 'notifier.transport_factory.forty-six-elks'], + NotifierBridge\FreeMobile\FreeMobileTransportFactory::class => ['symfony/free-mobile-notifier', 'notifier.transport_factory.free-mobile'], + NotifierBridge\GatewayApi\GatewayApiTransportFactory::class => ['symfony/gateway-api-notifier', 'notifier.transport_factory.gateway-api'], + NotifierBridge\GoIp\GoIpTransportFactory::class => ['symfony/go-ip-notifier', 'notifier.transport_factory.go-ip'], + NotifierBridge\GoogleChat\GoogleChatTransportFactory::class => ['symfony/google-chat-notifier', 'notifier.transport_factory.google-chat'], + NotifierBridge\Infobip\InfobipTransportFactory::class => ['symfony/infobip-notifier', 'notifier.transport_factory.infobip'], + NotifierBridge\Iqsms\IqsmsTransportFactory::class => ['symfony/iqsms-notifier', 'notifier.transport_factory.iqsms'], + NotifierBridge\Isendpro\IsendproTransportFactory::class => ['symfony/isendpro-notifier', 'notifier.transport_factory.isendpro'], + NotifierBridge\JoliNotif\JoliNotifTransportFactory::class => ['symfony/joli-notif-notifier', 'notifier.transport_factory.joli-notif'], + NotifierBridge\KazInfoTeh\KazInfoTehTransportFactory::class => ['symfony/kaz-info-teh-notifier', 'notifier.transport_factory.kaz-info-teh'], + NotifierBridge\LightSms\LightSmsTransportFactory::class => ['symfony/light-sms-notifier', 'notifier.transport_factory.light-sms'], + NotifierBridge\LineBot\LineBotTransportFactory::class => ['symfony/line-bot-notifier', 'notifier.transport_factory.line-bot'], + NotifierBridge\LineNotify\LineNotifyTransportFactory::class => ['symfony/line-notify-notifier', 'notifier.transport_factory.line-notify'], + NotifierBridge\LinkedIn\LinkedInTransportFactory::class => ['symfony/linked-in-notifier', 'notifier.transport_factory.linked-in'], + NotifierBridge\Lox24\Lox24TransportFactory::class => ['symfony/lox24-notifier', 'notifier.transport_factory.lox24'], + NotifierBridge\Mailjet\MailjetTransportFactory::class => ['symfony/mailjet-notifier', 'notifier.transport_factory.mailjet'], + NotifierBridge\Mastodon\MastodonTransportFactory::class => ['symfony/mastodon-notifier', 'notifier.transport_factory.mastodon'], + NotifierBridge\Matrix\MatrixTransportFactory::class => ['symfony/matrix-notifier', 'notifier.transport_factory.matrix'], + NotifierBridge\Mattermost\MattermostTransportFactory::class => ['symfony/mattermost-notifier', 'notifier.transport_factory.mattermost'], + NotifierBridge\Mercure\MercureTransportFactory::class => ['symfony/mercure-notifier', 'notifier.transport_factory.mercure'], + NotifierBridge\MessageBird\MessageBirdTransportFactory::class => ['symfony/message-bird-notifier', 'notifier.transport_factory.message-bird'], + NotifierBridge\MessageMedia\MessageMediaTransportFactory::class => ['symfony/message-media-notifier', 'notifier.transport_factory.message-media'], + NotifierBridge\MicrosoftTeams\MicrosoftTeamsTransportFactory::class => ['symfony/microsoft-teams-notifier', 'notifier.transport_factory.microsoft-teams'], + NotifierBridge\Mobyt\MobytTransportFactory::class => ['symfony/mobyt-notifier', 'notifier.transport_factory.mobyt'], + NotifierBridge\Novu\NovuTransportFactory::class => ['symfony/novu-notifier', 'notifier.transport_factory.novu'], + NotifierBridge\Ntfy\NtfyTransportFactory::class => ['symfony/ntfy-notifier', 'notifier.transport_factory.ntfy'], + NotifierBridge\Octopush\OctopushTransportFactory::class => ['symfony/octopush-notifier', 'notifier.transport_factory.octopush'], + NotifierBridge\OneSignal\OneSignalTransportFactory::class => ['symfony/one-signal-notifier', 'notifier.transport_factory.one-signal'], + NotifierBridge\OrangeSms\OrangeSmsTransportFactory::class => ['symfony/orange-sms-notifier', 'notifier.transport_factory.orange-sms'], + NotifierBridge\OvhCloud\OvhCloudTransportFactory::class => ['symfony/ovh-cloud-notifier', 'notifier.transport_factory.ovh-cloud'], + NotifierBridge\PagerDuty\PagerDutyTransportFactory::class => ['symfony/pager-duty-notifier', 'notifier.transport_factory.pager-duty'], + NotifierBridge\Plivo\PlivoTransportFactory::class => ['symfony/plivo-notifier', 'notifier.transport_factory.plivo'], + NotifierBridge\Primotexto\PrimotextoTransportFactory::class => ['symfony/primotexto-notifier', 'notifier.transport_factory.primotexto'], + NotifierBridge\Pushover\PushoverTransportFactory::class => ['symfony/pushover-notifier', 'notifier.transport_factory.pushover'], + NotifierBridge\Pushy\PushyTransportFactory::class => ['symfony/pushy-notifier', 'notifier.transport_factory.pushy'], + NotifierBridge\Redlink\RedlinkTransportFactory::class => ['symfony/redlink-notifier', 'notifier.transport_factory.redlink'], + NotifierBridge\RingCentral\RingCentralTransportFactory::class => ['symfony/ring-central-notifier', 'notifier.transport_factory.ring-central'], + NotifierBridge\RocketChat\RocketChatTransportFactory::class => ['symfony/rocket-chat-notifier', 'notifier.transport_factory.rocket-chat'], + NotifierBridge\Sendberry\SendberryTransportFactory::class => ['symfony/sendberry-notifier', 'notifier.transport_factory.sendberry'], + NotifierBridge\Sipgate\SipgateTransportFactory::class => ['symfony/sipgate-notifier', 'notifier.transport_factory.sipgate'], + NotifierBridge\SimpleTextin\SimpleTextinTransportFactory::class => ['symfony/simple-textin-notifier', 'notifier.transport_factory.simple-textin'], + NotifierBridge\Sevenio\SevenIoTransportFactory::class => ['symfony/sevenio-notifier', 'notifier.transport_factory.sevenio'], + NotifierBridge\Sinch\SinchTransportFactory::class => ['symfony/sinch-notifier', 'notifier.transport_factory.sinch'], + NotifierBridge\Slack\SlackTransportFactory::class => ['symfony/slack-notifier', 'notifier.transport_factory.slack'], + NotifierBridge\Sms77\Sms77TransportFactory::class => ['symfony/sms77-notifier', 'notifier.transport_factory.sms77'], + NotifierBridge\Smsapi\SmsapiTransportFactory::class => ['symfony/smsapi-notifier', 'notifier.transport_factory.smsapi'], + NotifierBridge\SmsBiuras\SmsBiurasTransportFactory::class => ['symfony/sms-biuras-notifier', 'notifier.transport_factory.sms-biuras'], + NotifierBridge\Smsbox\SmsboxTransportFactory::class => ['symfony/smsbox-notifier', 'notifier.transport_factory.smsbox'], + NotifierBridge\Smsc\SmscTransportFactory::class => ['symfony/smsc-notifier', 'notifier.transport_factory.smsc'], + NotifierBridge\SmsFactor\SmsFactorTransportFactory::class => ['symfony/sms-factor-notifier', 'notifier.transport_factory.sms-factor'], + NotifierBridge\Smsmode\SmsmodeTransportFactory::class => ['symfony/smsmode-notifier', 'notifier.transport_factory.smsmode'], + NotifierBridge\SmsSluzba\SmsSluzbaTransportFactory::class => ['symfony/sms-sluzba-notifier', 'notifier.transport_factory.sms-sluzba'], + NotifierBridge\Smsense\SmsenseTransportFactory::class => ['symfony/smsense-notifier', 'notifier.transport_factory.smsense'], + NotifierBridge\SpotHit\SpotHitTransportFactory::class => ['symfony/spot-hit-notifier', 'notifier.transport_factory.spot-hit'], + NotifierBridge\Sweego\SweegoTransportFactory::class => ['symfony/sweego-notifier', 'notifier.transport_factory.sweego'], + NotifierBridge\Telegram\TelegramTransportFactory::class => ['symfony/telegram-notifier', 'notifier.transport_factory.telegram'], + NotifierBridge\Telnyx\TelnyxTransportFactory::class => ['symfony/telnyx-notifier', 'notifier.transport_factory.telnyx'], + NotifierBridge\Termii\TermiiTransportFactory::class => ['symfony/termii-notifier', 'notifier.transport_factory.termii'], + NotifierBridge\TurboSms\TurboSmsTransportFactory::class => ['symfony/turbo-sms-notifier', 'notifier.transport_factory.turbo-sms'], + NotifierBridge\Twilio\TwilioTransportFactory::class => ['symfony/twilio-notifier', 'notifier.transport_factory.twilio'], + NotifierBridge\Twitter\TwitterTransportFactory::class => ['symfony/twitter-notifier', 'notifier.transport_factory.twitter'], + NotifierBridge\Unifonic\UnifonicTransportFactory::class => ['symfony/unifonic-notifier', 'notifier.transport_factory.unifonic'], + NotifierBridge\Vonage\VonageTransportFactory::class => ['symfony/vonage-notifier', 'notifier.transport_factory.vonage'], + NotifierBridge\Yunpian\YunpianTransportFactory::class => ['symfony/yunpian-notifier', 'notifier.transport_factory.yunpian'], + NotifierBridge\Zendesk\ZendeskTransportFactory::class => ['symfony/zendesk-notifier', 'notifier.transport_factory.zendesk'], + NotifierBridge\Zulip\ZulipTransportFactory::class => ['symfony/zulip-notifier', 'notifier.transport_factory.zulip'], ]; $parentPackages = ['symfony/framework-bundle', 'symfony/notifier']; - foreach ($classToServices as $class => $service) { - $package = substr($service, \strlen('notifier.transport_factory.')); - - if (!ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-notifier', $package), $class, $parentPackages)) { + foreach ($classToServices as $class => [$package, $service]) { + if (!ContainerBuilder::willBeAvailable($package, $class, $parentPackages)) { $container->removeDefinition($service); } } if (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', NotifierBridge\Mercure\MercureTransportFactory::class, $parentPackages) && ContainerBuilder::willBeAvailable('symfony/mercure-bundle', MercureBundle::class, $parentPackages) && \in_array(MercureBundle::class, $container->getParameter('kernel.bundles'), true)) { - $container->getDefinition($classToServices[NotifierBridge\Mercure\MercureTransportFactory::class]) + $container->getDefinition('notifier.transport_factory.mercure') ->replaceArgument(0, new Reference(HubRegistry::class)) ->replaceArgument(1, new Reference('event_dispatcher', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) ->addArgument(new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); } elseif (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', NotifierBridge\Mercure\MercureTransportFactory::class, $parentPackages)) { - $container->removeDefinition($classToServices[NotifierBridge\Mercure\MercureTransportFactory::class]); + $container->removeDefinition('notifier.transport_factory.mercure'); } // don't use ContainerBuilder::willBeAvailable() as these are not needed in production @@ -3365,7 +3363,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ } if (ContainerBuilder::willBeAvailable('symfony/bluesky-notifier', NotifierBridge\Bluesky\BlueskyTransportFactory::class, ['symfony/framework-bundle', 'symfony/notifier'])) { - $container->getDefinition($classToServices[NotifierBridge\Bluesky\BlueskyTransportFactory::class]) + $container->getDefinition('notifier.transport_factory.bluesky') ->addArgument(new Reference('logger')) ->addArgument(new Reference('clock', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); } @@ -3383,17 +3381,15 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ $loader->load('notifier_webhook.php'); $webhookRequestParsers = [ - NotifierBridge\Lox24\Webhook\Lox24RequestParser::class => 'notifier.webhook.request_parser.lox24', - NotifierBridge\Smsbox\Webhook\SmsboxRequestParser::class => 'notifier.webhook.request_parser.smsbox', - NotifierBridge\Sweego\Webhook\SweegoRequestParser::class => 'notifier.webhook.request_parser.sweego', - NotifierBridge\Twilio\Webhook\TwilioRequestParser::class => 'notifier.webhook.request_parser.twilio', - NotifierBridge\Vonage\Webhook\VonageRequestParser::class => 'notifier.webhook.request_parser.vonage', + NotifierBridge\Lox24\Webhook\Lox24RequestParser::class => ['symfony/lox24-notifier', 'notifier.webhook.request_parser.lox24'], + NotifierBridge\Smsbox\Webhook\SmsboxRequestParser::class => ['symfony/smsbox-notifier', 'notifier.webhook.request_parser.smsbox'], + NotifierBridge\Sweego\Webhook\SweegoRequestParser::class => ['symfony/sweego-notifier', 'notifier.webhook.request_parser.sweego'], + NotifierBridge\Twilio\Webhook\TwilioRequestParser::class => ['symfony/twilio-notifier', 'notifier.webhook.request_parser.twilio'], + NotifierBridge\Vonage\Webhook\VonageRequestParser::class => ['symfony/vonage-notifier', 'notifier.webhook.request_parser.vonage'], ]; - foreach ($webhookRequestParsers as $class => $service) { - $package = substr($service, \strlen('notifier.webhook.request_parser.')); - - if (!ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-notifier', $package), $class, ['symfony/framework-bundle', 'symfony/notifier'])) { + foreach ($webhookRequestParsers as $class => [$package, $service]) { + if (!ContainerBuilder::willBeAvailable($package, $class, ['symfony/framework-bundle', 'symfony/notifier'])) { $container->removeDefinition($service); } }